什么是SpringCloud ?我用好理解的方式作比喻:
这里我们拿京东的网站做解释,京东不一定这么搞得,但是思想是一致的。首先SpringCloud一种微服务架构的实现;首先京东支持14亿人访问,这个架构一定不简单,而这个架构就是微服务架构。看例子:京东的首页网站:https://www.jd.com/ 京东的商品列表:https://list.jd.com/ 京东商品详情:https://item.jd.com/ ,购物车:https://cart.jd.com/ 等等。有没有发现一个问题,就是他们的网站地址不一样 ?这就证明了他们的业务是拆分开了,他们用到了微服务架构。
比如说,我们进京东,首先访问的是,京东的首页,首页也是访问人数最多的一个网站。这时候用一台、几台tomcat肯定是支撑不了这么大的并发访问量的。第二,选商品肯定要在很多商品列表中看一个自己喜欢的,这时候就是https://list.jd.com/对应的服务器返回的数据,还比如说京东的订单功能:https://order.jd.com/,我们一定是选好商品,准备付款的时候跳转到订单列表,这个功能用的人相对首页来说,并发访问量就没那么大了。
这时候为了不浪费资源,程序员可以怎么做呢 ?举个例子: 我把首页部署 1000台服务器,因为用的人最多,把订单部署200台服务器,因为用的人相对较少,我把订单的评论功能用50台服务器。想想如果没有架构的京东会是什么样子 ?就是把上面所有的功能都写在一个项目中,然后用很多很多的服务器部署这个一个项目,而且还不一定在618的时候,可以抗的住大量的访问。
所以什么是微服务呢 ?
就是把功能单独拆分开来,单独集群部署,这么一个思想,就是微服务架构思想。
把原本臃肿的一个项目的所有模块拆分开来并做到互相没有关联,甚至可以不使用同一个数据库,这就是微服务。
而SpringCloud就是为微服务提供技术支持的。SpringCloud不是微服务,只是为微服务提供解决方案。
这么说,还是很抽象,SpringCloud不是有很多很多技术吗 ?
下面就是用举例子的方式讲解:SpringCloud组件
再举例子 (讲解eureka 集群、心跳 与zookeeper类似):
传送门:SpringCloud版本Hoxton SR5 --- 第二讲:eureka 、eureka与zookeeper的区别与使用场景。
比如现在京东首页展示的代码写好了,我们把这个代码项目名管叫:jd-index ,然后把这个项目复制1000份部署到1000台服务器上,这时候就有一个问题,1000台服务器,1000个ip地址,我访问谁呢 ?这时候一定有人会说用nginx做反向代理。没错这是一个解决方案。
但是nginx还有个缺点,就是比如说 1000台,宕机500台,nginx在访问的时候,大多都是轮循机制,什么意思呢?比如说,1000个人访问nginx,但是宕机500台,这500台正好是配置的前500台宕机了,每台服务器自动访问两次再换服务器访问。就会造成所有人访问都是失败的,后1000-2000的访问是成功的。这就会造成很大一部分人,手机或者电脑提示404或者一直再访问中。 而eureka就可以解决这个问题,eureka自动识别到这500台服务器故障,然后自动将这500台服务器剔除去,那么这1000个人,就不可能访问到故障服务器。eureka把故障机踢出去后,就只剩下500台可以访问的机器,这样所有用户就都能访问成功。大大提高了用户的体验,当500个故障服务故障排除之后,又会自动重连。但值得注意的是,eureka解决的仅仅是将故障服务器剔除,他没有nginx的负载均衡功能,所以还要配合Ribbon的负载均衡策略,才可以完成一个真正的具有健壮性的负载均衡。
所以:eureka可以做到的仅仅是是微服务之间的心跳检测 和 微服务之间的相互注册。把故障微服务剔除,再把留下来的健康的服务的接口交给Ribbon做负载均衡。所以eureka 需要与 Ribbon + Fegin一起,才能实现负载均衡的完整功能。
接着上面的例子 (讲解Ribbon 与nginx类似)
传送门:SpringCloud版本Hoxton SR5 --- 第三讲:Ribbon 、Ribbon与Feign配合使用
上面说到了把500个故障服务器踢出eureka群聊。然后用nginx做负载均衡转发,还可以给某个服务器配置权重,或者简单的轮循、随机访问等。但这些功能虽然可以解决一部分并发访问的问题,但是访问规则较为固定。这时候就有了ribbon,ribbon在负载均衡的访问上提供了7中访问规则,并且ribbon也可以配置权重,不仅如此,还可以自定义服务器的访问规则,由程序员重写,以适应公司需求。
所以: Ribbon可以做到 配置服务器访问权重、7种已经写好的访问规则、重写服务器访问权重的规则(英文名:IRule 也就是负载均衡策略)、可以实现功能比较复杂的负载均衡功能。
还是接着上面的例子(讲解Feign)
还是上面的传送门,这里只是单独说一下:SpringCloud版本Hoxton SR5 --- 第三讲:Ribbon 、Ribbon与Feign配合使用
在日常工作中,一定用到过 webService、Apache cxf。他们的作用就是一样的。 比如写一段代码,调用一个 https://order.jd.com 类似的连接,然后再获取该链接返回的数据。 再比如说,当用到微服务架构的时候,京东用户登录后,可以看到购物车有多少件商品的提示, 这时候其实就是 用户模块的代码中,调用了购物车这个模块的查询功能。但是这两个模块,是两份不同的代码,也是部署到不同的服务器的,所以一定会在用户的模块中,调用一个http的链接,这个链接就是指向购物车模块的查询功能,并将查询到的结果返回给用户模块。
所以: Feign就是可以调用http链接,并且支持SpringMvc的注解,支持与Eureka和Ribbon组合使用以支持负载均衡。
继续 (讲解Hystrix 熔断、限流、降级)
传送门: SpringCloud版本Hoxton SR5 --- 第四讲:Hystrix 熔断、限流(线程)、降级
在大型的微服务项目中,有很多实际会发生的问题:比如:访问的人数太多了,淘宝节那一天晚上,每一台服务器压力都是特别大的。如果服务器压力太大,前面还有无穷无尽的访问进来,而服务器端的响应,比如查询数据库这时候就特别慢。这时候,就会发生雪崩效应。无数的访问进来,得不到及时处理,服务器CPU不堪重负,最终全部死机。淘宝节只能草草落幕,当天晚上就可以上世界新闻了。
Hystrix解决的就是,在访问的过程中,访问超过自定义的时间,访问异常(不管是系统Bug还是数据库超时,mq超时等)立即将该请求中断,防止服务调用端的线程被长时间占用,从而避免故障在分布式架构中蔓延,乃至雪崩。
比如:
访问到一个异常,或者超时了,或者熔断了。就调用一个一定会返回数据的方法。比如降级方法返回:商品没有了,或者系统升级,再或者等一会儿再试,这就叫降级。
与此同时,一定时间范围内该服务被调用一定次数都失败了 并且调用失败率达到配置程度(默认50%),就触发熔断。 当一个微服务调用多次出现问题时(默认是10秒内20次调用失败,这个可以自己配置) 并且调用失败率达到配置程度(默认50%),hystrix就会采取熔断机制,不再继续调用有问题的接口(然后有问题的调用链会在默认5秒钟内,先试探性的先关闭熔断机制,但是如果这时候再(10秒内20次调用失败,失败率达到50%)又会重新进行熔断,直到该服务正常。这个现象就叫熔断。
后面的尝试重连的机制就是 监控起作用。(运用中,其实就是对超时时间、熔断条件的配置)
限流就是限制某个微服务的使用量,这里涉及到线程。比如只允许10个线程同时访问该微服务,其他的请求,访问其他的微服务。并且这项技术,适用于Feign。 也就是远程调用,不单单适用于服务器内部,这就叫限流 。(应用场景:比如某台服务器的性能比较低)
所以: Hystrix就是解决当系统出现不正常情况的时候,让原本要完成的工作,停下来,节约系统资源,防止系统在等待中崩溃。
继续(zuul路由、过滤器、容错与回退)
传送门: SpringCloud版本Hoxton SR5 --- 第五讲:zuul 路由、过滤、容错与回退、集群、高可用
当没有Zuul的时候,我们调用微服务就是这种格式:
http://微服务ID + 接口访问详细路径。 例如:http://SERVER-ORDER/order/query
有了zuul以后,可以这样访问: http:// zuul的ip:zuul的port/zuul配置地址 /order/query (隐藏了微服务的名称)
Zuul会把自己与Eureka整合,并把自己注册成为Eureka服务下的应用,然后获取Eureka中注册上来的所有调用接口,最后,当准备调用服务、接口的时候,直接由zuul完成调用,脱离Eureka的控制。
路由:没有zuul的时候,当我们再调用微服务的时候,几乎都是通过微服务名或者直接ip+端口号来调用的,如果暴露微服务名可能导致黑客 集中火力进攻一部分服务器,导致服务瘫痪,这时候就是用zuul的路由功能做映射,暴露一个集群的统一访问路径,以减轻对服务器的威胁,这就是路由。
过滤:当一个ip或者国外某个地区的ip同时攻击服务器的时候,就可以用zuul的过滤功能,将这些地方的ip限制起来,让其请求还没有进入服务器的时候,被拦截掉,保证系统安全,还或者可以禁用某些客户等。主要就是可以在过滤器里写代码,跟java的过滤器差不多。比如:可以鉴权,过滤ip等等。
* 过滤器(filter)是zuul的核心组件 zuul大部分功能都是通过过滤器来实现的。* <p>* zuul中定义了4种标准过滤器类型,这些过滤器类型对应于请求的典型生命周期如下:* PRE:这种过滤器在请求被路由之前调用。可利用这种过滤器实现身份验证、在 集群中选择请求的微服务、记录调试信息等。* ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服 务的请求,并使用 Apache HttpCIient或 Netfilx Ribbon请求微服务* POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准 的 HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。* ERROR:在其他阶段发生错误时执行该过滤器。
容错与回退:zuul默认是整合了hystrix和ribbon的, 提供降级回退,那如何来使用hystrix呢? 我们自行写一个类,继承FallbackProvider 类,然后重写里面的方法。但是这个降级有点不一样的地方就是,因为zuul这个组件本身设计的位置就决定了,zuul 是在前端调用 与 微服务之间的组件。那么使用zuul的容错回退,相当于对整个系统设置统一的降级方法,所以使用起来要格外注意。
这里的降级,不是针对某一个接口降级,而是对整个微服务,比如:有order和item两个微服务,item微服务没有启动、或者宕机了。
这时候调用item所有接口都会走zuul的降级方法,但是同时order微服务启动是正常的,这时候order微服务的某些接口比如 /order/query 调用的接口有bug。这时候是不会走zuul的降级方法,而是走调用order的降级方法,如果没有配置降级方法,那么一定是404, 调用报错。
继续 (HystrixDashbord 监控)
传送门: SpringCloud版本Hoxton SR5 --- 第六讲:hystrixDashboard监控
上面的例子说了,当访问人数特别特别多的时候,微服务一定也是特别特别多的,一两个运维工程师肯定是不行的,至少也得3-4吧。(开玩笑自嘲一下,目前太多公司没有专门的运维工程师,全都是由程序员解决,导致程序员太多时间浪费在了修电脑上,并且不专业导致系统出问题也是很不应该的)事实上,HystrixDashbord就不该是程序员该管的事,他的作用就是监控,当一个请求进来了,直到请求结束,他监控的是:请求经过了哪些微服务、调用了哪些接口、在哪个微服务出了问题,
所以:HystrixDashbord监控:出问题的频率、成功数、熔断数、请求出错的数量、超时数、延迟统计等等。
spring-cloud config (动态配置)
传送门:SpringCloud版本Hoxton SR5 --- 第七讲:SpringCloud Config 分布式配置中心+整合bus、rabbitmq、actuator
springcloud config解决的就是:比如我们有50个微服务,他们的数据库密码被修改了。现在要修改这50个微服务的数据库密码。
再比如,我们可以在代码里用@Value("xxx")获取配置数据吧,现在配置的xxx的数据值为false,某一天我们要需求变了,这些false要全部修改为true。
通常情况下,是不是打开代码 ?一个一个的修改 ?然后再一个一个的部署 ?至少这个过程是特别麻烦的吧。
而springcloud-config解决的就是这一类的问题。springcloud config 可以在外部修改配置文件(例如:git仓库),代码完全不用修改,然后重新启动一下被修改的微服务就好了。另外springcloud-config有客户端,也有服务端。服务端可以是单独的一个微服务。
他的原理就是:
我们按照一定规则将配置信息写好,保存到本地 或者 git云端。然后部署springcloud-config的服务端,就可以获取 本地 或者 git云端的配置文件。然后所有使用了springcloud-config客户端的微服务,重启一下,就会通过springcloud config服务端拿到git仓库这些配置然后启动微服务。在git仓库中的配置,还可以分环境部署(dev/test/pro/uat等)非常的方便,使用起来更加轻松,不需要程序员自己打开代码一个一个修改,运维工程师,可以直接修改git仓库里的配置,然后重启服务器就好了。 这就是spring-cloud-config 可以完成的一些主要功能。
有没有感觉上面的springcloud config并没有想象中的那么好 ? 我还需要重启服务器 ?那我还不如就在代码里改了,然后上传到git仓库,然后用Jenkins自己去git仓库获取代码,完成自动部署啊。
当然如果在代码里修改配置,还需要编译,打包,这也是不理智的。但是重启服务器,有点不开心。修改数据库配置,我重启服务器,我能接受,但是修改一个简单的controller里需要的属性,还要重启,就不是很开心。
这时候又有了另一个技术。springcloud的消息总线 : SpringCloud Bus 这个消息总线呢,又需要整合消息组件 (kafka/rabbitmq,springcloud他有专门整合kafka和rabbitmq的包)还有spring的 spring-boot-starter-actuator 组件(其实springcloud config动态修改配置的功能,就是actuator组件触发的,并且用的是post调用一个http地址,调用成功之后没有返回值)。写到这里我真的想吐槽springcloud了。太特么麻烦了。你直接集成好了不好吗 ?还要劳资去集成,组件多的一箩筐,学习成本也太大了吧。他的这个原理呢:上面不是说了么,springcloud config的服务端是用来读取git仓库中配置的。springcloud config客户端是用来读取 springcloud config服务端在git中获取到的配置信息。那这个消息总线bus呢,需要添加到所有使用了springcloud config客户端的微服务中去,还要配置mq的ip、端口、用户名密码。配置好了之后,所有微服务还要配置 spring-boot-starter-actuator,他的这个作用就好比监控,当调用某一个使用了springcloud config+bus+actuator的微服务的 http://ip:端口/actuator/bus-refresh 这个地址的时候 ,就通过消息总线给mq发送一条信息,然后呢,其他所有使用bus消息总线的的微服务,都会通过mq收到一条命令,这个命令就是告诉所有使用了springcloud config的客户端,需要修改配置了,你去获取配置。这还没完,上面只是说,各个微服务已经拿到了修改的配置,还需要指定某个类,是否使用这个更改了的配置,这时候还需要在修改的类上加@RefreshScope注解,表示如果配置修改了,这个类,及时使用修改过的配置。
使用起来就简单多了:当在git仓库修改好配置后,直接使用post请求调用一个 http://localhost:8080/actuator/bus-refresh 这个地址,springcloud config的动态配置就完成了。上面那个http://localhost:8080/actuator/bus-refresh的localhost:8080,必须是任意一个使用了springcloud config + bus +actuator的微服务的 ip和端口。这样springcloud config的动态配置的功能才算真正的完成。
最后一个了 (分布式链路跟踪 Sleuth 整合Zipkin +Elasticsearch 做数据持久化 用于查看日志)
传送门:SpringCloud版本Hoxton SR5 --- 第八讲:Sleuth 分布式链路跟踪 整合Zipkin + Elasticsearch持久化
解决的问题:
- 如何串联调用链,快速定位问题
- 如何理清楚,微服务之间的依赖关系
- 如何进行各个服务接口的性能分折
- 如何跟踪业务流的处理
在调用关系复杂的微服务中,如果某个微服务的接口出了问题,要快速的定位到该请求经过哪些微服务,调用了哪些接口,就需要Sleuth 分布式链路跟踪:
比如说当调用开始的时候,会为这个请求生成一个Trace ID(类似UUID的序号),调用过程中,会把这个Trace ID一直传递下去,用于标记该请求,后面可以根据Trace ID找到该请求经过了哪些微服务。
再说该调用链中,比如:A微服务调用B微服的过程,有多个Span ID的标识,比如代码运行A微服务的时候有个Span ID,A微服务调用B微服务的网络请求过程中也会有一个Span ID,B微服务代码执行的过程也会有一个Span ID,最后可以通过这些ID计算出执行时间。用于调优。
Spring Cloud Sleuth可以追踪10种类型的组件:async、Hystrix,messaging,websocket,rxjava,scheduling,web(Spring MVC Controller,Servlet),webclient(Spring RestTemplate)、Feign、Zuul
所以 Sleuth的作用就是记录:请求过程中,调用的每个微服务,请求路径,经过了哪些服务组件等等信息给生成出来。
然后使用Zipkin的客户端将这些信息,发送给Zipkin的服务端,然后Zipkin服务端整合这些数据,并提供UI界面用于查看Sleuth记录的信息。
这里又有一个问题,Zipkin服务端,是将这些信息保存在内存中的,当数据量太大的时候服务器的内存不够用,并且当停掉Zipkin服务端的时候,这些信息就会在内存中被清除。这时候,就使用Elasticsearch保存数据 (这里可以理解为数据库) ,他就将Zipkin整合好的信息,保存在硬盘中(持久化)。
到这里,SpringCloud的组件我就写的差不多了,谢谢观看。
嘿嘿。