一、springCloud微服务请求:
上篇博客说到,如何注册服务到注册中心,并且实现erueka集群,那么把服务注册到注册中心后,如何来调用这些服务呢?
(1)、最傻的方式就是直接拼接ip地址加端口号:
/**
* get请求(rest风格)
* @return
*/
@GetMapping("/getPathVariableConsumer")
public String getPathVariableConsumer(){
RestTemplate restTemplate=new RestTemplate();
Map<String,String> paramMap = new HashMap();
paramMap.put("start","1");
paramMap.put("page","5");
return restTemplate.getForObject("http://localhost:8001/getDcPathVariable/{start}/{page}",String.class,paramMap);
}
说明:
如果这样请求,那我们还用cloud干嘛呢?还不如自己写个常量类维护好这些ip地址。这样直接请求ip地址,
第一维护麻烦,还要知道其他微服务的ip地址才行
第二不能实现负载均衡,比如这个请求的目标服务部署了多个实例,那就不能均衡的访问者多个实例。
(2)、不傻但是麻烦的方式就是通过LoadBalancerClient对象的choose方法,选中当前请求服务的实例(支持负载均衡),然后通过这个实例来拼接ip地址:
/**
* post请求(loadBalancerClient)
* @return
*/
@GetMapping("/postBalancerConsumer")
public String postBalancerConsumer(){
RestTemplate restTemplate=new RestTemplate();
Map<String,String> paramMap = new HashMap();
paramMap.put("start", "1");
paramMap.put("page", "5");
//选中服务实例
ServiceInstance serviceInstance =loadBalancerClient.choose("eureka-client");
System.out.println(serviceInstance.getServiceId()+":"+serviceInstance.getPort());
String url="http://"+serviceInstance.getHost()+ ":" + serviceInstance.getPort() + "/postDcRequestBody";;
return restTemplate.postForObject(url,paramMap,String.class);
}
(3)、比较通用的方法,利用@LoadBalanced注解改造RestTemplate,使它有负载均衡的功能:
新建个配置类RestTemplateConfig ,构造一个restTemplateRibbon到spring容器:
@Configuration
public class RestTemplateConfig {
@LoadBalanced
@Bean("restTemplateRibbon")
public RestTemplate restTemplateRibbon(){
return new RestTemplate();
}
}
在调用方法里面注入restTemplateRibbon,并调用请求方法:
@Autowired
@Qualifier("restTemplateRibbon")
public RestTemplate restTemplateRibbon;
@GetMapping("/postRestTemplateRibbonConsumer")
public String postRestTemplateRibbonConsumer(){
Map<String,String> paramMap = new HashMap();
paramMap.put("start", "1");
paramMap.put("page", "5");
return this.restTemplateRibbon.postForObject("http://eureka-client/"+"/postDcRequestBody",paramMap,String.class);
}
说明:这里也需要拼接地址,但是拼接的不是ip地址,而是eureka-client:微服务在注册中心的名字,因为标注了@LoadBalanced,就实现了Ribbon的负载均衡功能,所以这里会根据一定的算法(默认是轮询),来找到合适的实例地址(eureka-client有多个实例,ip地址或者端口不同)进行请求。
(4)、上面的那种方式已经很方便了,还有更加方便的方式,通过Feign接口来实现,我们连地址拼接都不需要了:
先实现一个Feign接口:
@FeignClient(value ="eureka-client",fallback = FeignFallBack.class)
public interface FeignInterface {
@PostMapping("/postDcRequestBody")
public String postDcRequestBody(@RequestBody Map<String,String> paramMap);
@PostMapping("/postFeignClientConsumerHystrix")
public String postFeignClientConsumerHystrix();
}
说明:@FeignClient(value =“eureka-client”,fallback = FeignFallBack.class),value指向要请求的微服务名称(在注册中心的名称),fallback指向发送错误时的处理类(这个下篇讲熔断的时候再说,先不管)
然后注入这个接口,并调用接口方法:
@Autowired
public FeignInterface feignInterface;
@GetMapping("/postFeignClientConsumer")
public String postFeignClientConsumer(){
Map<String,String> paramMap = new HashMap();
paramMap.put("start", "1");
paramMap.put("page", "5");
return this.feignInterface.postDcRequestBody(paramMap);
}
Feign默认是实现了负载均衡的,所以这里调用接口方法的时候,也会根据接口里面的@FeignClient(value =“eureka-client”)选中最合适的实例去请求。
二、理解:
其实微服务相互请求,就是先把这些服务注册到同一个注册中心,这些服务都会从注册中心拉取一份微服务名单。
然后通过集成Ribbon,在消费端请求提供者端的服务(通过服务名来请求),实现负载均衡。
好处就是负载均衡分散了每个服务实例的访问压力,不需要关注每个服务的每个具体实例(ip和端口是多少),
通过服务名就可以请求到。
三、其它配置:
(1)、pom.xml
<?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>1.5.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.base</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>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</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>Dalston.SR1</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)、yml配置:
spring:
application:
name: eureka-consumer
server:
port: 9001
eureka:
client:
serviceUrl:
defaultZone: http://localhost:1001/eureka/
instance:
instance-id: ${spring.cloud.client.ipAddress}:${server.port} #设置服务在注册中心的实例id
prefer-ip-address: true
说明:将这个消费者服务也要注册到erueka服务中心(服务提供者也在这个中心).
(3)、启动类:
@EnableFeignClients :引入FeignClient
@EnableDiscoveryClient: 标注为服务客户端,便于从erueka获取服务列表。