springCloud的了解(二)

773 阅读12分钟
                                                     更新时间:2019年7月18日

前言

今天的话,我们将继续来学习springCloud。springCloud的组件是极其多的,而其中最为出色的厂家则是NetFlix,可以说这个厂家几乎包揽了springCloud中最为重要的一些服务,例如:服务发现——Netflix Eureka,客服端负载均衡——Netflix Ribbon,断路器——Netflix Hystrix,服务网关——Netflix Zuul。因此也是这个厂商,在去年宣布了不再更新了Eureka和Hystrix,这其实对于springCloud的生态造成了巨大变化。

当然,即便如此,我们在实际的生产过程中,还是在使用NetFlix的大部分组件,因为这些组件即便不再更新了,但是在最近这几年,我相信市场还是NetFlix的,因为他们做的组件确实是成熟的,也是符合市场要求的。

因此,我们今天的主题是springCloud的组件,这当然也就包括了NetFlix厂家的组件。

Let's go party!!!

ps:大家快去看《乐队的夏天》这个综艺节目,里面的刺猬乐队的主唱子健,据说是程序员里面最会唱歌的( ̄▽ ̄)~*。

springCloud的组件以及分析

在开始了解springCloud的组件之前,我们必须先要了解一下微服务到底是个什么东西,毕竟我们的springCloud的基调是springboot,而springboot就是微服务。

一 .微服务

微服务就是把一个项目拆分为多个项目, 项目之间进行独立运行。通过Http或者Socket来进行通信处理数据和调用。这些小的Web服务可以独立地编译及部署,并通过各自暴露的API接口相互通讯。它们彼此相互协作,作为一个整体为用户提供功能,却可以独立地进行扩充。

因此衍生出的是微服务的编程思维:http restful。

肯定有人问为什么不使用RPC来编程,RPC的高效低延迟这个性能指标相信是很多微服务梦寐以求的,如果一个请求所需要的服务是3个以上并且各个服务业务逻辑复杂,甚至涉及众多IO操作,那是不是RPC的方式更为保障?

这个问题,我们留到后面再去详细了解,今天我们还是先进入正题。

二. 微服务组件的使用场景

 1:我们把整个系统根据业务拆分成几个子系统。
 2:每个子系统可以部署多个应用,多个应用之间使用负载均衡(Netflix Ribbon)。
 3:需要一个服务注册中心,所有的服务都在注册中心注册,负载均衡也是通过在注册中
    心注册的服务来使用一定策略来实现(Netflix Eureka)。
 4:所有的客户端都通过同一个网关地址访问后台的服务,通过路由配置,网关来判断一
    个URL请求由哪个服务处理。请求转发到服务上的时候也使用负载均衡(Netflix Zuul)。
 5:服务之间有时候也需要相互访问。例如有一个用户模块,其他服务在处理一些业务的
    时候,要获取用户服务的用户数据(Feign,本质上就是Ribbon+Hystrix,用注解的
    方式进行服务调用,代码更好看了)。
 6:需要一个断路器,及时处理服务调用时的超时和错误,防止由于其中一个服务的问题
    而导致整体系统的瘫痪(Netflix Hystrix)。
 7:还需要一个监控功能,监控每个服务调用花费的时间等(Turbin)。
 8:也需要一个配置中心,支持本地仓库、SVN、Git、Jar包内配置等模式,类似规章制
    度,每个人都从这里获取规定配置。(Config)

springCloud的组件太多,但是在实际的开发中,我们使用的组件,可能没有这么多,因此在实际的开发中,我们不需要一次性全部学会,只需要关注比较重要的几个就行了。当然,今天我们还是尝试着走马观花的将所有的组件了解一遍。

三. srpingCloud的组件解析

接下来我们开始了解springCloud组件,请戴上你的耳机,我推荐一首歌,最近很喜欢的一首歌《say it again》,是国内的一个乐队“盘尼西林”的歌,也参加了《乐队的夏天》这个综艺。哈哈哈哈ヾ(๑╹◡╹)ノ",没错,我就是传说中的自来水粉丝。

