SpringCloud是一个基于SpringBoot实现的微服务框架,它包含了实现微服务架构所需的各种组件。
本文将从SpringCloud出发,分两小节讲述微服务框架的「五脏六腑」:
「服务架构」
顺着上一节的思路,从最简单、最核心的问题出发,假设服务A要调用服务B,会有什么问题?
这两个是最核心的问题,也是任何微服务框架首要解决的两个问题。
为了解决第一个问题SpringCloud提供了Eureka、Zookeeper、CloudFoundry、Consul等服务治理框架的集成。它们的工作模式是将所有的微服务注册到一个Server上,然后通过心跳进行服务健康监测。这样服务A调用B时可以从注册中心拿到可用的服务B的地址、端口进行调用。
第二个服务调用有人可能认为就是一个简单的HTTP或者RPC调用,不是什么问题。但是在分布式的场景下,服务调用需要考虑的因素会更多。比如一个服务有多个实例,此时请求进来了交给谁处理,请求的负载怎么平衡到各个实例,都是比较棘手的问题。
SpringCloud提供了两种服务调用的方式:一种是Ribbon+restTemplate,另一种是Feign。其中Ribbon是基于HTTP和TCP客户端的负载均衡器,restTemplate是Spring提供的Restful远程调用的模板,两者结合就可以达到远程调用的负载均衡。
既然两个问题都得到了解决,我们就用一个例子来进一步说明一下,例子包含了微服务中最基本的三个角色(注册中心、服务提供者、服务消费者):
注册中心
注解@EnableEurekaServer表示该SpringBoot应用是一个注册中心。
@EnableEurekaServer@SpringBootApplicationpublicclassEurekaserverApplication{publicstaticvoidmain(String[]args){SpringApplication.run(EurekaserverApplication.class,args);}}eureka.client.registerWithEureka:false和fetchRegistry:false来表明自己是一个eurekaserver。
注解@EnableEurekaClient表示他是一个Eureka客户端,它会在注册中心注册自己。
注解@RestController表示这是一个控制器,@RequestMapping("/hello")表示匹配到请求'/hello'时会调用该方法进行响应。
「心脏」的依托
接下来我们要进一步思考的是「五脏六腑」中其余的部分,因为少了它们人也是活不久的。下面通过一个问题或需求对应一个组件的方式进行介绍。
服务“雪崩”与断路器
由于网络等原因,服务并不能保证100%可用,如果单个服务出现问题,调用这个服务就会出现线程阻塞,此时若有大量的请求涌入,Servlet容器的线程资源会被消耗殆尽,导致服务瘫痪。
由于服务与服务之间存在依赖,故障会在调用链路上传播,导致整个微服务系统崩溃,这就是服务故障的“雪崩”效应。
为了解决这个问题,SpringCloud提供了对Hystrix断路器的集成,当服务调用失败的频次达到一定阈值,断路器将被开启,降级的策略可以开发者制定,一般是返回一个固定值。这样就能够避免连锁故障。
此外SpringCloud还提供HystrixDashboard和HystrixTurbine,帮助我们进行监控和聚合监控。
服务暴露与路由网关
微服务中的服务很多,直接暴露给用户一是不安全,二是对用户不友好。因此在微服务和面向服务的架构中,通常会有一个路由网关的角色,来负责路由转发和过滤。对应到SpringCloud中有Zuul和Gateway两个组件可用。什么是服务网关?
路由网关接收了所有的用户请求,有着很高的负载,因此它通常是一个集群。用户的请求会先经过一层负载均衡被发到路由网关。
服务配置与配置中心
在微服务应用中,服务数量巨多,而每个服务不同环境都有着不同的配置,为了方便服务配置文件统一管理,实时更新,所以需要分布式配置中心组件。需要注意的是此处的配置与注册中心注册的配置信息是两个概念,此处的配置是服务本身的一些配置信息,如下图:
SpringCloud提供了SpringCloudConfig组件,它支持配置服务放在配置服务的内存中(即本地),也支持放在远程Git仓库中,帮助我们管理服务的配置信息。
信息同步与消息总线
前一个问题讲到了每个服务都有一些配置信息,那么配置信息更新了我们该怎么办,手动一个个去更新?当然不是,SpringCloud提供了SpringCloudBus组件,它通过轻量消息代理连接各个分布的节点。当配置信息更新的时候,我们只要更新一个节点的配置,这个更新就会被广播到这个分布式系统中。
问题定位与链路追踪
在微服务系统中,服务之间可以相互调用,因此我们一个请求可能会一条调用链,而整个系统会存在一张调用网,其中任意一个服务调用失败或网络超时都可能导致整个请求失败。因为调用关系的复杂,这给问题的定位造成了极大的困难,这也是必须提供服务链路追踪的原因。
SpringCloud为我们提供了SpringCloudSleuth组件,它能够跟进一个请求到底有哪些服务参与,参与的顺序是怎样的,从而达到每个请求的步骤清晰可见。借助服务链路追踪,我们可以快速定位问题。
至此,SpringCloud的所有基础组件都介绍完了。但是目前所有的组件介绍都是分散的,它们组合起来,完整的样子是什么样的?如下图:
偷懒偷了张图,图中漏掉了ConfigServer和链路追踪组件。但是结合上文的介绍,我们大致可以脑补出这两个东西在图中的位置。ConfigServer是一个与所有服务相连的服务集群,链路追踪组件则集成在每个服务中。
小结
服务治理为心脏,路由网关、消息中心、断路器、链路追踪、配置中心等为依托,构造了整个微服务框架的「五脏六腑」。