Spring Cloud 微服务架构的五脏六腑!

本文涉及的产品
云原生网关 MSE Higress,422元/月
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
注册配置 MSE Nacos/ZooKeeper,118元/月
简介: Spring Cloud 微服务架构的五脏六腑!

Spring Cloud 是一个基于 Spring Boot 实现的微服务框架,它包含了实现微服务架构所需的各种组件。

注:Spring Boot 简单理解就是简化 Spring 项目的搭建、配置、组合的框架。因为与构建微服务本身没有直接关系,所以本文不对 Spring Boot 进行展开。

另外本文有一些例子涉及到 Spring 和 Spring Boot,建议先了解一下 Spring 和 Spring Boot 再阅读本文。

本文的阅读对象主要是没有接触过服务架构,想对其有一个宏观的了解的同学。

本文将从 Spring Cloud 出发,分两小节讲述微服务框架的「五脏六腑」:

第一小节「服务架构」旨在说明的包括两点,一服务架构是什么及其必要性;二是服务架构的基本组成。为什么第一节写服务架构而不是微服务架构呢?原因主要是微服务架构本身与服务架构有着千丝万缕的关系,服务架构是微服务架构的根基。

第二小节「五脏六腑」则将结合 Spring Cloud 这个特例来介绍一个完整的微服务框架的组成。

「服务架构」

为了方便理解,我先讲一个小故事:(改编自一知乎答主)

Martin(微服务提出者也叫 Martin)刚来到公司时是一个基层员工,它上面有经理、老板,那个时候所有人都听老板的指挥。

但是过了两年,公司的人越来越多,原来的模式下整个公司的运作效率太低,管理也很混乱。

于是已经踏上中层岗位的 Martin 建议老板进行部门划分(服务化),专门的部门只做专门的事情(单一职责)。例如研发部门只做研发,人事部门只做招聘。

老板听取了 Martin 的意见,对公司的组织架构进行了调整。

有一天,Martin 发现公司的部门越来越多,各个部门并不能完全知道对方所做的事情,这对跨部门协作(服务调用)带来了困难。

行政部门会(注册中心)来记录所有的部门,每当有新的部门行政都会记录下来(服务注册),然后公布出来让所有部门知道(服务发现)。

在新的组织架构下,公司的效率逐步提高。老板也给 Martin 发了大量奖金作为奖励,Martin 从此赢取白富美走向了人生巅峰。

这是一个公司组织架构演变的故事,主要讲的是随着公司规模的扩大,组织从集中化管理到分布化管理的过程。

映射到我们的信息系统里来也是一样的,随着我们的系统越来越复杂,变得难以管理,也有人想到去拆分然后治理。在解决复杂问题上,分治可以说是一个屡试不爽的办法。

服务化即是拆解的一种手段。而上面圆括号里面的内容其实就对应了一个服务化架构的最小组成元素,分别是服务、服务调用、注册中心、服务注册、服务发现。有了这些基本的组成要素,就可以实现一个最简单的服务架构。

面向服务的架构和微服务架构

