赞
踩
Spring Cloud是一系列框架的有序集合。利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、熔断器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。
SpringCloud主要框架有:
1)服务发现——Netflix Eureka
2)服务调用——Netflix Feign
3)熔断器——Netflix Hystrix
4)服务网关——Netflix Zuul
5)分布式配置——Spring Cloud Config
6)消息总线——Spring Cloud Bus
是Netflix开发的服务发现框架,实现SpringCloud服务发现功能。Eureka包含两个组件:Eureka Server和Eureka Client。
Eureka Server提供服务注册服务,各个节点启动后,会在Eureka Server中进行注册,这样Eureka Server中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。
Eureka Client是一个Java客户端,用于简化与Eureka Server的交互,客户端同时也就别一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会向Eureka Server发送心跳,默认周期为30秒,如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,Eureka Server将会从服务注册表中把这个服务节点移除(默认90秒)。
Eureka Server之间通过复制的方式完成数据的同步,Eureka还提供了客户端缓存机制,即使所有的Eureka Server都挂掉,客户依然可以利用缓存中的信息消费其他服务的API。综上,Eureka通过心跳检查、客户端缓存等机制,确保了系统的高可用性和可伸缩性。
导包
- <dependencyManagement>
- <dependencies>
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-dependencies</artifactId>
- <version>Finchley.M9</version>
- <type>pom</type>
- <scope>import</scope>
- </dependency>
- </dependencies>
- </dependencyManagement>
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
- </dependency>
配置application.yml
- server:
- port:8080
- eureka:
- client:
- register-with-eureka: false #是否将自己注册到Eureka服务中
- fetch-registry: false #是否从Eureka中获取注册信息
- #Eureka客户端与Eureka服务端进行交互的地址
- serviceUrl:
- defaultZone: http://127.0.0.1:${server.port}/eureka/
启动类
- @SpringBootApplication
- @EnableEurekaServer
- public class EurekaServer{
- public static void main(String[] args){
- SpringApplication.run(EurekaServer.class);
- }
- }
导包
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
- </dependency>
配置application.yml
eureka.client.service-url.defaultZone: http://127.0.0.1:8080/eureka/
启动类
加上注解 @EnableEurekaClient
简化Java HTTP客户端开发的工具,前提是服务注册,在Eureka服务器上才行。如A调用B,那么就需要对A进行Feign的引入。
导包
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-openfeign</artifactId>
- </dependency>
调用接口类
- // @FeignClient注解用于指定从哪个服务中调用功能
- @FeignClient("需要调用的模块application的name配置")
- public interface XXXClient{
- // @RequestMapping注解用于对被调用的微服务进行地址映射
- // @PathVariable一定要指定参数名称
- @RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
- public Result findById(@PathVariable("id") String id);
-
- }
启动类
加上注解 @EnableDiscoveryClient和@EnableFeignClients
注:Feign默认已经实现了负载均衡,多次调用采用轮询方式
在微服务架构中通常会有多个服务层调用,基础服务的故障可能导致级联故障,进而造成整个系统不可用的情况,这种现象称为服务雪崩效应。服务雪崩效应是一种因“服务提供者”的不可用导致“服务消费者”的不可用,并将不可用逐渐放大的过程。例如A作为服务提供者,B是A的服务消费者,C和D是B的服务消费者。A不可用会引起B的不可用,并将不可用想滚雪球一样放大到C和D时,雪崩效应就形成了。
Hystrix中文豪猪,因其背上长满了刺,而拥有自我保护能力。
Hystrix能使系统在出现依赖服务失效的时候,通过隔离系统所依赖的服务,防止服务级联失败,同时提供失败回退机制,更加优雅地应对失败,并使系统能更快地从异常中恢复。
Feign本身支持Hystrix,不需要额外引入依赖。
1)application.yml增加配置,开启hystrix
- feign:
- hystrix:
- enabled: true
2)给接口添加熔断实现类,实现可能存在异常的接口
- @Component
- public class UserServiceImpl implements UserService{
-
- @Override
- public Result findById(String id){
- return new Result(false, StatuCode.ERROR, "熔断器启动了");
- }
-
- }
3)修改接口注解
@FeignClient("需要调用的模块application的name配置", fallback = UserServiceImpl.class)
当其他服务调用该服务时,如果该服务未启动或有异常,则会走熔断实现类的方法,一旦该服务启动/正常后就不会调用熔断类了。
不同的微服务一般有不同的网络地址,而外部的客户端可能需要调用多个服务的接口才能完成一个业务需求。比如一个电影购票APP,可能调用电影分类微服务,用户微服务,支付微服务等,如果客户端直接和微服务进行通信,会存在以下问题:
1)客户端多此请求不同微服务,增加客户端的复杂性
2)存在跨域请求,在一定场景下处理相对复杂
3)认证复杂,每一个服务都需要独立认证
Zuul包含了对请求的路由和过滤两个主要功能
1)路由功能:负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础
2)过滤器功能:负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础
Zuul和Eureka进行整合,将Zuul自身注册未Eureka服务治理下的应用,同时从Eureka中获得其他微服务的消息,即以后的访问微服务都是通过Zuul跳转后获得。
5.2.1 快速搭建
1)创建微服务网关模块,pom添加依赖
- <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-netflix-zuul</artifactId>
- </dependency>
2)创建application.yml
- zuul:
- routes:
- xxx-base: #要调用的微服务模块名称,随便写,一般都是微服务模块的名称
- path: /base/** #配置请求URL的规则
- serviceId: xxx-base #指定Eureka注册中心的服务id,不能乱写
3)启动类
添加注解@EnableZuulProxy
测试:之前访问都要不同服务切换不同端口号,现在就只要通过该网关微服务的端口号加上path路径就可以访问各个服务了。
什么情况下需要用到过滤器呢?发现请求如果存在请求头会在转发后丢失。
直接在网关微服务模块添加过滤器类,可以加多个
- @Component
- public class XxxxFilter extends ZuulFilter{
-
- // 请求前加pre或请求后加post执行
- @Override
- public String filterType(){
- return "pre";
- }
-
- // 多个过滤器的执行顺序,数字越小,越先执行
- @Override
- public intfilterOrder(){
- return 0;
- }
-
- // 当前过滤器是否开启
- @Override
- public boolean shouldFilter(){
- return true;
- }
-
- // 过滤器执行的操作,任何object的值都表示进行执行
- // setSendZuulResponse(false)表示不再继续执行
- @Override
- public Object run() throws ZuulException {
- // ==== 请求头转发操作 ====
- // 得到request上下文
- ReuquestContext currentContext = RequestContext.getCurrentContext();
- HttpServletRequest request = currentContext.getRequest();// 得到request域
- String header = request.getHeader("xxx"); // 得到头信息
- // 判断是否有头信息
- if(header != null && !"".equals(header)){
- // 头信息继续向下传
- currentContext.addZuulRequestHeader("xxx", header);
- }
- return null;
- }
-
- }
在分布式系统中,由于服务数量巨多,为了方便服务配置文件统一管理,实时更新,所以需要分布式配置中心组件。在Spring Cloud中,有分布式配置中心组件Spring Cloud Config,它支持配置服务放在配置服务的内存中(即本地),也支持放在远程Git仓库中。在Spring Cloud Config组件中,分两个角色,一是Config Server,二是Config Client。
Config Server是一个可横向扩展、集中式的配置服务器,用于集中管理应用程序各个环境下的配置,默认使用Git存储配置文件内容,也可以使用SVN存储,或是本地文件存储。
Config Client是Config Server的客户端,用于操作存储在Config Server中的配置内容。微服务在启动时会请求Config Server获取配置文件的内容,请求到后再启动容器。
将配置文件提交到码云,文件命名规则{application}-{profile}.yml,application为应用名称,profile指的开发环境(开发、测试、生产等)。
1)创建配置中心微服务模块,pom添加依赖
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-config-server</artifactId>
- </dependency>
2)创建application.yml
- cloud:
- config:
- server:
- git:
- uri: https://gitee.com/xxxxxx
3)启动类
添加注解@EnableConfigServer,开启配置服务
测试:访问localhost:{端口号}/{配置文件名称}就可以看到配置内容
1)pom添加依赖
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-config</artifactId>
- </dependency>
2)创建bootstrap.yml,删除application.yml(删除的配置文件已经放到了码云上)
- spring:
- cloud:
- config:
- name: base # name与profile要保持和码云上传的配置文件名称保持一样
- profile: dev
- label: master
- uri: http://127.0.0.1:{Config Server的端口}
测试:启动改造后的工程,看是否可以正常运行
如果我们更新码云中的配置文件,那客户端工程不能及时接受新的配置信息,只有重启才会读取配置。那我们如果不重启微服务的情况下更新配置,可以使用Spring Cloud Bus来实现配置的自动更新。
1)创建消息总线组件Spring Cloud Bus服务端模块,pom添加依赖,基于Spring Cloud Config
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-bus</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-stream-binder-rabbit</artifactId>
- </dependency>
2)修改application.yml
- spring:
- rabbitmq:
- host: xxx.xxx.xxx.xxx
-
- management: # 暴露触发消息总线的地址
- endpoints:
- web:
- exposure:
- include: bus-refresh
1)创建消息总线组件Spring Cloud Bus服务端模块,pom添加依赖
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-bus</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-stream-binder-rabbit</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-actuator</artifactId>
- </dependency>
2)添加配置,基于Spring Cloud Config的话需要在码云那边的配置文件添加
- spring:
- rabbitmq:
- host: xxx.xxx.xxx.xxx
测试:需要通过访问http://127.0.0.1:{端口}/actuator/bus-refresh触发客户端的重新编译配置文件。
注:上面这种配置文件修改只能是针对框架内部自定义的配置属性,如果是自己外部随便定义的属性值也需要通过这种形式去更新,只需要加上注解@RefreshScope就行。
- @RefreshScope
- public class XxxxController{
- // 获取配置文件中名称为ip的值
- @Value("${ip}")
- private String ip;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。