接下来,我会按照重要程度降序,来一一解析springCloud的部分重要组件。

1. Netflix Eureka——服务发现

毫无疑问,Eureka是springCloud的组件中的重要程度是要排第一的。

我们需要分别下载 Eureka 官方源码和 Spring Cloud Netflix 适配 Eureka 的代码。

原生 Eureka 代码: github.com/Netflix/eur…

Spring Cloud针对于Eureka的Spring Cloud适配:github.com/spring-clou…

ps: 没有下载git的朋友请下载git,用来在github上下载源代码。

服务发现(Eureka)是NetFlix旗下的核心组件之一,它负责服务注册,管理服务列表。所有的微服务都需要在Eureka上面进行注册登记,各个服务之间不需要之间对方的ip和端口,都是通过服务发现中心来进行互相调用API(一个在注册中心注册的REST服务),这当然会出现额外的开支--这个开支也就是所有客户机必须实现某种逻辑来与这个中心点进行交互,这样在实现服务请求之前将增加一次额外的网络往返。

springCloud使用Eureka来进行服务发现,在微服务注册到Eureka的时候,它必须向Eureka发送心跳信息,以此Eureka会判断这个微服务是否在线上。

如果你相同的微服务你开了多个服务端,那么在Eureka也会在注册发现中心显现出来功能相同的微服务的不同的服务端,那么也是依赖Eureka来进行类似nginx分发服务的负载均衡的功能。

到了这里,我们发现在之前的学习过程中,我们还是不够了解springboot。因为springboot实际上的开发解耦就是将后端和前端直接分离开了,不是说使用springboot或者springCloud不能进行前后端一体开发,而是springCloud乃至springboot的本身就是为了前后端分离而诞生的。(在springCloud中,后端接口的API都是注册到了Eureka中的,实际开发中,前端开发工作人员甚至可以直接在Eureka中直接查找需要的接口API。)

总结:

1. 是纯正的 servlet 应用,需构建成war包部署 
2. 使用了 Jersey 框架实现自身的 RESTful HTTP接口 
3. peer之间的同步与服务的注册全部通过 HTTP 协议实现 
4. 定时任务(发送心跳、定时清理过期服务、节点同步等)通过 JDK 自带的 Timer 实现 
5. 内存缓存使用Google的guava包实现

其实不需要问为什么使用的是HTTP协议,看看市面上有什么不支持HTTP的么?这其实就是为什么要使用HTTP的原因之一。

2. Netflix Ribbon——客服端负载均衡

Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起。

我们在配置文件中列出负载均衡所有的机器,Ribbon会自动的帮助我们基于某种规则(如简单轮询、随机连接等等)去连接这些机器。

Ribbon客户端组件提供了一列完善的配置项(如连接超时、重试等等),我们也能很容易的使用Ribbon实现自定义的负载均衡算法。

Ribbon和Eureka整合后服务消费方可以直接调用服务而不用再关心提供服务的地址以及提供服务的端口号。

Ribbon其实就是一个软负载均衡的客户端软件,它可以和其它所需请求的客户端结合使用,和Eureka结合只是其中的一个实例。

接下来贴出一些最基本的配置项:

 RoundRobinRule:轮询
 RandomRule:随机
 AvailabilityFilteringRule:会先过滤掉由于多次访问故障而处于断路器跳闸状态和并
                            发的连接数量超过阈值的服务,然后对剩余的服务列表按
                            照轮询策略进行访问。
 WeightedResponseTimeRule:根据平均响应时间计算所有服务的权重,响应时间越快服
                           务权重越大被选中的概率越高。
 RetryRule:先按照RoundRobinRule的策略获取服务,如果获取服务失败,则在指定时间
            内会进行重试,获取可用的服务。
 BestAvailableRule:会过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选
                    择一个并发量最小的服务。
 ZoneAvoidanceRule:默认规则,复合判断Server所在区域的性能和Server的可用性选择服
                    务器。

如果需要修改的话也很简单,我在网络上找到了一些方法,现在贴出一个来:

