五分钟带你玩转springcloudNetflix(四)服务间调用
上文我们把我们项目注册到服务器上了,但是我们会使用A服务调用B服务,那么就会使用服务的调用,这里有两种方式ribbon和feign,我们分别介绍。
ribbon
ribbon说白了就是使用restTemplate。下面上代码
首先pom文件
-
<?xml version="1.0" encoding="UTF-8"?>
-
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
-
<modelVersion>4.0.0</modelVersion>
-
<parent>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-starter-parent</artifactId>
-
<version>2.2.5.RELEASE</version>
-
<relativePath/> <!-- lookup parent from repository -->
-
</parent>
-
<groupId>com.baocl</groupId>
-
<artifactId>eureka-consumer</artifactId>
-
<version>0.0.1-SNAPSHOT</version>
-
<name>eureka-consumer</name>
-
<description>Demo project for Spring Boot</description>
-
-
<properties>
-
<java.version>1.8</java.version>
-
<spring-cloud.version>Hoxton.SR1</spring-cloud.version>
-
</properties>
-
-
<dependencies>
-
<dependency>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-starter-web</artifactId>
-
</dependency>
-
<dependency>
-
<groupId>org.springframework.cloud</groupId>
-
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
-
</dependency>
-
<dependency>
-
<groupId>org.springframework.cloud</groupId>
-
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
-
</dependency>
-
<dependency>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-starter-test</artifactId>
-
<scope>test</scope>
-
<exclusions>
-
<exclusion>
-
<groupId>org.junit.vintage</groupId>
-
<artifactId>junit-vintage-engine</artifactId>
-
</exclusion>
-
</exclusions>
-
</dependency>
-
</dependencies>
-
-
<dependencyManagement>
-
<dependencies>
-
<dependency>
-
<groupId>org.springframework.cloud</groupId>
-
<artifactId>spring-cloud-dependencies</artifactId>
-
<version>${spring-cloud.version}</version>
-
<type>pom</type>
-
<scope>import</scope>
-
</dependency>
-
</dependencies>
-
</dependencyManagement>
-
-
<build>
-
<plugins>
-
<plugin>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-maven-plugin</artifactId>
-
</plugin>
-
</plugins>
-
</build>
-
-
</project>
然后EurekaConsumerApplication类
需要在新建RestTemplate的bean
-
package com.cloud;
-
-
import org.springframework.boot.SpringApplication;
-
import org.springframework.boot.autoconfigure.SpringBootApplication;
-
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
-
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
-
import org.springframework.context.annotation.Bean;
-
import org.springframework.web.client.RestTemplate;
-
-
@SpringBootApplication
-
@EnableDiscoveryClient
-
-
public class EurekaConsumerApplication {
-
-
@Bean
-
@LoadBalanced // ribbon注解
-
public RestTemplate restTemplate() {
-
return new RestTemplate();
-
}
-
-
public static void main(String[] args) {
-
SpringApplication.run(EurekaConsumerApplication.class, args);
-
}
-
-
}
DcController
新建接口 调用上文服务
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.cloud.client.discovery.DiscoveryClient;
-
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
-
import org.springframework.http.ResponseEntity;
-
import org.springframework.web.bind.annotation.GetMapping;
-
import org.springframework.web.bind.annotation.RequestMapping;
-
import org.springframework.web.bind.annotation.RestController;
-
import org.springframework.web.client.RestTemplate;
-
-
@RestController
-
@RequestMapping("/eureka1")
-
public class DcController {
-
-
@Autowired
-
LoadBalancerClient loadBalancerClient;
-
@Autowired
-
RestTemplate restTemplate;
-
@Autowired
-
DiscoveryClient discoveryClient;
-
-
@GetMapping("/consumer")
-
public ResponseEntity<String> dc() {
-
-
-
//String url = "http://eureka-client/aaa/dc?dk=3001";
-
String url = "http://EUREKA-CLIENT/aaa/dc?dk=3001";
-
System.out.println(url);
-
// ServiceInstance serviceInstance =
-
// loadBalancerClient.choose("eureka-client");// 获取服务提供者信息
-
// // String url = "http://localhost:" + serviceInstance.getPort() + "/aaa/dc";
-
// System.out.println(serviceInstance.getPort() );
-
// System.out.println(url);
-
// ResponseEntity r = restTemplate.getForEntity("http://eureka-client/aaa/dc",
-
// String.class);
-
// System.out.println("r.getHeaders().getHost():"+r.getHeaders().getHost());
-
// System.out.println("r.getHeaders().getLocation():"+r.getHeaders().getLocation());
-
// System.out.println("r.getHeaders().getOrigin():"+r.getHeaders().getOrigin());
-
return restTemplate.getForEntity(url, String.class); // ribbon应用
-
}
-
-
-
}
有一个坑 在调用时候需要
String url = "http://eureka-client/aaa/dc?dk=3001";
而不是
String url = "http://localhost:2002/aaa/dc?dk=3001";
否则会报错。
java.lang.IllegalStateException: No instances available for localhost
最后是配置文件application.yml
这里我们使用.yml文件 都是基础配置
-
eureka:
-
client:
-
registery-fetch-interval-seconds: 5000
-
serviceUrl:
-
defaultZone: http://localhost:1001/eureka/
-
eureka-client:
-
ribbon:
-
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
-
server:
-
port: 3001
-
spring:
-
application:
-
name: eureka-consumer
输入http://localhost:3001/eureka1/consumer就可以调用到上文的client服务了,同时还会使用顺序调用负载均衡策略。
feign
EurekaConsumerFeignApplication
首先在EurekaConsumerFeignApplication使用@EnableFeignClients中开启feign
-
import org.springframework.boot.SpringApplication;
-
import org.springframework.boot.autoconfigure.SpringBootApplication;
-
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
-
import org.springframework.cloud.openfeign.EnableFeignClients;
-
-
-
@EnableFeignClients
-
@EnableDiscoveryClient
-
@SpringBootApplication
-
public class EurekaConsumerFeignApplication {
-
-
public static void main(String[] args) {
-
SpringApplication.run(EurekaConsumerFeignApplication.class, args);
-
}
-
}
新建一个接口DcClient
配置调用其他服务的名称和接口名称
-
import org.springframework.cloud.openfeign.FeignClient;
-
import org.springframework.web.bind.annotation.GetMapping;
-
-
@FeignClient(name = "eureka-client")
-
public interface DcClient {
-
-
@GetMapping("/aaa/dc?dk=3002")
-
String consumer();
-
-
@GetMapping("/aaa/dc?dk=3002")
-
String consumer2();
-
}
DcController
业务接口的书写 同时注入dcClient调用其他服务
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.web.bind.annotation.GetMapping;
-
import org.springframework.web.bind.annotation.RequestMapping;
-
import org.springframework.web.bind.annotation.RestController;
-
-
import com.cloud.DcClient;
-
-
@RestController
-
@RequestMapping("/eureka2")
-
public class DcController {
-
@Autowired
-
DcClient dcClient;
-
@GetMapping("/consumer")
-
-
public String dc() {
-
return dcClient.consumer();
-
}
-
}
application.properties
基础配置
-
spring.application.name=eureka-consumer-feign
-
server.port=3002
-
eureka.client.serviceUrl.defaultZone=http://localhost:1001/eureka/
pom文件
版本问题一定要控制!!!!
-
<?xml version="1.0" encoding="UTF-8"?>
-
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
-
<modelVersion>4.0.0</modelVersion>
-
<parent>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-starter-parent</artifactId>
-
<version>2.2.5.RELEASE</version>
-
<relativePath/> <!-- lookup parent from repository -->
-
</parent>
-
<groupId>com.baocl</groupId>
-
<artifactId>eureka-consumer-feign</artifactId>
-
<version>0.0.1-SNAPSHOT</version>
-
<name>eureka-consumer-feign</name>
-
<description>Demo project for Spring Boot</description>
-
-
<properties>
-
<java.version>1.8</java.version>
-
<spring-cloud.version>Hoxton.SR1</spring-cloud.version>
-
</properties>
-
-
<dependencies>
-
<dependency>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-starter-web</artifactId>
-
</dependency>
-
<dependency>
-
<groupId>org.springframework.cloud</groupId>
-
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
-
</dependency>
-
<dependency>
-
<groupId>org.springframework.cloud</groupId>
-
<artifactId>spring-cloud-starter-feign</artifactId>
-
<version>1.4.7.RELEASE</version>
-
</dependency>
-
-
<dependency>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-starter-test</artifactId>
-
<scope>test</scope>
-
<exclusions>
-
<exclusion>
-
<groupId>org.junit.vintage</groupId>
-
<artifactId>junit-vintage-engine</artifactId>
-
</exclusion>
-
</exclusions>
-
</dependency>
-
</dependencies>
-
-
<dependencyManagement>
-
<dependencies>
-
<dependency>
-
<groupId>org.springframework.cloud</groupId>
-
<artifactId>spring-cloud-dependencies</artifactId>
-
<version>${spring-cloud.version}</version>
-
<type>pom</type>
-
<scope>import</scope>
-
</dependency>
-
</dependencies>
-
</dependencyManagement>
-
-
<build>
-
<plugins>
-
<plugin>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-maven-plugin</artifactId>
-
</plugin>
-
</plugins>
-
</build>
-
-
</project>
这里有一个坑 就是版本问题,有时会报错
org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate component class: file [F:\workspace\springcloud\tse9\eureka-consumer-feign\target\classes\com\cloud\DcClient.class]; nested exception is org.springframework.core.annotation.AnnotationConfigurationException: Attribute 'value' in annotation [org.springframework.cloud.netflix.feign.FeignClient] must be declared as an @AliasFor 'serviceId', not 'name'.
解决办法http://www.pianshen.com/article/2239869942/
然后调用http://localhost:3002/eureka2/consumer 可以发现接口掉通了 帮帮哒
ribbon和Eureka整合原理
基本流程就是 客户端从eureka中获取到缓存的服务列表,获取到目的服务的信息,然后通过自身的负载均衡策略,去调用对应的服务
负载均衡策略
BestAvailableRule 选择一个最小的并发请求的server. AvailabilityFilteringRule 过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值). WeightedResponseTimeRule 根据响应时间分配一个weight,响应时间越长,weight越小,被选中的可能性越低. RetryRule 对选定的负载均衡策略机上重试机制. RoundRobinRule roundRobin方式轮询选择server. RandomRule 随机选择一个server. ZoneAvoidanceRule 复合判断server所在区域的性能和server的可用性选择server.
文章来源: baocl.blog.csdn.net,作者:小黄鸡1992,版权归原作者所有,如需转载,请联系作者。
原文链接:baocl.blog.csdn.net/article/details/104738600
- 点赞
- 收藏
- 关注作者
评论(0)