定义
微服务是由单一应用程序构成的小服务,拥有自己的进程与轻量化处理,服务依业务功能设计,以全自动的方式部署,与其他服务使用HTTP API通讯。同时,服务会使用最小规模的集中管理 (例如Docker)技术,服务可以用不同的编程语言与数据库等
单体应用的痛点
- 部署效率低下:当单体应用依赖的代码越来越多,依赖的资源越来越多的时候,应用编译打包、部署测试一次,需要的时间比较长,高达10分钟甚至更久
- 团队协作开发成本高:多个分支并行开发,合并需要处理的冲突也较多
- 系统高可用性差:某一功能的问题会影响到整个服务
- 线上发布慢
服务化的思想
把传统的单机应用中通过JAR依赖产生的本地调用,或是同一项目的函数调用,改造为通过RPC接口产生的远程方法调用。RPC:远程过程调用协议,允许程序调用另一个地址空间的函数或过程。
比如微博系统,包括内容模块、消息模块和用户模块,三个模块之间业务相同,代码互相耦合。
考虑把用户模块从单体应用中拆分出来,独立成一个服务部署,以RPC接口的形式对外提供服务。消息和内容模块调用用户接口,从进程内的调用变成远程RPC调用。这样用户模块可以独立开发、测试、上线和运维。
微服务 vs 服务化
- 服务拆分粒度更细:微服务可以看作更细粒度的服务化,小到一个子模块,只要该模块依赖的资源和其他模块无关,就可以拆分为一个微服务
- 服务独立部署:每个微服务都严格遵循独立打包部署的准则,互不影响。比如一台物理机上可以部署多个Docker实例,每个Docker实例可以部署一个微服务的代码
- 服务独立维护
- 服务治理能力要求高:拆分为微服务以后,服务数量变多,需要有统一的服务治理平台,对各个服务进行管理
微服务缺点
- 复杂性增加:系统管理的复杂性增加,每个服务都需要独立的部署、配置和监控;服务间的依赖关系管理变得复杂,需要保证服务之间的兼容性和版本控制
- 通信开销:通过API通信,调用会产生网络延迟;需要额外的基础设施支持服务发现、负载均衡和容错
- 数据一致性问题:数据分散在不同的服务里
- 部署和测试难度
微服务之间通信
同步通信
客户端发送请求以后,等待服务端处理完毕并返回结果,实时性高,但是可能因为服务端处理时间过长而导致客户端阻塞,常见的同步通信协议有HTTP和RPC,RPC性能更高
- 网关:一般基于HTTP协议,使用RESTFUL风格,数据格式为JSON,HTTP方法有GET,POST,PUT,DELETE等,简单且易用
- RPC:远程过程调用协议,允许客户端像调用本地方法一样调用远程服务,通常使用二进制协议。和HTTP相比,有更高的性能和更低的网络开销。常见的RPC框架有gprc、dubbo、brpc、thrift等
异步通信
客户端发送请求后,无需等待服务端处理完毕即可继续执行其他任务,当服务端处理完毕之后,会通过某种方式通知客户端。这种通信方式可以降低系统的耦合度,提高并发度,但是系统的复杂性会增加。常见的异步通信方式有消息队列和事件驱动两种 - 消息队列:生产者将消息发送到队列,消费者从队列里接收消息并处理。常见的中间件有Kafka、RabbitMQ等。
- 事件驱动:一种基于事件的通信方式,允许服务之间通过发布和订阅交互。当某个事件发生时,相关服务会接收到通知并作出相应处理。
消息队列(如RabbitMQ、Kafka) 例子: 在电商系统中,当一个订单被创建后,系统不会直接等待支付、库存扣减等操作完成,而是将这些操作作为消息发送到消息队列中。支付服务、库存服务作为消息的消费者,独立地处理这些消息,完成后更新状态。这种方式下,订单服务与支付、库存服务之间是异步通信的。
事件驱动:例子: 在微服务架构中,当用户完成注册,系统触发一个“用户注册”事件。这个事件被多个服务监听,比如邮件服务接收到事件后发送欢迎邮件,数据分析服务则开始处理新用户的数据分析任务。每个服务根据事件独立工作,无需等待其他服务的响应,实现了服务间的解耦和异步处理。
RPC协议
grpc:
基于HTTP/2协议 使用Protocol Buffers作为接口定义语言合数据序列化格式,支持多种语言,内置身份验证,流式调用支持。.proto文件
dubbo:
阿里巴巴开源,主要面向Java,但是逐渐扩展到多语言支持。支持多种协议,包括Dubbo、HTTP、Triple(兼容grpc)
BRPC:
百度开发,支持HTTP/1.1、HTTP/2、BRPC协议。优化了网络通信和CPU使用,特别适合内部服务间的高效通信。高性能,对C++原生支持极佳,提供了丰富的特性如异步调用、超时控制、重试策略等。
Thrift:
Apache项目,支持多种语言和数据序列化方式,默认使用 TBinaryProtocol,允许定义服务接口和数据结构,生成客户端和服务端代码。.thrift文件
微服务架构的实现方式
微服务架构的实现方式涉及多个方面,以下是基于参考内容和一般实践的详细介绍:
服务拆分
● 业务领域驱动:根据业务功能将应用拆分成独立的服务,每个服务对应一个业务能力,如订单服务、用户服务等。
● 小而自治:每个服务应尽可能小且具有独立的生命周期,能够独立部署和扩展。
服务发现与注册
● 服务注册:服务启动时,向服务注册中心(如Zookeeper、Eureka、Consul)注册自己的地址和元数据。
● 服务发现:其他服务通过服务注册中心查找并调用目标服务,动态地发现和调用服务,支持服务的动态增减。
通信机制
● 同步通信
● 异步通信
配置管理
● 集中式配置:使用如Spring Cloud Config或Consul的配置中心,实现配置的集中管理和动态刷新。
服务治理
● 负载均衡:在服务调用中使用负载均衡策略,如Ribbon、Feign,分散请求到多个实例。
● 熔断与重试:引入如Hystrix进行熔断保护,防止服务雪崩,同时提供重试机制以应对暂时性失败。
数据一致性
● 分布式事务:面对微服务间的事务一致性问题,可采用两阶段提交、补偿事务(Saga)、事务消息等模式。
● 数据隔离:每个服务可能拥有自己的数据库,减少耦合,但需注意数据一致性问题。
安全性
● API Gateway:作为入口,统一处理认证、授权、加密等安全措施。
● 服务间安全通信:使用TLS/SSL加密通信,JWT(JSON Web Tokens)进行安全的身份验证。
监控与日志
● 分布式追踪:如Zipkin、Jaeger,帮助追踪请求在多个服务间的流转。
● 日志管理:集中式日志系统(如ELK Stack)收集、分析服务日志。
持续集成与部署
● CI/CD:自动化构建、测试和部署流程,确保服务快速迭代和稳定发布。
微服务框架
● Spring Cloud、Dubbo、Service Mesh(如Istio、Linkerd)等框架提供了实现微服务架构的工具集,简化了服务发现、配置管理、服务治理等复杂性。
实践建议
● 逐步迁移:从现有系统逐步迁移到微服务架构,避免一次性重构带来的风险。
● 团队结构匹配:微服务的实施往往需要组织结构的相应调整,每个服务应由小团队独立负责。
● 文化转变:强调团队间的沟通与协作,以及对自动化工具的依赖。
通过这些实现方式,微服务架构能够提供高度的灵活性、可扩展性和容错能力,但同时也带来了复杂性管理的挑战,需要团队有较强的DevOps能力和对分布式系统管理的经验。