spring cloud netflix 组件小结
文章目录
本文实践代码托管在:https://github.com/leishiguang/spring-cloud-demo
eureka 服务注册与发现
嗯,先说说注册中心,假如没有注册中心,如何管理多个服务?我们可能会在客户端提前配置服务端的地址。
但这样,没有注册中心,带来的问题有:
- 无法监控服务提供方的健康情况,接口服务器可能不固定,可能随时增删机器;
- 接口调用方无法知晓提供方的具体 ip 和 port 地址,除非手动调整接口调用者的代码;
那么,注册中心的存在意义,就是为了:
- 服务方当前是什么状态,是否健康?
- 服务方的地址有没有迁移,最新的是什么?
- 让修改客户端服务方列表的过程,变成自动进行;
这也是 eureka 的作用,它的执行流程如:
流程说明:
- 服务提供者启动时,定时向 EurekaServer 注册自己的服务信息(服务名、IP、端口…等等)
- 服务消费者启动时,后台定时拉取 EurekaServer 中存储的服务信息
集成和配置的一些 tips:
- 引入 spring-boot-starter-actuator,用以监控 spring boot 的一些端点;
- 引入 spring-boot-starter-web,可以通过 http 方式访访问监控主页;
- 引入 spring-cloud-starter-netflix-eureka-server,这样就有了 eureka 核心组件,就可以具有 eureka server 功能,供其它客户端进行接入了;
- 在启动类添加 @EnableEurkaServer 注解,这时就会自动的读取 EurekaServerMarkerConfiguration.class 配置,帮助我们实例化 eureka 服务;
- 在配置文件中执行 eureka 的相关配置,这就有许多了,常用比如:
spring.application.name,服务名称
server.port,服务端口
eureka.instance.hostname,当前实例名称
eureka.instance.intance-id,实例的id
eureka.client.fetch-registry,是否要拉取 eureka 的服务列表?
eureka.client.register-with-eureka,是否要把自己注册在eureka?
eureka.client.service-url.defalutZone,要选择的注册中心?
eureka.server.wait-time-in-ms-when-sync-empty,服务要同步数据的等待时间
eureka.server.enable-self-reservation,自我保护机制,是不是防止网络颤动时的服务下线,这一步虽然确保了自身的健壮性,但可能会保留已宕机的服务,好在有别的组件弥补了这部分的不足
eureka.server.peer-eureka-nods-update-interval-ms,服务同步时间,可以稍微设置长一些,因为我们不需要它那么快速的去同步
defaultZone 是一个区域的概念,可以指定对应的地区,比较适用于较大范围的服务器,这样客户端会优先调用同地区的服务,比如这么一个配置:
eureka.client.service-url.defalutZone = http://localhost:10000/eureka
eureka.client.service-url.zone1 = http://localhost:10002/eureka
eureka.client.availability-zones.china
:zone1
这样,在 china 节点,就会优先调用 10002 上注册的服务,如果调用不到,才会调用 10000 上注册的
嗯,顺利启动之后,便可以在配置好的服务地址,看到服务信息哦,如:
这时,只是 eureka 服务端启动了,如果要进行服务,还需要有:
- 服务提供方,即 eureka 服务节点
- 服务调用方,就是客户端,要发起服务的调用
那么,eureka 客户端的集成:
- 客户端引入 spring-cloud-starter-netfilx-eureka-client,便可以连接已存在的 eureka 服务,进行服务注册或者服务调用;
- 服务方注意配置 spring-application.name 服务名称
- 配置 eureka.client.service-url.defaultZone,或是其它的注册中心,把自己提供的服务,注册到 eureka 中去。服务调用方也这么配置,从该 eureka 中拉取服务
- 在调用时,使用
http://服务名/
替代 ip 和 port,如:
@Autowired
private RestTemplate restTemplate;
@GetMapping("index")
public Object getIndex(){
return restTemplate.getForObject("http://HELLOSERVER/",String.class,"");
}
那么,eureka 的核心知识有哪些呢?
- eureka 如何注册服务?
- 如何发现服务?
- 服务断开了怎么办?
- 服务名是怎么变成 ip+port 呢?
- 自我保护机制,网络颤动怎么办?
hashMap 保存服务信息之后,再拦截对应的服务调用,替换为具体的服务实例~
详细源码解析,下回分解 ?
ribbon 客户端负载均衡
前面说到,eureka 中,当服务提供方有多个的时候,要按什么样的规则去调用呢?
好比 nginx 可以对请求进行分流。当请求已经进入服务端之后,该服务端又要作为服务的调用方,去调用其它服务。这时候,要怎么做负载均衡呢?
这就是 ribbon 为我们做的事情,客户端负载均衡。
如何集成呢?这儿先看看如何在脱离 eureka 的情况下,进行 ribbon 负载均衡…
- 引入 spring-cloud-starter-netflix-ribbon,之后开始配置…
- (注意这儿没有与 eureka 集成)改造配置,声明可负载均衡的服务列表,声明 @RibbonClients 注解,声明 @LoadBlance 注解,调用时使用 LoadBanlancerClient,具体的配置看之后的代码示例咯…
- 通过 RibbonLoadBlanceClient 的 choose 方法获取到服务实例
- 通过服务实例得到的 ip + port 去调用服务…
那么,这里涉及到的 ribbon 核心知识:
- ribbon的结构和初始化过程?
- 如何发现有哪些服务实例?
- 怎么实现负载均衡策略?
- 容错机制有吗?
源码解析的部分靠后,这儿先简单的概括一些:
- RibbonAutoConfiguration:自动装配
- LoadBlancerClient:定义了各种方法,如 URL 获取,服务实例选择等。默认是 RibbonLoadBalancerClient
- SpringClientFactory:内部包含了各种获取对象,如 loadbalancer、instance 等方法
ribbon 中,如果要自定义策略,实现 IRule 接口即可,官方提供了这么些负载均衡策略:
嗯,Ribbon 与 RestTemplate,前面介绍时,使用的是 LoadBanlancerClient,实际上,Ribbon 可以与 RestTemplate 很好的结合:
@Bean
@LoadBalanced
public RestTemplate template(){ return new RestTemplte() }
这样,就可以和 eureka 一样,通过服务名进行调用了。
详细源码解析,下回分解 ?
hystrix 服务容错机制
在微服务中,一个请求有可能是多个微服务协同处理的,多个微服务相互依赖。这时候,如果某个服务超时、网络不通,导致调用者阻塞,怎么办?总不能够全部的请求都积压在这一个服务上,占用大量资源,导致系统雪崩吧?
那,如何保护系统呢?一个服务不能用就不能用,不能因为这样,全盘系统都不能用了。
于是:
- 服务限流:服务消费者限制自身对某一服务能够发起的并发请求数量,超过数量则不调用;
- 熔断状态:熔断状态下,服务消费者不会发起对某一服务的调用;
- 服务降级:请求异常情况下,程序执行指定的降级策略(有点儿类似于异常捕获的catch代码块)
好比,在使用淘宝时,如果请求太大,会提示:服务忙,请稍后再试。
嗯,这三个东西要自己实现,还是有些麻烦的。那么,hystrix 就是现成可用的。
如何集成?
- 引入 spring-cloud-starter-netflix-hystrix 依赖
- 创建一个类继承 HystrixCommand,重写 fallback 方法;或者使用注解来进行配置…
- 通过这个类去代理相关请求;
- 出现问题后执行 fallback;
这儿要注意,熔断是在服务调用者端进行设计哦…
具体的配置,还参考示例…
那么,关于 hystrix 的核心:
- hystrix 资源隔离的思想
- 初始化流程
- 执行流程
- 和 spring cloud 集成
- hystrix 的监控 dashboard
具体原理,下回分解咯 ?
feign 声明式接口调用
用 RestTemplte 可能还有些不顺手,那么,是不是可以有类似于普通的 java 接口调用呢?这就是 Feign 的来源了,它让 web 接口调用和普通 java 接口一样便携。
spring cloud 对 Feign 的增强和改造:
- 将 Spring MVC 的注解与 Feign 客户端的定义进行了结合;
- 支持使用 Spring Web 中的 HttpMessageConverters 对请求和响应进行编解码工作。
那么,要怎么使用(集成)呢?
- 引入 spring-cloud-starter-openfeign 依赖;
- 启动类中添加 @EnableFeignClients 注解;
- 定义一个接口,加上 @FeignClient 注解,把每个要 http 请求的方法,用接口方法替代;
- 在需要用 restTemplate 的地方,改用定义好的接口方法;
tips:在定义接口的时候,也可以与 hystrix 集成,添加 fallback 哦,在配置文件中加入 feign.hystrix.enabled=true
即可,具体的参见代码实践…
关于 Feign 的使用,接口定义的示例:
@Component
@FeignClient(name="helloserver",fallback = HelloDemoFallback.class)
public interface HelloDemoService {
@RequestMapping(value = "",method = RequestMethod.GET)
public String index();
}
使用示例:
@RestController
public class CustomerController {
@Autowired
HelloDemoService helloDemoService;
@GetMapping("index")
public Object getIndex(){
return helloDemoService.index();
}
}
那么,核心原理,比如如何初始化?
其本质是使用 FeignClientFactoryBean 生成代理对象,并交给 spring 托管…
zuul 微服务网关
后端的服务提供者越来越多了,各个服务者之间调用倒是挺开心的。但是,对于外部来说呢?
- 外部客户端种类多,可能就没有集成服务注册发现的机制,无法发现服务;
- 出于安全和 ip 资源考虑,服务提供方的地址并不会直接对公网进行开放;
- 安全认证方面,是不是每个服务都需要实现权限认证呢…
zuul 网关应运而生,专门用以解决类似于上述典型问题。所有的外部请求先通过这个微服务网关,客户端只和网关进行交互,然后由网关进行各个微服务的调用。
这个过程就有点儿类似于 nginx 了,而它的特性有:
- 统一接入:为各种应用提供统一接入服务,高性能,高并发,高可靠,负载均衡,容灾切换;
- 协议适配:适配前端系统(http,websocket),后端业务系统 RPC,长短连接都支持。依据前端请求路由到相应的服务执行,并返回结果;
- 流量管控:限流、熔断、降级,路由一切容灾切换的应用;
- 安全防护:IP 黑名单,URL 黑名单,权限校验,防刷,恶意攻击等…
如果把整个微服务当作我们的家,网关就相当于是大门。
这儿容灾切换,指的是异地存在多个服务器,比如华南区、华北区,这种如果有一个区域宕机了,将自动把服务切换过去。尽量减少一个区域崩了之后,就完全无法用了。
zuul 本质上就是一个 web 应用,是一个 API Gateway 服务器。zuul 可以提供动态路由,监控,弹性,安全等边缘服务的框架。相当于是服务和所有 web 请求的大门。
zuul 能做什么?
- 认证和安全:识别每个需要认证的资源,拒绝不符合要求的请求;
- 性能监测:追踪并统计数据,提供精确的运行时状态数据;
- 动态路由:根据需要将请求动态路由(转发)到后端集群;
- 静态资源处理:直接负载均衡,预先为每种类型的请求分配容量,当请求超过容量时自动丢弃。
如何使用(集成)呢?
- 引入 spring-cloud-starter-netflix-zuul 相关依赖;
- 在启动类中添加 @EnableZuulProxy 注解开启 zuul 网关代理功能;或者添加 @EnableZuulServer 开启非代理模式的网关服务。
@EnableZuulProxy,实际上也继承了 @EnableZuulServer 的自动装配,扩展了 Server 的功能,主要区别是 Proxy 用动态代理的方式去转发路由。
- 配置,除了很通常的端口、应用名、注册中心外。也有 zuul 独有的,如:
zuul.host.connect-timeout-millis: http请求超时时间
zuul.host.socket-timeout-millis:socket请求超时时间
zuul.host.max-total-connections:最大连接数(连接池大小)
zuul.host.max-per-route-connections:每个 host 的最大连接数
zuul.ribbon-isolation-strategy: 隔离模式
zuul.semaphore.max-semaphores:最大并发数
zuul.routes... 路由配置
那么,zuul 的核心知识:
-
zuul 的初始化和执行流程
-
zuul 的路由定位流程
-
.http 的执行流程
-
拓展应用:用户登陆,权限校验
三大类的 filter: -
前置 filters,
-
routing filters,用来执行请求,比如用 ribbon 封装,就是有一个 ribbon 的 routing filters。
-
post filters,在请求之后执行,用于返回数据。
-
通常,如果有任意 filter 出错了,都会进到 error filter。
zuul 的初始化过程:
zuul 的 filter 执行流程:
zuul 的路由定位流程:
zuul 的请求流程:
具体的源代码分析,下回分解咯~
如果要扩展 zuul 功能,比如登陆验证,就看实践代码…
代码示例
一次完整的 spring cloud demo 实战,跳转 https://github.com/leishiguang/spring-cloud-demo
目前正在不断完善中…