目录
Spring cloud 组件
Eureka 服务发现框架
何为服务,何又为发现呢?
它主要包括两个组件:Eureka Server 和 Eureka Client
Eureka Client:一个Java客户端,用于简化与 Eureka Server 的交互(通常就是微服务中的客户端和服务端)
Eureka Server:提供服务注册和发现的能力(通常就是微服务中的注册中心)
每个微服务的客户端和服务端,都会注册到 Eureka Server
在这个服务发现过程中有三个角色分别是服务提供者,服务消费者,注册中心
可以用现实生活中的例子来理解这三个角色 服务提供者(房东),服务消费者(租客),注册中心(中介)
服务提供者:就是提供一些自己能够执行的一些服务给外界。
服务消费者:就是需要使用一些服务的“用户”。
服务中介:就是服务提供者和服务消费者之间的“桥梁”,服务提供者可以把自己注册到服务中介那里,而服务消费者如需要消费一些服务(使用一些功能)就可以在服务中介中寻找注册在服务中介的服务提供者。
可以试想 没中介你要租房子 那是一个什么场景 房东得去找租客 租客得去找房东 刚开始也许你觉得很有趣 时间久了就会觉得很干燥了而且这样很浪费时间。
这时有个聪明的房东就想到了 我可以贴小广告啊!
小广告这一做法放在现实世界来说的确可以但是这样会造成想租房跟不想租房的人都会看到这个广告,在计算机世界里的话就会出现资源消耗的问题。但是也还是麻烦 我要租房我就得东找小广告西找小广告 (想想都烦死了) 这时候有个中介 租客租房 房东出租房的问题是不是就迎刃而解了
房东将房子信息提交给中介, 租客根据中介提供的房子信息来选择自己想租的房 这样不就简单起来了嘛~
emmm 这就是我理解到的注册过程了。
这时候就有新的问题出现了(新的风暴已经出现 怎么能够停滞不前)get不到就算了 哈哈哈哈~
新问题:
- 房东注册后不想租了怎么办,我们需要让他定期续约,如果没续约我们是否考虑将他在注册列表中移除?
- 租客是不是也要进行注册呢?不然合同乙方怎么来呢?
- 中介可不可以做连锁店呢?如果这一个店因为某些不可抗力因素而无法使用,那么我们是否可以换一个连锁店呢?
续约:微服务会周期性(默认30s)地向 Eureka Server 发送心跳以Renew(续约)自己的信息(类似于heartbeat)
续期:Eureka Server 会定期(默认60s)执行一次失效服务检测功能,它会检查超过一定时间(默认90s)没有Renew(续约)的微服务,发现则会注销该微服务节点
识别:Eureka Client 会缓存 Eureka Server 中的信息,即使所有 Eureka Server 节点都宕掉,服务消费者仍可使用缓存中的信息找到服务提供者
同步:每个 Eureka Server 同时也是 Eureka Client(逻辑上的),多个 Eureka Server 之间通过复制的方式完成服务注册表的同步,形成 Eureka 的高可用
服务下线:Eureka客户端在程序关闭时向Eureka服务器发送取消请求。发送请求后,该客户端实例信息将从服务器的实例注册表中删除。该下线请求不会自动完成,它需要调用以下内容:DiscoveryManager.getInstance().shutdownComponent();
当然服务发现的组件有很多:Zookeeper,Consul, Eureka 等。
Ribbon 进程内负载均衡器
Ribbon 是Netflix公司的一个开源的负载均衡 项目,是一个客户端/进程内负载均衡器,运行在消费者端。
简单来说Ribbon 就是一个类库,集成在服务消费方,消费方从服务注册中心获知有哪些地址(即服务)可用,然后消费方通过 Ribbon 从这些地址当中选择一个合适的服务器来消费服务。
Nginx 和 Ribbon 的对比
说到负载均衡 大部分人都会想到Nginx。
Nginx采用的是集中式负载均衡器。
什么是集中式? 集中式就是将请求全部集中起来后再进行负载均衡。
Ribbon:消费者端获取到了所有的服务列表之后,在其内部使用负载均衡算法,进行对多个系统的调用。
Ribbon的使用
在服务的消费方导入Ribbon的依赖
<!--ribbon负载均衡依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
Ribbon 的几种负载均衡算法: Ribbon默认采用轮询策略。
- 轮询策略 RoundRobinRule: 若经过一轮轮询没有找到可用的provider(服务提供者),其最多轮询 10轮。若最终还没有找到,则返回 null。
- 随机策略 RandomRule: 从所有可用的 provider 中随机选择一个。
- 重试策略 RetryRule: 先按照 RoundRobinRule 策略获取 provider,若获取失败,则在指定的时限内重试。默认的时限为 500 毫秒。
完整算法据我了解是有7种这里就不一一列举了~
默认的负载均衡算法可以更改,只需要在配置文件中做出修改
providerName:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
Open Feign 服务调用映射
OpenFeign 也是运行在消费者端的,使用 Ribbon 进行负载均衡,所以 OpenFeign 直接内置了 Ribbon。
什么是Feign?
官方的解释:Feign 是一个声明式 WebService 客户端。使用 Feign 能让编写的 WebService 客户端更加简洁,它的使用方法式定义一个接口,然后在上面添加注解。Spring Cloud 对 Feign 进行了封装,使其支持了 Spring MVC 标准注解和 HttpMessageConverters。Feign 可以与 Eureka 和 Ribbon 组合使用以支持负载均衡。
什么是 RestTemplate?
RestTemplate是Spring提供的一个访问Http服务的客户端类
Eureka 框架中的注册、续约等,底层都是使用的RestTemplate。
为什么要用Feign?
当有了Eureka,RestTemplate,Ribbon我们就可以愉快地进行服务间的调用了,但是使用RestTemplate还是不方便,每次调用RestTemplate的API都要 url、请求、返回类型的,能不能像调用原来代码一样进行各个服务间的调用呢?
路过的琦玉老师:可以使用映射,就像域名和IP地址的映射。我们可以将被调用的服务代码映射到消费者端,这样就可以进行“无缝开发”了
在导入了Open Feign之后我们就可以进行愉快编写 Consumer端代码了,然后我们在Controller就可以像原来调用Service层代码一样调用它了。
必不可少的Hystrix 服务降级熔断器
先说一下服务雪崩 什么是服务雪崩?
设我们有A,B,C三个服务器当服务A调用服务B,服务B调用服务C,这时飞来横祸,服务C出问题了(屋漏偏逢连夜雨)这时有大量请求进来卡在了服务C, 如果只有服务C阻塞了还好,毕竟只是一个服务器崩溃,但注意上面说的服务B调用服务C ,服务C自身都难保,无法返回响应给服务B, 服务B请求服务C的请求也堵了同样的道理那么调用服务B的服务A也阻塞崩溃了
为什么阻塞会崩溃?
因为这些请求会消耗占用系统的线程、IO 等资源,消耗完你这个系统服务器不就崩溃了嘛。
Hystrix之熔断和降级
熔断指的是[Hystrix]中的断路器模式
所谓熔断就是服务雪崩的一种有效解决方案。当指定时间窗内的请求失败次数达到设定阈值时,系统则通过断路器直接将此请求链路断开。
可以使用简单的@[Hystrix]Command注解来标注某个方法,这样[Hystrix]就会使用断路器来“包装”这个方法,每当调用时间超过指定时间时(默认为1000ms),断路器将会中断对这个方法的调用。
我们可以对注解里的属性进行设置,比如超时时间
- execution配置
@HystrixCommand(
commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "1500")}
)
- execution.isolation.strategy :该属性用来设置执行的隔离策略
- execution.isolation.thread.timeoutInMilliseconds:该属性用来配置 HystrixCommand 执行的超时时间,单位为毫秒,默认值 1000 ,超出此时间配置,Hystrix 会将该执行命令为 TIMEOUT 并进入服务降级处理逻辑
- execution.timeout.enabled:该属性用来配置 HystrixCommand 执行是否启动超时时间,默认值 true,如果设置为 false,execution.isolation.thread.timeoutInMilliseconds属性的配置将不起作用
- execution.isolation.thread.interruptOnTimeout: 该属性用来配置当 HystrixCommand 执行超时的时候,是否需要将他中断,默认值 true
- execution.isolation.semaphore.maxConcurrentRequests:当隔离策略使用信号量时,该属性用来配置信号量的大小,当最大并发请求数达到该设置值,后续的请求将会被拒绝
还有 fallback配置,circuitBreaker 配置,metrics 配置,requestContext 配置,collapser 配置,threadPool 配置 有兴趣的可以去了解一下。
降级
降级是为了更好的用户体验,当一个方法调用异常时,通过执行另一种代码逻辑来给用户友好回复。对应着[Hystrix]的后备处理模式。你可以通过设置fallbackMethod来给一个方法设置备用的代码逻辑。
举个栗子
有个热点新闻我们推荐给用户,用户查看详情,用户通过热点id去看新闻详情,但因为访问人数较多,大量用户同时访问也可能导致系统崩溃,这时候我们就可以使用服务降级,部分请求做降级处理提示:服务器开了小差,请休息一会再试。
结尾:Hystrix不止那么点东西,有兴趣可以去深入了解下。
Zuul 微服务网关
网关是系统唯一对外的入口,介于客户端与服务器端之间,用于对请求进行鉴权、限流、路由、监控等功能。这些功能Zuul都有!最关键的就是路由和过滤器了
Zuul需要向 Eureka 进行注册在启动类上加入@EnableZuulProxy注解
路由
** 代表匹配多级任意路径
*代表匹配一级任意路径
统一前缀:在访问路径前面加一个前缀
localhost:8888/user/update
通过yml文件进行配置
zuul:
prefix: /zuul
这样就需要通过localhost:8888/zuul/user/update来进行访问。
路由策略配置
前面用户访问是直接通过服务名来进行访问,存在安全风险,我们可以通过自定义路径来替代服务名称,即自定义路由策略。
zuul:
routes:
user: /test/**
这时就可以使用localhost:8888/zuul/test/user/update进行访问。
服务名屏蔽
配置了路由策略后还是可以通过服务名访问滴~ 这时就需要服务名屏蔽
zuul:
ignore-services: "*"
路径屏蔽
用户请求中包含指定的 URI 路径,那么该请求将无法访问到指定的服务
zuul:
ignore-patterns: **/test/**
这样关于 test 的请求我们就可以过滤掉
过滤功能
如果说,路由功能是Zuul的基操的话,那么过滤器就是Zuul的利器了。毕竟所有请求都经过网关(Zuul),那么我们可以进行各种过滤,这样我们就能实现限流,权限控制等等。
过滤器类型对应于请求的典型生命周期。
- PRE:这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
- ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用 Apache HttpClient 或 Netfilx Ribbon 请求微服务。
- POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的 HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
- ERROR:在其他阶段发生错误时执行该过滤器。 除了默认的过滤器类型,Zuul 还允许我们创建自定义的过滤器类型。例如,我们可以定制一种 STATIC 类型的过滤器,直接在 Zuul 中生成响应,而不将请求转发到后端的微服务。
Zuul 中默认实现的 Filter:
禁用过滤器
可以在 application.yml 中配置需要禁用的 filter,格式为zuul.<过滤器名>.<过滤器类型>.disable=true。
比如要禁用org.springframework.cloud.netflix.zuul.filters.post.SendResponseFilter就设置
#禁用过滤器
zuul.SendResponseFilter.post.disable=true
结尾:还有很多没举例的 有兴趣的可以去了解下。
Config 微服务统一配置中心
Spring Cloud Config就是能将各个 应用/系统/模块 的配置文件存放到统一的地方然后进行管理(Git 或者 SVN)
应用只有启动的时候才会进行配置文件的加载,那么我们的Spring Cloud Config就暴露出一个接口给启动应用来获取它所想要的配置文件,应用获取到配置文件然后再进行它的初始化工作
配置的动态刷新则需要配合Bus消息总线使用(不是很了解,嘿嘿)
结尾:有兴趣可以自行了解下。
Bus 消息总线
Spring Cloud Bus的作用就是管理和广播分布式系统中的消息,也就是消息引擎系统中的广播模式。当然作为消息总线的Spring Cloud Bus可以做很多事而不仅仅是客户端的配置刷新功能。
使用Spring Cloud Bus后创建一个简单的请求加上@ResfreshScope注解就能进行配置的动态修改
结尾:有兴趣可以自行了解下。
题外:栗子本栗
不喜勿喷 如有侵权请联系本人!!
笔者也是菜鸟一枚, 结合自己平时看的文章等写出这篇博文,如果有不清楚/不适/侵权的地方 请多多谅解and联系本人;