面向服务的架构(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://${eureka.instance.hostname}:${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 两个组件可用。什么是服务网关?

路由网关接收了所有的用户请求,有着很高的负载,因此它通常是一个集群。用户的请求会先经过一层负载均衡被发到路由网关。

服务配置与配置中心

在微服务应用中,服务数量巨多,而每个服务不同环境都有着不同的配置,为了方便服务配置文件统一管理,实时更新,所以需要分布式配置中心组件。需要注意的是此处的配置与注册中心注册的配置信息是两个概念,此处的配置是服务本身的一些配置信息,如下图:

b0e2cf33e8d717ed0f3397a4399d08c.png

Spring Cloud 提供了 Spring Cloud Config 组件,它支持配置服务放在配置服务的内存中(即本地),也支持放在远程 Git 仓库中,帮助我们管理服务的配置信息。

信息同步与消息总线

前一个问题讲到了每个服务都有一些配置信息,那么配置信息更新了我们该怎么办,手动一个个去更新?当然不是,Spring Cloud 提供了 Spring Cloud Bus 组件,它通过轻量消息代理连接各个分布的节点。当配置信息更新的时候,我们只要更新一个节点的配置,这个更新就会被广播到这个分布式系统中。

问题定位与链路追踪

在微服务系统中,服务之间可以相互调用,因此我们一个请求可能会一条调用链,而整个系统会存在一张调用网,其中任意一个服务调用失败或网络超时都可能导致整个请求失败。因为调用关系的复杂,这给问题的定位造成了极大的困难,这也是必须提供服务链路追踪的原因。

Spring Cloud 为我们提供了 Spring Cloud Sleuth 组件,它能够跟进一个请求到底有哪些服务参与,参与的顺序是怎样的,从而达到每个请求的步骤清晰可见。借助服务链路追踪,我们可以快速定位问题。

至此,Spring Cloud 的所有基础组件都介绍完了。但是目前所有的组件介绍都是分散的,它们组合起来,完整的样子是什么样的?如下图:

6a04a630f88015f36fd31dc2b37fb30.png

偷懒偷了张图,图中漏掉了 Config Server 和链路追踪组件。但是结合上文的介绍,我们大致可以脑补出这两个东西在图中的位置。Config Server 是一个与所有服务相连的服务集群,链路追踪组件则集成在每个服务中。

小结

服务治理为心脏,路由网关、消息中心、断路器、链路追踪、配置中心等为依托,构造了整个微服务框架的「五脏六腑」。

当然,一个微服务系统远比本文所写的复杂得多,尤其是在不同的业务场景之下,因此想要更深入地了解它就需要我们不断地去实践。而作为前端,我了解这些内容一是为了更好地了解整个请求的流程,二是为了后续在 SOA 中接入 Node 子服务积累相关知识。

最后分享一句有趣的调侃 Spring 的话:在 Spring 中没有什么是一个注解解决不了的,如果有,那么就用两个注解。

来源:webfe.kujiale.com/spring-could-heart/

相关实践学习
SLB负载均衡实践
本场景通过使用阿里云负载均衡 SLB 以及对负载均衡 SLB 后端服务器 ECS 的权重进行修改,快速解决服务器响应速度慢的问题
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
目录
相关文章
|
10天前
|
数据采集 监控 前端开发
二级公立医院绩效考核系统源码,B/S架构,前后端分别基于Spring Boot和Avue框架
医院绩效管理系统通过与HIS系统的无缝对接,实现数据网络化采集、评价结果透明化管理及奖金分配自动化生成。系统涵盖科室和个人绩效考核、医疗质量考核、数据采集、绩效工资核算、收支核算、工作量统计、单项奖惩等功能,提升绩效评估的全面性、准确性和公正性。技术栈采用B/S架构,前后端分别基于Spring Boot和Avue框架。
|
18天前
|
Dubbo Java 应用服务中间件
Spring Cloud Dubbo:微服务通信的高效解决方案
【10月更文挑战第15天】随着信息技术的发展,微服务架构成为企业应用开发的主流。Spring Cloud Dubbo结合了Dubbo的高性能RPC和Spring Cloud的生态系统,提供高效、稳定的微服务通信解决方案。它支持多种通信协议,具备服务注册与发现、负载均衡及容错机制,简化了服务调用的复杂性,使开发者能更专注于业务逻辑的实现。
44 2
|
2月前
|
Cloud Native Java 对象存储
面向未来的架构设计:Spring Cloud和Netflix OSS在云原生环境下的发展趋势
展望未来,随着5G、边缘计算等新技术的兴起,微服务架构的设计理念将会更加深入人心,Spring Cloud和Netflix OSS也将继续引领技术潮流,为企业带来更为高效、灵活且强大的解决方案。无论是对于初创公司还是大型企业而言,掌握这些前沿技术都将是在激烈市场竞争中脱颖而出的关键所在。
60 0
|
2月前
|
Java 对象存储 开发者
解析Spring Cloud与Netflix OSS:微服务架构中的左右手如何协同作战
Spring Cloud与Netflix OSS不仅是现代微服务架构中不可或缺的一部分,它们还通过不断的技术创新和社区贡献推动了整个行业的发展。无论是对于初创企业还是大型组织来说,掌握并合理运用这两套工具,都能极大地提升软件系统的灵活性、可扩展性以及整体性能。随着云计算和容器化技术的进一步普及,Spring Cloud与Netflix OSS将继续引领微服务技术的发展潮流。
48 0
|
26天前
|
Java Spring
Spring底层架构源码解析(三)
Spring底层架构源码解析(三)
|
26天前
|
XML Java 数据格式
Spring底层架构源码解析(二)
Spring底层架构源码解析(二)
|
30天前
|
Kubernetes 安全 微服务
使用 Istio 缓解电信 5G IoT 微服务 Pod 架构的安全挑战
使用 Istio 缓解电信 5G IoT 微服务 Pod 架构的安全挑战
48 8
|
29天前
|
JSON 前端开发 Java
Spring Boot框架中的响应与分层解耦架构
在Spring Boot框架中,响应与分层解耦架构是两个核心概念,它们共同促进了应用程序的高效性、可维护性和可扩展性。
45 3
|
1月前
|
Java 数据库 数据安全/隐私保护
Spring 微服务提示:使用环境变量抽象数据库主机名
Spring 微服务提示:使用环境变量抽象数据库主机名
38 1
|
1月前
|
消息中间件 负载均衡 Cloud Native
云原生之旅:从容器到微服务的架构演变
在数字化转型的风潮中,云原生技术以其灵活性、可扩展性和弹性而备受青睐。本文将通过一个虚拟的故事,讲述一个企业如何逐步拥抱云原生,实现从传统架构向容器化和微服务架构的转变,以及这一过程中遇到的挑战和解决方案。我们将以浅显易懂的方式,探讨云原生的核心概念,并通过实际代码示例,展示如何在云平台上部署和管理微服务。