前面讲了服务的注册和发现,在微服务架构中,业务会被拆分成一个个的微服务,服务与服务又是如何通讯的?
SpringCloud中的通信协议是基于HTTP restful的,其中有两种服务调用方式,一种是ribbon+restTemplate,另一种是feign。
ribbon
ribbon是一个负载均衡客户端,可以很好的控制htt和tcp的一些行为。Feign默认集成了ribbon。
1.依赖
<dependencies>
<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-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
</dependencies>
2.配置
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
server:
port: 8763
spring:
application:
name: service-ribbon
3.代码
3.1 在工程的启动类中,通过@EnableDiscoveryClient向服务中心注册(如果使用eureka作为注册中心使用EnableEurekaClient,@EnableDiscoveryClient都可以,若使用consul等注册中心方案需使用@EnableDiscoveryClient)
@SpringBootApplication
@EnableEurekaClient
//@EnableDiscoveryClient
public class ServiceRibbonApplication {
public static void main(String[] args) {
SpringApplication.run( ServiceRibbonApplication.class, args );
}
}
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
public class ServiceRibbonApplication {
public static void main(String[] args) {
SpringApplication.run( ServiceRibbonApplication.class, args );
}
}
3.2 @Bean向程序的ioc注入一个bean: restTemplate;并通过@LoadBalanced注解表明这个restRemplate开启负载均衡的功能。
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
3.3 在SERVICE-HI服务中提供远程方法
@RestController
public class HelloControler {
@GetMapping(value = "/hi")
public String hi(@RequestParam String name) {
return helloService.hiService( name );
}
}
3.4 注入RestTemplate模版,在service中编写逻辑(远程方法调用)调用SERVICE-HI的Controller中hi方法。
@Service
public class HelloService {
@Autowired
RestTemplate restTemplate;
public String hiService(String name) {
return restTemplate.getForObject("http://SERVICE-HI/hi?name="+name,String.class);
}
}
3.5 在service-ribbon服务中提供hello接口测试远程调用SERVICE-HI服务方法。
@RestController
public class HelloControler {
@Autowired
HelloService helloService;
@GetMapping(value = "/hello")
public String hello(@RequestParam String name) {
return helloService.hiService( name );
}
}
如果SERVICE-HI服务,在注册中心上注册了多个实例,则多次调用时会交替调用服务实例,实现负载。
Feign
Feign是一个声明式的伪Http客户端,它使得写Http客户端变得更简单。使用Feign,只需要创建一个接口并注解。Feign默认集成了Ribbon,和Eureka结合默认实现负载效果。
1.依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
2.配置文件
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
server:
port: 8765
spring:
application:
name: service-feign
3.代码
3.1 在程序的启动类ServiceFeignApplication,加上@EnableFeignClients注解开启Feign的功能
如果需要将所有feignAPI接口写到maven的一个子工程里,@EnableFeignClients注解需要指明路径@EnableFeignClients(“com.api.feign”)
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class ServiceFeignApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceFeignApplication.class, args);
}
}
3.2 编写一个controller提供hello接口供外部调用
@RestController
public class HiController {
@Autowired
SchedualServiceHi schedualServiceHi;
@RequestMapping(value = "/hello",method = RequestMethod.GET)
public String sayHi(@RequestParam String name){
return schedualServiceHi.sayHiFromClientOne(name);
}
}
同ribbon,如果服务提供方开启多个实例,会使用负载依次调用其服务。
本文参考文章:方志鹏-深入理解SpringCloud与微服务构建