当然,我现在也只是大概了解了一下,因为在实际开发中,很有可能是需要配置自己自定义的规则,那么修改方法可能不一样了,具体情况大家感兴趣的话可以在网络上自行百度。

3. Netflix Zuul——服务网关

在下才疏学浅,很多的东西都解释不好,因此只能厚颜从网络上搬来一部分资料。刚刚在网络上的一个博客看到一个大神解释的关于Eureka和Ribbon的解释图,给大家看看。

其实在之前的Eureka的解析中,我多多少少有解释过,前后端分离的解耦,最重要的原因是开发人员可以直接调用接口API。

但是在实际开发中,我们在每一个服务接口上面都会加上一些权限校验,那么在这里,如果我们在每一次调用服务接口的时候都进行权限校验,那么我们必须在每一次调用服务接口的时候必须加上权限校验的代码,这很明显的增加了我们的工作量。

而且如果微服务数量多了,那么一些接口的调用规则,服务列表的维护工作也会变得十分的麻烦,甚至需要公司在开发之前都要做好接口的规则确定。

于是,API网关(路由网关)应运而生。

在没有网关之前,客户端服务包括两个步骤:

1.从EurekaServer获取一个客户端服务的所有地址
2.通过Ribbon负载均衡选择一个机器进行访问

引入网关之后,客户端通过 “http://gateway/服务ID/url” URL格式调用网关,网关执行包括两个步骤:

1.使用服务ID查找客户端服务
2.使用Netflix Ribbon对调用服务进行负载均衡。

路径解释:

gateway:网关服务在Eureka注册的服务ID
服务ID:客户端服务在Eureka注册的服务ID
url:访问客户端服务的url。

在上一个图片的基础上,我们贴出有了路由网关的图:

我们看到,整个系统的入口就是zuul,当我们有参数校验的需求时,我们就可以利用Zuul的Pre过滤器,进行参数的校验。例如我现在希望请求都一律带上token参数,否则拒绝请求。当然,在这个图中,没有加入Pre过滤器。

这就是zuul的两大功能:过滤(权限控制)和路由转发。

4. Netflix Hystrix——断路器

Hystrix的中文翻译是豪猪,也就是身上长满了刺的猪。它的主要功能是-自我保护。Hystrix具有服务降级,熔断,线程池隔离,信号量隔离,缓存等功能,基本上能覆盖到微服务中调用依赖服务会遇到的问题。

为了保证其高可用,单个服务通常会集群部署。由于网络原因或者自身的原因,服务并不能保
证100%可用,如果单个服务出现问题,调用这个服务就会出现线程阻塞,此时若有大量的请求
涌入,Servlet容器的线程资源会被消耗完毕,导致服务瘫痪。服务与服务之间的依赖性,故
障会传播,会对整个微服务系统造成灾难性的严重后果,这就是服务故障的“雪崩”效应。

当执行调用服务方法时,若调用方法出现问题,如:请求超时,抛出异常,线程池拒绝,熔断这些情况下,为该方法定义降级方法,以便在出现问题时执行,实现备用返回。之前我们已经实现了服务降级功能,主要就是通过@HystrixCommand(fallbackMethod = "defaultMethod")注释到需要在出现问题时降级的方法。

fallbackMethod指定降级后执行的方法。方法定义在该类中,public,private,protected都可以。在注释的方法出问题后,如超时未返回(execution.isolation.thread.timeoutinMilliseconds来配置),就会执行备用方法,返回备用方法的返回值。当然,降级的方法也可以定义再下一级的降级方法,实现和上面一样。

上面说到方法抛出异常也会触发服务降级,但是如果我们自定义了异常,并需要将异常抛出给上层做操作,不希望Hystrix捕捉到自定义异常执行服务降级时,可以使用@HystrixCommand(ignoreExceptions ={MyException.class})来定义忽略捕捉的异常。多个异常用逗号隔开。也可以将抛出的异常通过入参传到降级的方法,来实现不同类型异常的不同处理。

小结

到了这里,我相信大家对springCloud有了一个整体的大概的了解,当然,实际情况中,springCloud的复杂程度是超出当前我的讲述的。明天,我们将继续来了解springCloud。