一文带你理解 Spring Cloud 高并发微服务架构核心理念的五脏六腑
映射到我们的信息系统里来也是一样的,随着我们的系统越来越复杂,变得难以管理,也有人想到去拆分然后治理。在解决复杂问题上,分治可以说是一个屡试不爽的办法。
服务化即是拆解的一种手段。而上面圆括号里面的内容其实就对应了一个服务化架构的最小组成元素,分别是服务、服务调用、注册中心、服务注册、服务发现。有了这些基本的组成要素,就可以实现一个最简单的服务架构。
面向服务的架构和微服务架构
面向服务的架构(SOA)和微服务架构是目前两种主流的服务化架构,都符合上面的例子,也有上面提到的所有组件。这两种服务架构有很多可以讲的,但是与本文的相关性不大,本文不做会过多展开,只简单介绍一下两者的区别。
准确地说微服务是去 ESB(企业服务总线)的 SOA。ESB 借鉴了计算机组成原理中的通信模型 —— 总线,所有需要和外部系统通信的系统,通过 ESB 进行标准化地转换从而消除协议、异构系统之间的差异,这样就可以利用现有的系统构建一个全新的松耦合的异构的分布式系统。微服务架构去掉 ESB,本质上是一种去中心化的思想。
「五脏六腑」
顺着上一节的思路,从最简单、最核心的问题出发,假设服务 A 要调用服务 B,会有什么问题?
服务在哪?(服务治理问题)
怎么调用?(服务调用问题)
这两个是最核心的问题,也是任何微服务框架首要解决的两个问题。
为了解决第一个问题 Spring Cloud 提供了 Eureka、Zookeeper、Cloud Foundry、Consul 等服务治理框架的集成。它们的工作模式是将所有的微服务注册到一个 Server 上,然后通过心跳进行服务健康监测。这样服务 A 调用 B 时可以从注册中心拿到可用的服务 B 的地址、端口进行调用。
第二个服务调用有人可能认为就是一个简单的 HTTP 或者 RPC 调用,不是什么问题。但是在分布式的场景下,服务调用需要考虑的因素会更多。比如一个服务有多个实例,此时请求进来了交给谁处理,请求的负载怎么平衡到各个实例,都是比较棘手的问题。Spring Cloud 提供了两种服务调用的方式:一种是 Ribbon + restTemplate,另一种是 Feign。
其中 Ribbon 是基于 HTTP 和 TCP 客户端的负载均衡器,restTemplate 是 Spring 提供的 Restful 远程调用的模板,两者结合就可以达到远程调用的负载均衡。
而 Feign 是一个更加声明式的 HTTP 客户端,开发者可以像调用本地方法一样调用它,完全感觉不到是远程调用,结合 Ribbon 也可以做负载均衡。
既然两个问题都得到了解决,我们就用一个例子来进一步说明一下,例子包含了微服务中最基本的三个角色(注册中心、服务提供者、服务消费者):
注册中心
注解?@EnableEurekaServer?表示该 Spring Boot 应用是一个注册中心。 @EnableEurekaServer @SpringBootApplication public class EurekaserverApplication { ? ?public?static?void?main(String[] args) { ? ? ? ?SpringApplication.run(EurekaserverApplication.class, args); ? ?} } eureka.client.registerWithEureka: false?和 fetchRegistry: false?来表明自己是一个 eureka server。 server: ?port:?8080 eureka: ?instance: ? ?hostname: localhost ?client: ? ?registerWithEureka: false ? ?fetchRegistry: false ? ?serviceUrl: ? ? ?defaultZone:?http://{server.port}/eureka/ service-hello 服务 注解?@EnableEurekaClient?表示他是一个 Eureka 客户端,它会在注册中心注册自己。 注解?@RestController?表示这是一个控制器,@RequestMapping("/hello")?表示匹配到请求?'/hello'?时会调用该方法进行响应。 @SpringBootApplication @EnableEurekaClient @RestController public?class?ServiceHelloApplication { ? ?public?static?void?main(String[] args) { ? ? ? ?SpringApplication.run(ServiceHelloApplication.class, args); ? ?} ? ?@Value("${server.port}") ? ?String?port; ? ?@RequestMapping("/hello") ? ?public?String?home(@RequestParam?String?name) { ? ? ? ?return?"hello "+name+",i am from port:"?+port; ? ?} } 注册中心的地址为?http://localhost:8080/eureka/,也就是上面我们定义的。服务名为?service-hello,将会被调用者使用。 eureka: ?client: ? ?serviceUrl: ? ? ?defaultZone:?http://localhost:8080/eureka/ server: ?port:?8081 spring: ?application: ? ?name: service-hello
服务消费者 service-ribbon
假设 service-ribbon 端口为 8082,当我们访问 http://localhost:8080/hello 时,HelloControler?接收到请求,并调用?HelloService?中的?helloService?方法,HelloService?中通过定义的?restTemplate?去调用?http://service-hello/hello。此处要注意的是?@LoadBalanced?注解,它表示启用负载均衡。 @SpringBootApplication @EnableDiscoveryClient public class ServiceRibbonApplication { ? ?public?static?void?main(String[] args) { ? ? ? ?SpringApplication.run(ServiceRibbonApplication.class, args); ? ?} ? ? ? ?@Bean ? ?@LoadBalanced ? ?RestTemplate?restTemplate() { ? ? ? ?return?new?RestTemplate(); ? ?} } @Service public?class?HelloService?{ ? ?@Autowired ? ?RestTemplate restTemplate; ? ?public?String?helloService(String name) { ? ? ? ?return?restTemplate.getForObject("http://service-hello/hello?name="+name,String.class); ? ?} } @RestController public?class?HelloControler?{ ? ?@Autowired ? ?HelloService helloService; ? ? ? ?@RequestMapping(value =?"/hello") ? ?public String hello(@RequestParam?String name){ ? ? ? ?return?helloService.helloService(name); ? ?} }
至此其实一个微服务应用的雏形已经搭建出来了,服务治理、服务调用可以说是「五脏六腑」中的「心脏」。
「心脏」的依托
接下来我们要进一步思考的是「五脏六腑」中其余的部分,因为少了它们人也是活不久的。下面通过一个问题或需求对应一个组件的方式进行介绍。
服务“雪崩”与断路器
由于网络等原因,服务并不能保证 100% 可用,如果单个服务出现问题,调用这个服务就会出现线程阻塞,此时若有大量的请求涌入,Servlet 容器的线程资源会被消耗殆尽,导致服务瘫痪。
由于服务与服务之间存在依赖,故障会在调用链路上传播,导致整个微服务系统崩溃,这就是服务故障的“雪崩”效应。
为了解决这个问题,Spring Cloud 提供了对 Hystrix 断路器的集成,当服务调用失败的频次达到一定阈值,断路器将被开启,降级的策略可以开发者制定,一般是返回一个固定值。这样就能够避免连锁故障。
此外 Spring Cloud 还提供 Hystrix Dashboard 和 Hystrix Turbine,帮助我们进行监控和聚合监控。
服务暴露与路由网关
微服务中的服务很多,直接暴露给用户一是不安全,二是对用户不友好。因此在微服务和面向服务的架构中,通常会有一个路由网关的角色,来负责路由转发和过滤。对应到 Spring Cloud 中有 Zuul 和 Gateway 两个组件可用。什么是服务网关?
路由网关接收了所有的用户请求,有着很高的负载,因此它通常是一个集群。用户的请求会先经过一层负载均衡被发到路由网关。
服务配置与配置中心
在微服务应用中,服务数量巨多,而每个服务不同环境都有着不同的配置,为了方便服务配置文件统一管理,实时更新,所以需要分布式配置中心组件。需要注意的是此处的配置与注册中心注册的配置信息是两个概念,此处的配置是服务本身的一些配置信息,如下图:
Spring Cloud 提供了 Spring Cloud Config 组件,它支持配置服务放在配置服务的内存中(即本地),也支持放在远程 Git 仓库中,帮助我们管理服务的配置信息。
信息同步与消息总线
前一个问题讲到了每个服务都有一些配置信息,那么配置信息更新了我们该怎么办,手动一个个去更新?当然不是,Spring Cloud 提供了 Spring Cloud Bus 组件,它通过轻量消息代理连接各个分布的节点。当配置信息更新的时候,我们只要更新一个节点的配置,这个更新就会被广播到这个分布式系统中。
问题定位与链路追踪
在微服务系统中,服务之间可以相互调用,因此我们一个请求可能会一条调用链,而整个系统会存在一张调用网,其中任意一个服务调用失败或网络超时都可能导致整个请求失败。因为调用关系的复杂,这给问题的定位造成了极大的困难,这也是必须提供服务链路追踪的原因。
Spring Cloud 为我们提供了 Spring Cloud Sleuth 组件,它能够跟进一个请求到底有哪些服务参与,参与的顺序是怎样的,从而达到每个请求的步骤清晰可见。借助服务链路追踪,我们可以快速定位问题。
至此,Spring Cloud 的所有基础组件都介绍完了。但是目前所有的组件介绍都是分散的,它们组合起来,完整的样子是什么样的?如下图:
偷懒偷了张图,图中漏掉了 Config Server 和链路追踪组件。但是结合上文的介绍,我们大致可以脑补出这两个东西在图中的位置。Config Server 是一个与所有服务相连的服务集群,链路追踪组件则集成在每个服务中。
小结
服务治理为心脏,路由网关、消息中心、断路器、链路追踪、配置中心等为依托,构造了整个微服务框架的「五脏六腑」。
当然,一个微服务系统远比本文所写的复杂得多,尤其是在不同的业务场景之下,因此想要更深入地了解它就需要我们不断地去实践。而作为前端,我了解这些内容一是为了更好地了解整个请求的流程,二是为了后续在 SOA 中接入 Node 子服务积累相关知识。
最后分享一句有趣的调侃 Spring 的话:在 Spring 中没有什么是一个注解解决不了的,如果有,那么就用两个注解。
这本京东 T8 架构师解析 Spring Cloud 与 Docker 高并发微服务架构核心理念 PDF 给大家分享出来
====================================================
springCloud 是微服务架构的最佳落地方案,满足几乎所有的微服务技术维度要求,它解决的第一个问题就是服务与服务之间的解耦。
作为 java 语言的微服务框架,它依赖于 Spring Boot,有快速开发、持续交付和容易部署的特点,包含的组件非常多,设计到微服务的方方面面。但是,整个核心架构只有一点,即 Rest 服务,整个的配置过程,都是围绕 Rest 完成的,处理对象即服务的提供者和消费者。
内容简介
====
本书从架构设计、应用开发和运维部署三个方面出发,对微服务架构设计的实施进行了全方位的阐述和深入实践,并结合生产实际讲解了 Spring Cloud、Docker 和 Jenkins 等工具的具体使用方法。书中通过一个互联网电商平台实例实现了高并发的微服务架构设计,并通过详细的开发和实施过程,演示了构建一个安全可靠、稳定高效并可持续扩展的系统平台的方法。
第一部分架构篇
=======
**第 1 章微服务架构与
Spring Cloud**
第 2 章微服务架构最佳设计
第 3 章电商平台微服务设计实例
评论