微服务设计 - 偏向python
2026-01-15 09:16:37 5 举报
AI智能生成
微服务设计是一种架构风格,它主张将单一应用程序开发为一组小型服务,每个服务运行在自己的进程中,并且通常围绕业务能力来组织。这里介绍了选型,注意事项,服务部署。 微服务通常使用轻量级的通信机制如HTTP/REST或MQ传递。微服务强调松耦合和独立部署,每个服务可以由小型跨职能团队独立开发、扩展和更新。 核心内容包括: - 独立的服务粒度 - 服务自治与去中心化治理 - 服务请求,重试,熔断,降级处理 - 弹性与容错性 - 技术多样性和组件化设计
作者其他创作
大纲/内容
微服务理念(Microservices)<br>
微服务是一种架构风格<br>
其核心理念包括<br>
单一职责
每个服务只关注一个业务能力,如用户服务、问答服务、搜索服务等。<br>
服务自治<br>
每个服务可以独立开发、部署、扩展、崩溃而不影响其他服务。<br>
服务间解耦<br>
服务间通过 REST API,gRPC API 或消息(MQ)通信,避免直接代码依赖。<br>
去中心化治理
服务各自拥有自己的数据库、配置、代码生命周期。<br>
技术异构友好 不同服务可以用不同语言/数据库实现(比如 Python + Rust + JS)。<br>
适合的场景
业务功能相对独立:例如用户管理、订单管理、问答主程序、缓存程序,推荐程序,选股程序,实体识别模块,日志等模块,彼此之间没有强烈的依赖。<br><br>部署/扩展需求不同:某些服务需要高频更新,另一些服务更稳定;或者某服务需要高并发处理,而其他服务访问较少。<br><br>技术异构性强:不同服务可能需要使用不同的数据库、语言、框架、性能要求差异大。<br><br>团队规模较大且分工明确:多个团队各自负责不同的服务,提升协作效率。<br>
不合适的场景
不适合微服务的情况(强耦合或上下文紧密)<br><br>强事务一致性要求:比如一个业务流程必须保证跨服务的数据一致性(如下单 + 扣库存 + 支付),若频繁进行分布式事务协调会增加复杂度。<br><br>调用链深度大:多个服务层层嵌套调用(A→B→C→D),容易引发延迟累积、错误传递、调试困难等问题。<br><br>数据模型共享度高:多个服务共用大量表结构,拆分会带来大量重复数据同步和冗余设计。<br>
实现方式(RPC)<br>
RPC(Remote Procedure Call)的本质:<br>
RPC 是一种“调用远程服务像本地函数一样”的编程抽象。
RPC(Remote Procedure Call)的核心目标是让开发者能够像调用本地方法一样调用远程服务,隐藏底层网络通信的复杂性。<br>
HTTP
HTTP RPC 是构建在 HTTP 协议之上的 RPC 实现。
最直接的实现基于 RESTful 理念的 RPC
特点
性能
性能适中
开发体验
多人团队容易上手、调试方便<br>
服务解耦合度
服务耦合度 中(需双方在线)<br>
复杂度
低。技术栈简单,易于理解和调试。
注意事项
✅**统一 API 规范** <br>
约定 JSON 请求/响应格式
"Accept": "application/json"<br>
"Accept": "text/event-stream"
✅**合理使用status_code** <br>
服务端异常 5xx 状态码<br>
尽量不要返回 全篇服务端代码栈错误<br>
客户端请求错误 4xx 状态码<br>
如用户认证错误,客户端请求参数错误
✅**响应一致结构**
其他响应统一返回结构,便于统一处理:<br>
{<br> "code": 0,<br> "msg": "Success.",<br> "data": {<br> "ids": "1",<br> "typing": "单只个股分析"<br> }<br>}
响应错误案例,非0的code码:<br>
{<br>"code":4002,<br>"msg":"没有选股结果",<br>"data":{},<br>"event":"Search",<br>"id":0<br>}
✅**服务健康检查** <br>
每个服务暴露 `/healthz` 接口用于探活
✅**统一日志追踪(Tracing)** <br>
使用 `trace_id` 贯穿所有请求<br>
使用请求重试,请求熔断,请求降级
✅**版本控制** <br>
微服务接口设计应支持多版本(如 `/v1/classifier/`, `/v2/classifier/`)<br>
建议与提升
使用 OpenAPI/Swagger 统一的文档管理
python框架在 HTTP 微服务中的实践<br>
推荐Fastapi, Sanic<br>
使用服务注册与发现 | Consul、Etcd、K8s DNS 或 Envoy 自动发现服务<br>
安全认证 | 采用统一网关进行 Token 验证,服务内部信任 Header 信息,如 OAuth2 / JWT
常见形式
HTTP JSON-RPC(可视为一种轻量 RPC)
特点
统一端点(Single Endpoint)
方便做路由配置,复杂均衡
自描述协议(API Description)
请求自带完整信息,不需要额外的HTTP语义: 做什么, 参数是什么, 请求标识是什么<br>
响应和错误标准化
{"jsonrpc": "2.0", "result": {"answer": 10}, error: null, "id": "req_123"}
真正的优势场景 - 批量操作
服务端设计
定义请求
class JSONRPCRequest(BaseModel):<br> """JSON-RPC 2.0 请求格式"""<br> jsonrpc: str = Field("2.0", const=True)<br> method: str = Field(..., description="要调用的方法名")<br> params: Optional[Union[Dict[str, Any], List[Any]]] = Field(None, description="方法参数")<br> id: Optional[Union[str, int]] = Field(None, description="请求ID,用于匹配响应")<br><br>
定义响应
class JSONRPCResponse(BaseModel):<br> """JSON-RPC 2.0 响应格式"""<br> jsonrpc: str = Field("2.0", const=True)<br> result: Optional[Any] = Field(None, description="方法调用的结果")<br> error: Optional[Dict[str, Any]] = Field(None, description="错误信息")<br> id: Optional[Union[str, int]] = Field(None, description="匹配的请求ID")<br><br>class JSONRPCError(BaseModel):<br> """JSON-RPC 错误对象"""<br> code: int<br> message: str<br> data: Optional[Dict[str, Any]] = None<br><br>
--> {"jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": 1}<br><-- {"jsonrpc": "2.0", "result": 19, "id": 1}
处理请求逻辑
handle_jsonrpc_request
method 案例
handle_requests - jsonrpc_endpoint
客户端设计
JSON-RPC 客户端<br>
JSON-RPC 具体发送请求案例
简单的JSON-RPC实现确实没有完全体现RPC的核心理念。
RPC客户端展示如何隐藏网络细节<br>
客户端代理生成器
gRPC-Web (通常基于 HTTP/2)<br>
HTTP2(基于 HTTP/2 + Protobuf)<br>
但 gRPC-Web 允许浏览器客户端通过 HTTP/1.1 或 HTTP/2 与 gRPC 服务通信。
真正的RPC框架通过代码生成、类型系统等高级技术;使用网络技术,动态代理、才能真正实现"像调用本地方法一样调用远程服务"的体验。
特点
性能
高(压缩 + 多路复用)
开发体验
前期团队配合新协议需要打磨,后期开发加速,自动代码生成<br>
服务解耦合度
低(需定义 proto)<br>
三种设计哲学<br>
服务定义优先(Contract First)<br>
语言中立(Language Agnostic)<br>
同一份 .proto 文件可生成: Python、Java、Go、C++、JavaScript 等客户端和服务端代码
基于 HTTP/2
四种通信模式
一元RPC(Unary RPC)<br>
// 传统请求-响应<br>rpc GetUser(GetUserRequest) returns (UserResponse);
服务器流式RPC(Server Streaming RPC)<br>
// 服务器返回流<br>rpc ListUsers(ListRequest) returns (stream User);
客户端流式RPC(Client Streaming RPC)
// 客户端发送流<br>rpc UploadFile(stream FileChunk) returns (UploadResponse);
双向流式RPC(Bidirectional Streaming RPC)<br>
// 双向流<br>rpc Chat(stream Message) returns (stream Message);
Protocol Buffers 深入理解
Proto3 语法详解
Proto 字段的重要性
实战项目设计
AMQP
MQ 消息队列的通信方式(如基于 RabbitMQ);<br>
特点
性能
通常更高。基于二进制的消息协议,连接复用性好,吞吐量高。
但延迟可能更中等(有中间件的参与)
开发体验
比较复杂,需消息设计
服务解耦合度
高(完全解耦)<br>
复杂度
高。需要引入和维护 MQ 集群,编程模型更复杂。
流程
请求和响应都走 RabbitMQ。<br><br>客户端请求消息 发送到 MQ 的 RPC 队列;<br><br>服务消费者(比如 qa_service)收到消息并处理;<br><br>结果作为响应消息 也通过 MQ 回传;<br><br>调用方收到响应(如果是同步调用,会阻塞等待结果)。<br>
客户端:<br>
生成一个唯一的 correlation_id 和一个临时性的、独占的回复队列(Reply Queue)。<br><br>构造消息,将请求数据、correlation_id 和回复队列的名称(reply_to)一起发送到请求队列。<br><br>在回复队列上等待,只消费 correlation_id 与自己发送的消息匹配的那条响应消息。<br>
服务端:<br>
监听请求队列,消费消息。<br><br>处理业务逻辑。<br><br>将处理结果作为新消息,发送到 reply_to 指定的回复队列中,并设置相同的 correlation_id。
架构分析
在 Nameko 架构中一个 RPC 调用<br>
开始一个简单案例
保证消息正确性
correlation_id 每个请求消息带有唯一 ID,响应消息使用相同 ID 关联<br>
reply_to 字段 每个请求方客户端声明自己的临时响应队列(exclusive queue)<br>
自动 Ack / 重试机制 服务处理成功后会自动 ack,否则消息可重试或入死信队列<br>
Channel 隔离 每个服务使用独立 Channel,避免共享冲突(线程/进程安全)<br>
Timeout 管理 客户端设置超时时间,避免一直等待无响应的请求
请求消息
{<br> "body": [<br> {"user_id": 123}<br> ],<br> "headers": {<br> "nameko.routing_key": "get_user_info",<br> "correlation_id": "rpc-call-7f9d12a4",<br> "reply_to": "rpc.reply.0ee7120f-c880-4937-b7d0-e308ffc8e3a0",<br> "content_type": "application/json"<br> }<br>}<br>
响应消息样例<br>
{<br> "body": "User info of user_id 123",<br> "headers": {<br> "correlation_id": "rpc-call-7f9d12a4"<br> }<br>}
服务间通信
🔵 Consul 功能全、Python 生态好、适合自托管部署<br>
特点
所有服务注册到 Consul Server,服务通过 Consul 查找其他服务<br>
🧭 服务发现 自动注册服务,支持 HTTP 查询其他服务实例<br>
🔍 健康检查 HTTP 或 TCP 方式定期检查服务状态<br>
🗺️ Key/Value 存储 用于存储服务配置、元数据等<br>
🌐 DNS 接入 提供 DNS 接口支持域名解析式发现服务<br>
🔐 多数据中心支持 原生支持跨数据中心的服务同步<br>
💬 Consul Connect 实现服务之间的加密通信(Service Mesh)
缺点
需要集成
需要代理逻辑
配置复杂度中等
安装<br>
docker单节点
注册发现
注册服务到 Consul<br>
import requests<br><br>def register_service():<br> url = "http://localhost:8500/v1/agent/service/register"<br> service_data = {<br> "ID": "user-service-1",<br> "Name": "user-service",<br> "Address": "127.0.0.1",<br> "Port": 8000,<br> "Check": {<br> "HTTP": "http://127.0.0.1:8000/health",<br> "Interval": "10s"<br> }<br> }<br> requests.put(url, json=service_data)<br>
查询服务地址<br>
<br>def discover_service(name="user-service"):<br> url = f"http://localhost:8500/v1/catalog/service/{name}"<br> resp = requests.get(url)<br> data = resp.json()<br> if data:<br> return data[0]["ServiceAddress"], data[0]["ServicePort"]
FastAPI 集成 Consul 示例<br>
Sanic API 集成Consul<br>
🟢 Kubernetes DNS 最推荐,简洁、无需额外组件,自动服务注册与发现<br>
原生的服务注册与发现机制
<b>原生集成 不需要引入第三方如 Consul、Etcd 等服务注册组件</b>
✅ 自动注册 所有 Service 和 Pod 一创建即自动注册 DNS<br>
✅ DNS 命名一致 统一通过 http://<service-name> 就可访问,命名简洁<br>
DNS 解析 所有服务默认在 cluster.local 域名下自动注册<br>
✅ 自动负载均衡 DNS + kube-proxy 自动做负载均衡
Service Kubernetes 的服务抽象,负载均衡访问 Pod<br>
✅ 高可用 CoreDNS 是集群内置组件,自动冗余部署
Headless Service 不进行负载均衡,返回所有 Pod IP(用于客户端做负载)<br>
环境变量注入 Pod 启动时会注入服务地址(不推荐用于动态场景)
缺点
需要项目环境又成熟的运维人员<br>
需要又成熟的生成级别k8s集群
注册发现
自动通过yalm文件配置后实现
案例
案例
服务间通信(示例代码)<br>order-service 调用 user-service:<br><br>@app.route("/order/<user_id>")<br>async def get_order(request, user_id):<br> url = f"http://user-service:8000/user/{user_id}" # 使用 service name 直接访问<br> async with ClientSession() as session:<br> async with session.get(url) as resp:<br> user_data = await resp.json()<br> ...<br>无需使用 Consul!Kubernetes 会自动解析 user-service 这个名字,做负载均衡并转发请求。
案例结构
k8s/<br>├── user-service/<br>│ ├── deployment.yaml<br>│ └── service.yaml<br>├── order-service/<br>│ ├── deployment.yaml<br>│ └── service.yaml<br>├── auth-service/<br>│ ├── deployment.yaml<br>│ └── service.yaml<br>
部署步骤
1. 编写 Dockerfile(构建镜像)
2. 编写 Kubernetes 部署文件
deployment.yaml<br>
service.yaml<br>
3. 使用 kubectl 部署<br>
kubectl apply -f user-service/deployment.yaml<br>
kubectl apply -f user-service/service.yaml
4. 服务间通信(例如 order-service 调用 user-service)<br>
在 Sanic / FastAPI 中配置:<br><br>url = "http://user-service:8000/user/123"
使用脚本批量部署<br>
kubectl apply -f k8s/user-service/<br>kubectl apply -f k8s/order-service/<br>kubectl apply -f k8s/auth-service/<br>
其他注意事项
🔴 Eureka/ZooKeeper 更重,不推荐用于 Python 轻量微服务除非混合架构需要
0 条评论
下一页