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

本文涉及的产品
任务调度 XXL-JOB 版免费试用,400 元额度,开发版规格
MSE Nacos/ZooKeeper 企业版试用,1600元额度,限量50份
云原生网关 MSE Higress,422元/月
简介: Spring Cloud 微服务架构的五脏六腑!

image.pngSpring 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 {
  publicstaticvoidmain(String[] args) {
      SpringApplication.run(EurekaserverApplication.class, args);
  }
}


eureka.client.registerWithEureka: falsefetchRegistry: 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
publicclass ServiceHelloApplication {

  publicstaticvoid main(String[] args) {
      SpringApplication.run(ServiceHelloApplication.class, args);
  }

  @Value("${server.port}")
  String port;
  @RequestMapping("/hello")
  publicString home(@RequestParamString 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 {

  publicstaticvoidmain(String[] args) {
      SpringApplication.run(ServiceRibbonApplication.class, args);
  }
 
  @Bean
  @LoadBalanced
  RestTemplaterestTemplate() {
      returnnewRestTemplate();
  }

}
@Service
publicclassHelloService {

  @Autowired
  RestTemplate restTemplate;

  publicStringhelloService(String name) {
      returnrestTemplate.getForObject("http://service-hello/hello?name="+name,String.class);
  }

}
@RestController
publicclassHelloControler {

  @Autowired
  HelloService helloService;
 
  @RequestMapping(value = "/hello")
  public String hello(@RequestParam String name){
      returnhelloService.helloService(name);
  }

}


至此其实一个微服务应用的雏形已经搭建出来了,服务治理、服务调用可以说是「五脏六腑」中的「心脏」。


「心脏」的依托

接下来我们要进一步思考的是「五脏六腑」中其余的部分,因为少了它们人也是活不久的。下面通过一个问题或需求对应一个组件的方式进行介绍。

服务“雪崩”与断路器

由于网络等原因,服务并不能保证100%可用,如果单个服务出现问题,调用这个服务就会出现线程阻塞,此时若有大量的请求涌入,Servlet容器的线程资源会被消耗殆尽,导致服务瘫痪。

由于服务与服务之间存在依赖,故障会在调用链路上传播,导致整个微服务系统崩溃,这就是服务故障的“雪崩”效应。

为了解决这个问题,Spring Cloud提供了对Hystrix断路器的集成,当服务调用失败的频次达到一定阈值,断路器将被开启,降级的策略可以开发者制定,一般是返回一个固定值。这样就能够避免连锁故障。参考:分布式服务防雪崩熔断器,Hystrix理论+实战。

此外Spring Cloud还提供Hystrix Dashboard和Hystrix Turbine,帮助我们进行监控和聚合监控。

服务暴露与路由网关

微服务中的服务很多,直接暴露给用户一是不安全,二是对用户不友好。因此在微服务和面向服务的架构中,通常会有一个路由网关的角色,来负责路由转发和过滤。对应到Spring Cloud中有Zuul和Gateway两个组件可用。

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

服务配置与配置中心

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

image.png

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

信息同步与消息总线

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

问题定位与链路追踪

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

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

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

image.png

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

小结


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


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

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

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
目录
相关文章
|
2月前
|
数据可视化 Java BI
将 Spring 微服务与 BI 工具集成:最佳实践
本文探讨了 Spring 微服务与商业智能(BI)工具集成的潜力与实践。随着微服务架构和数据分析需求的增长,Spring Boot 和 Spring Cloud 提供了构建可扩展、弹性服务的框架,而 BI 工具则增强了数据可视化与实时分析能力。文章介绍了 Spring 微服务的核心概念、BI 工具在企业中的作用,并深入分析了两者集成带来的优势,如实时数据处理、个性化报告、数据聚合与安全保障。同时,文中还总结了集成过程中的最佳实践,包括事件驱动架构、集中配置管理、数据安全控制、模块化设计与持续优化策略,旨在帮助企业构建高效、智能的数据驱动系统。
176 1
将 Spring 微服务与 BI 工具集成:最佳实践
|
2月前
|
Java 数据库 数据安全/隐私保护
Spring 微服务和多租户:处理多个客户端
本文介绍了如何在 Spring Boot 微服务架构中实现多租户。多租户允许单个应用实例为多个客户提供独立服务,尤其适用于 SaaS 应用。文章探讨了多租户的类型、优势与挑战,并详细说明了如何通过 Spring Boot 的灵活配置实现租户隔离、动态租户管理及数据源路由,同时确保数据安全与系统可扩展性。结合微服务的优势,开发者可以构建高效、可维护的多租户系统。
386 127
|
2月前
|
存储 安全 Java
管理 Spring 微服务中的分布式会话
在微服务架构中,管理分布式会话是确保用户体验一致性和系统可扩展性的关键挑战。本文探讨了在 Spring 框架下实现分布式会话管理的多种方法,包括集中式会话存储和客户端会话存储(如 Cookie),并分析了它们的优缺点。同时,文章还涵盖了与分布式会话相关的安全考虑,如数据加密、令牌验证、安全 Cookie 政策以及服务间身份验证。此外,文中强调了分布式会话在提升系统可扩展性、增强可用性、实现数据一致性及优化资源利用方面的显著优势。通过合理选择会话管理策略,结合 Spring 提供的强大工具,开发人员可以在保证系统鲁棒性的同时,提供无缝的用户体验。
|
2月前
|
消息中间件 Java 数据库
Spring 微服务中的数据一致性:最终一致性与强一致性
本文探讨了在Spring微服务中实现数据一致性的策略,重点分析了最终一致性和强一致性的定义、优缺点及适用场景。结合Spring Boot与Spring Cloud框架,介绍了如何根据业务需求选择合适的一致性模型,并提供了实现建议,帮助开发者在分布式系统中确保数据的可靠性与同步性。
210 0
|
1月前
|
Cloud Native Serverless API
微服务架构实战指南:从单体应用到云原生的蜕变之路
🌟蒋星熠Jaxonic,代码为舟的星际旅人。深耕微服务架构,擅以DDD拆分服务、构建高可用通信与治理体系。分享从单体到云原生的实战经验,探索技术演进的无限可能。
微服务架构实战指南:从单体应用到云原生的蜕变之路
|
1月前
|
监控 Cloud Native Java
Spring Boot 3.x 微服务架构实战指南
🌟蒋星熠Jaxonic,技术宇宙中的星际旅人。深耕Spring Boot 3.x与微服务架构,探索云原生、性能优化与高可用系统设计。以代码为笔,在二进制星河中谱写极客诗篇。关注我,共赴技术星辰大海!(238字)
Spring Boot 3.x 微服务架构实战指南
|
1月前
|
负载均衡 Java API
《深入理解Spring》Spring Cloud 构建分布式系统的微服务全家桶
Spring Cloud为微服务架构提供一站式解决方案,涵盖服务注册、配置管理、负载均衡、熔断限流等核心功能,助力开发者构建高可用、易扩展的分布式系统,并持续向云原生演进。
|
2月前
|
消息中间件 Java Kafka
消息队列比较:Spring 微服务中的 Kafka 与 RabbitMQ
本文深入解析了 Kafka 和 RabbitMQ 两大主流消息队列在 Spring 微服务中的应用与对比。内容涵盖消息队列的基本原理、Kafka 与 RabbitMQ 的核心概念、各自优势及典型用例,并结合 Spring 生态的集成方式,帮助开发者根据实际需求选择合适的消息中间件,提升系统解耦、可扩展性与可靠性。
203 1
消息队列比较:Spring 微服务中的 Kafka 与 RabbitMQ
|
2月前
|
Prometheus 监控 Java
日志收集和Spring 微服务监控的最佳实践
在微服务架构中,日志记录与监控对系统稳定性、问题排查和性能优化至关重要。本文介绍了在 Spring 微服务中实现高效日志记录与监控的最佳实践,涵盖日志级别选择、结构化日志、集中记录、服务ID跟踪、上下文信息添加、日志轮转,以及使用 Spring Boot Actuator、Micrometer、Prometheus、Grafana、ELK 堆栈等工具进行监控与可视化。通过这些方法,可提升系统的可观测性与运维效率。
272 1
日志收集和Spring 微服务监控的最佳实践
|
2月前
|
Java 数据库 数据安全/隐私保护
Spring Boot四层架构深度解析
本文详解Spring Boot四层架构(Controller-Service-DAO-Database)的核心思想与实战应用,涵盖职责划分、代码结构、依赖注入、事务管理及常见问题解决方案,助力构建高内聚、低耦合的企业级应用。
719 1

热门文章

最新文章