千磨万击还坚劲,任尔东西南北风。这篇文章主要讲述多服务间的调用相关的知识,希望能为你提供帮助。
?
文章图片
上文我们把我们项目注册到服务器上了,但是在微服务中,我们会有多个服务,同时也会使用A服务调用B服务的接口。springcloud netflix这里有两种方式ribbon和feign,我们分别介绍。
1.ribbonribbon说白了就是使用restTemplate。上文编写了被调用方的代码,下文将编写调用方的代码。
1.修改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>
2.修改Application
然后修改EurekaConsumerApplication类,需要在新建RestTemplate的bean。
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);
}
}
3.新建调用方接口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应用
}
}
4.修改application
有一个坑 在调用时候需要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服务了,同时还可以配置负载均衡策略。在NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule 处配置。
2.feign 1.修改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/
2.修改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);
}
}
3.新建接口DcClient
新建一个接口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();
}
4.新建调用接口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();
}
}
5.修改application.properties
下文是最基础的配置。
spring.application.name=eureka-consumer-feign
server.port=3002
eureka.client.serviceUrl.defaultZone=http://localhost:1001/eureka/
然后调用http://localhost:3002/eureka2/consumer 可以发现接口掉通了 ,在被调用方也有相应的日志。
3.ribbon和Eureka整合原理基本流程就是 客户端从eureka中获取到缓存的服务列表,获取到目的服务的信息,然后通过自身的负载均衡策略,去调用对应的服务。
文章图片
1.负载均衡策略
- BestAvailableRule 选择一个最小的并发请求的server。
- AvailabilityFilteringRule 过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值)。
- WeightedResponseTimeRule 根据响应时间分配一个weight,响应时间越长,weight越小,被选中的可能性越低。
- RetryRule 对选定的负载均衡策略机上重试机制。
- RoundRobinRule roundRobin方式轮询选择server.。
- RandomRule 随机选择一个server。
- ZoneAvoidanceRule 复合判断server所在区域的性能和server的可用性选择server。
【多服务间的调用】
推荐阅读
- RabbitMQ怎么保证消息不丢失
- 使用navicat将mysql数据转换为postgresql
- ribbon,feign选择和与Hystrix的整合应用
- java开发的格式与书写规范
- 注册中心eureka的搭建
- 更改Apollo数据库为oracle
- 实战中反射的应用
- 使标记在woocommerce中显示为下拉列表
- 在循环WordPress中循环