微服务简述
单体架构和微服务架构的区别?
最显著的区别看上去就是单体架构用的同一个数据库,微服务架构用的各自的数据库
- 单体架构:
- 所有功能模块(如用户管理、订单处理、支付等)都紧密耦合在一个代码库中。
- 模块之间通过函数调用或类依赖进行交互。
- 微服务架构:
- 每个功能模块被拆分为独立的服务,服务之间通过轻量级协议(如HTTP/REST、gRPC)通信。
- 服务之间松耦合,独立开发、部署和扩展。
微服务架构典型特征
微服务架构是一种将单体应用拆分为多个小型、独立服务的架构风格。每个服务专注于特定的业务功能,并通过轻量级协议(如HTTP/REST、gRPC、消息队列)进行通信。
1. 服务独立性
- 单一职责:
- 每个服务负责一个独立的业务功能,例如用户管理、订单处理、支付等。
- 独立部署:
- 服务可以独立部署和升级,不会影响其他服务。
- 独立技术栈:
- 每个服务可以使用不同的技术栈(如Python、Java、Node.js),根据业务需求选择最适合的技术。
2. 松耦合
- 服务间通信:
- 服务之间通过API(如RESTful API、gRPC)或消息队列(如Kafka、RabbitMQ)进行通信,避免紧密耦合。
- 数据隔离:
- 每个服务有自己的数据库或数据存储方案,避免数据耦合。
3. 可扩展性
- 水平扩展:
- 可以通过增加服务实例来处理更多的请求,例如通过Kubernetes自动扩展服务实例。
- 按需扩展:
- 只需扩展需要更多资源的服务,而不是整个应用。
4. 弹性与容错性
- 故障隔离:
- 一个服务的故障不会影响其他服务,系统可以通过熔断、重试等机制提高容错性。
- 自我修复:
- 微服务架构通常与容器编排工具(如Kubernetes)结合使用,可以实现服务的自动重启和恢复。
5. 持续交付
- CI/CD流水线:
- 每个服务都有自己的CI/CD流水线,可以快速迭代和部署。
- 自动化测试:
- 每个服务都有独立的单元测试和集成测试,确保代码质量。
6. 集中式管理
- 服务注册与发现:
- 使用服务注册中心(如Eureka、Consul、Zookeeper)来管理服务的注册和发现。
- 配置管理:
- 使用配置中心(如Spring Cloud Config、Nacos)来集中管理服务的配置。
7. 分布式追踪
- 调用链监控:
- 使用分布式追踪工具(如Zipkin、Jaeger)来监控服务间的调用链,便于排查问题。
微服务核心机制
微服务架构中,服务注册、服务发现和服务间通信是核心机制,它们共同确保服务能够动态发现、调用彼此,实现分布式系统的高效运行。
- 服务注册是服务实例向注册中心上报自身信息的过程。(服务启动时向注册中心登记自己的网络位置和元数据。)
- 服务发现是调用方从注册中心查询目标服务实例的过程。
- 服务间通信是服务通过同步或异步方式交换数据的过程。
- 微服务架构通过服务注册、发现和通信机制,实现了服务的高可用性、可扩展性和弹性。
1. 服务注册
定义
- 服务注册是服务启动时,将自身的元数据(如IP地址、端口号、服务名称等)注册到服务注册中心的过程。
- 服务注册中心是一个集中式组件,用于存储所有可用服务的实例信息。
实现方式
- 客户端注册:服务实例在启动时,主动向注册中心发送注册请求。
- 示例:Spring Cloud Eureka、Consul。
- 服务端注册:通过外部工具(如Kubernetes、Docker Swarm)自动将服务实例信息写入注册中心。
流程
- 服务启动时,读取配置文件(如服务名称、端口号)。
- 调用注册中心的API(如
/register
),提交自身信息。 - 注册中心将信息存储到内存或数据库中,并返回注册成功响应。
2. 服务发现
定义
- 服务发现是服务调用方在需要调用其他服务时,从服务注册中心查询目标服务的实例信息的过程。
- 服务发现机制使调用方能够动态获取服务实例的位置,无需硬编码IP地址。
实现方式
- 客户端发现:调用方直接查询注册中心,获取服务实例列表。
- 示例:Spring Cloud Netflix Ribbon。
- 服务端发现:调用方通过网关或负载均衡器访问服务,网关从注册中心获取服务实例信息。
- 示例:Kubernetes Service、Nginx+Consul。
流程
- 调用方发起服务调用请求(如访问
/users
接口)。 - 调用方查询注册中心,获取目标服务的实例列表(如
user-service
的多个实例)。 - 调用方根据负载均衡策略(如轮询、随机)选择一个实例进行调用。
3. 服务间通信
定义
- 服务间通信是微服务之间通过协议(如HTTP/REST、gRPC、消息队列)进行数据交换的过程。
- 通信方式的选择取决于服务间的关系(同步或异步)和性能需求。
实现方式
- 同步通信:
- RESTful API:基于HTTP协议,使用JSON或XML格式传输数据。
- 示例:调用
user-service
的/users/{id}
接口。
- 示例:调用
- gRPC:基于HTTP/2协议,使用Protocol Buffers进行高效序列化。
- 示例:调用
order-service
的CreateOrder
方法。
- 示例:调用
- RESTful API:基于HTTP协议,使用JSON或XML格式传输数据。
- 异步通信:
- 消息队列:通过中间件(如Kafka、RabbitMQ)解耦服务间的依赖。
- 示例:订单服务向Kafka发送“订单创建”消息,支付服务消费该消息。
- 消息队列:通过中间件(如Kafka、RabbitMQ)解耦服务间的依赖。
流程
- 同步通信流程:
- 调用方根据服务发现结果,选择一个服务实例。
- 调用方通过HTTP客户端(如
curl
、RestTemplate
)或gRPC客户端发起请求。 - 被调用方处理请求并返回响应。
- 异步通信流程:
- 生产者服务将消息发送到消息队列。
- 消费者服务订阅消息队列,接收并处理消息。
4. 示例:用户服务调用订单服务
场景
- 用户服务需要调用订单服务,查询某个用户的订单列表。
步骤
- 服务注册:
- 用户服务和订单服务启动时,分别向Eureka注册中心注册自身信息。
- 服务发现:
- 用户服务需要调用订单服务时,查询Eureka,获取订单服务的实例列表。
- 服务间通信:
- 用户服务选择一个订单服务实例,通过HTTP客户端发送GET请求:
复制代码
GET http://order-service/orders?userId=123
- 订单服务处理请求,返回订单列表。
- 用户服务选择一个订单服务实例,通过HTTP客户端发送GET请求:
异步扩展:
- 如果订单服务需要通知用户服务订单状态更新,可以通过Kafka发送消息:
json复制代码
{
"orderId": "456",
"status": "COMPLETED"
}
- 用户服务订阅Kafka主题,接收并处理订单状态更新消息。