上一篇文章中说明的提供者架构,
SpringCloud之提供者架构Eureka+Sleuth+RabbitMQ
本次则写消费者的和和架构,秉承我的观念,把SpringCloud的技术栈串起来,我会尽可能的把消费者设计的较完善.
消费者则使用Eureka发现服务,Eureka的注册中心之前的文章有说过,
SpringCloud之Eureka服务注册中心,服务注册和服务发现
调用provider,则使用Ribbon负载均衡,SpringCloud还提供了Feign让我们继续使用controller调用service层的技术,后面会提及到,feign和阿里巴巴的dubbo框架很类似,dubbo的使用之前的文章有说过
基于SpringBoot的dubbo+zookeeper搭建分布式
和provider类似,我们还是使用sleuth来进行服务跟踪,并把日志发布到RabbitMQ中,让Zipkin订阅分析,Zipkin文章如下
SpringCloud之提供者和消费者的日志分析Zipkin+RabbitMQ
对于调用,我们使用Hystrix进行服务容错保护,并把使用Hystrix的接口调用信息也发布到RabbitMQ中,让Turbine订阅来进行consumer数据聚集,最后交给Hystrix-dashboard进行面板展示,Turbine文章如下
SpringCloud之监控数据聚合Turbine+RabbitMQ
Hystrix-Dashboard文章如下
SpringCloud之监控面板Hystrix-Dashboard
在pom.xml中引入依赖
注意:
SpringBoot使用1.5.15
SpringCloud使用Edgware.SR4
<!--eureka+ribbon+feign+hystrix -->
<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>
<!-- 引入Eureka就引入Ribbon-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<!-- RabbitMQ + Turbine -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-hystrix-amqp</artifactId>
</dependency>
<!-- Sleuth +RabbitMQ + Zipkin -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-stream</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
在application.yml中配置如下
其中RabbitMQ的作用有两个
1.服务跟踪: sleuth–> rabbitMQ–>zipkin
2.hystrix-dashboard面板显示: stream–>rabbitMQ–>turbine
注意:
1.使用feign的服务容错,需要使用feign.hystrix.enable: true开启,不然不生效
2.日志采样使用100%,不然默认为0.1
server:
port: 9001
spring:
application:
name: consumer
#日志取样100%
sleuth:
sampler:
percentage: 1
rabbitmq:
host: 120.77.245.104
port: 5672
username: guest
password: guest
eureka:
instance:
prefer-ip-address: true
instance-id: consumer:9001
client:
service-url:
defaultZone: http://localhost:7001/eureka/ #,http://localhost:7002/eureka/
#开启feign接口的fallbackFactory支持
feign:
hystrix:
enable: true
在启动类中使用@EnableHystrix 开启服务容错,使用该注解feign的服务容错才开启,该注解已经包含@EnableHystrix
使用@EnableFeignClients开启feign,feign 类似于dubbo, 并扩展了接口版的springmvc
消费者使用Ribbon的负载均衡,使用方式异常简单,只需要在配置RestTemplate中添加一个注解 @LoadBalanced
SpringCloud大大简化了分布式开发
@EnableHystrix
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class ConsumerApplication {
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
接着使用Feign开发接口版的springmvc,Feign基于Ribbon,上面配置的负载均衡对Feign也有效,Feign也使用Hystrix的服务容错,只需要在接口上添加fallbackFactory 的类,.实现每一个接口的方法的服务容错
Feign+Hystrix
@FeignClient(value = "http://PROVIDER",fallbackFactory = UserServiceFallback.class)
public interface UserService {
@GetMapping("/getMsg")
public String getMsg();
}
实现方法的服务容错如下,注意使用@Component,使之添加到Spring的IOC容器中
public class UserServiceFallback implements FallbackFactory<UserService> {
@Override
public UserService create(Throwable throwable) {
return new UserService() {
@Override
public String getMsg() {
return "fegin hystrix fallbackFactory";
}
};
}
}
使用Ribbon的负载均衡的consumer的controller的如下,我们只需要调用RestTemplate即可.
我们还可以为每一个方法添加@HystrixCommand注解,并定义服务容错的fallbackMethod
后面会说到的hystrix-dashboard 只监听有@HystrixCommand注解的方法.
回顾使用dubbo框架,我们还需要引入另一个微服务的service接口,但使用Feign,我们则改为在接口中直接使用接口版的springmvc,个人觉得Feign比dubbo更解耦合
@RestController
public class UserController {
private final Logger logger = Logger.getLogger(getClass());
//ribbon负载均衡
private static final String REST_URL_PREFIX="http://PROVIDER";
@Autowired
RestTemplate restTemplate;
//feign
@Autowired
UserService userService;
@GetMapping("/getMsg")
public String getMeg(){
logger.info("consumer ribbon");
return restTemplate.getForObject(REST_URL_PREFIX+"/getMsg",String.class);
}
@GetMapping("/getMsg2")
public String getMsg2(){
logger.info("consumer feign ");
return userService.getMsg();
}
//该方法抛出异常调用指定方法处理返回
@HystrixCommand(fallbackMethod = "fallBackGetMsg")
@GetMapping("/getMsg3")
public String getMsg3(){
logger.info("consumer hustrix fallback ");
int i=10/0;
return "test";
}
public String fallBackGetMsg(){
logger.info("consumer hustrix fallback method ");
return "fallbackGetMsg";
}
}