服务公告
微服务:最佳实践
发布时间:2026-04-21 10:01
搞过的人都知道,最烦的是微服务一上线就各种坑:服务之间互相扯皮、配置乱成一锅粥、出了问题根本不知道哪个环节炸了。本教程不讲虚的,直接说怎么把微服务搞稳、搞可靠。一、前言
微服务架构听着高大上,落地全是血泪。服务拆分、注册发现、链路追踪、配置中心,随便哪个环节没做好,生产环境就是灾难。本教程聚焦3个核心最佳实践:服务注册与发现、配置外部化、分布式追踪,这些都是老兵踩坑踩出来的经验。
二、操作步骤
第1步:统一服务注册与发现机制
搞过微服务的都懂,服务多了以后,IP端口全靠人工记是找死。必须上服务注册中心。
使用Consul作为注册中心(CentOS/RHEL)
# 安装Consul
$ yum install -y consul
# 启动Consul Agent(服务器模式)
$ consul agent -server
-bootstrap-expect=1
-node=consul-server-01
-data-dir=/var/lib/consul
-config-dir=/etc/consul.d
-ui=true
-bind=0.0.0.0
-client=0.0.0.0
# 预期输出:
# ==> Starting Consul agent...
# ==> Consul agent running!
# ==> Node name: consul-server-01
# ==> Datacenter: dc1
# ==> Encrypt: a1234b5678c90de...
# ==> Log Level: INFO
# ==> Server: true (bootstrap: false)
# ==> Client Addr: 0.0.0.0
# ==> Cluster Addr: 10.0.1.10使用Consul作为注册中心(Ubuntu)
# 安装Consul
$ apt-get update && apt-get install -y consul
# 启动Consul Agent(服务器模式)
$ consul agent -server
-bootstrap-expect=1
-node=consul-server-01
-data-dir=/var/lib/consul
-config-dir=/etc/consul.d
-ui=true
-bind=0.0.0.0
-client=0.0.0.0
# 预期输出:
# ==> Starting Consul agent...
# ==> Consul agent running!
# ==> Node name: consul-server-01
# ==> Datacenter: dc1
# ==> Encrypt: a1234b5678c90de...
# ==> Log Level: INFO
# ==> Server: true (bootstrap: false)
# ==> Client Addr: 0.0.0.0
# ==> Cluster Addr: 10.0.1.10服务注册后,用以下命令验证注册状态:
# 查看注册的服务列表
$ consul catalog services
# 预期输出:
# consul
# order-service
# payment-service
# user-service
# 查看某个服务的详细信息
$ consul catalog service user-service
# 预期输出:
# Node Address ServiceID ServiceName
# service-node-01 10.0.1.20 user-service-01 user-service
# service-node-02 10.0.1.21 user-service-02 user-service第2步:配置外部化与中心化管理
配置文件散落在各个服务目录里?改个配置要登录十几台机器?必须搞配置中心。
# 在Consul中创建配置
$ consul kv put config/order-service/database/host db-master.internal
$ consul kv put config/order-service/database/port 3306
$ consul kv put config/order-service/database/username db_user
$ consul kv put config/order-service/database/password YOUR_PASSWORD
$ consul kv put config/order-service/database/name orders_db
# 验证配置已写入
$ consul kv get -recurse config/order-service
# 预期输出:
# config/order-service/database/host:db-master.internal
# config/order-service/database/name:orders_db
# config/order-service/database/password:YOUR_PASSWORD
# config/order-service/database/port:3306
# config/order-service/database/username:db_user注意:生产环境中密码必须加密存储,使用Consul的Encryption Key或集成Vault。
第3步:健康检查配置
服务注册上去就不管了?那是给自己挖坑。必须配置健康检查。
# 注册服务时带上健康检查(CentOS/RHEL & Ubuntu通用)
$ consul services register
-name=order-service
-address=10.0.1.30
-port=8080
-check=http://10.0.1.30:8080/health
-check-interval=10s
-check-timeout=5s
# 预期输出:
# Registered service: order-service
# 查看服务健康状态
$ consul services health -service=order-service
# 预期输出:
# Node Service Check Status
# service-node-01 order-service service:order-service passing第4步:实现服务间通信的熔断机制
一个服务挂了把整个系统拖死?Resilience4j熔断器必须安排上。
# 在Spring Boot项目中引入依赖(pom.xml)
$ cat >> pom.xml << 'EOF'
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot2</artifactId>
<version>2.1.0</version>
</dependency>
EOF
# 配置熔断规则(application.yml)
$ cat >> src/main/resources/application.yml << 'EOF'
resilience4j:
circuitbreaker:
instances:
paymentService:
registerHealthIndicator: true
slidingWindowSize: 10
minimumNumberOfCalls: 5
permittedNumberOfCallsInHalfOpenState: 3
automaticTransitionFromOpenToHalfOpenEnabled: true
waitDurationInOpenState: 5s
failureRateThreshold: 50
eventConsumerBufferSize: 10
EOF
# 重启服务后查看熔断状态
$ curl http://order-service:8080/actuator/health
# 预期输出:
# {"status":"UP","components":{
# "circuitBreakers":{"status":"UP","details":{
# "paymentService":{"status":"CLOSED","failureRate":0.0}
# }}
# }}第5步:分布式链路追踪
用户下单失败,问题出在哪个服务?日志追到吐血。必须上链路追踪。
# 安装Jaeger(CentOS/RHEL)
$ yum install -y jaeger
# 启动Jaeger Collector和Query
$ jaeger-all-in-one
--collector.zipkin-port=9411
--query.base-path=/jaeger
# 预期输出:
# 2024/01/15 10:30:00 Starting Jaeger UI on :16686
# 2024/01/15 10:30:00 Receiving zipkin spans on port 9411
# 2024/01/15 10:30:00 Received shutdown signal, exiting...
# 在微服务中配置OpenTelemetry(示例配置)
$ cat >> src/main/resources/application.yml << 'EOF'
spring:
application:
name: order-service
otlp:
tracing:
endpoint: http://jaeger-collector:4317
EOF
# 测试链路追踪
$ curl http://jaeger-query:16686/api/traces?service=order-service
# 预期输出(JSON格式截取):
# {"data":[{
# "traceID":"4bf92f3577b34da6a3ce929d0e0e4736",
# "spans":[{
# "operationName":"/api/orders",
# "serviceName":"order-service",
# "references":[{
# "refType":"CHILD_OF",
# "traceID":"4bf92f3577b34da6a3ce929d0e0e4736",
# "spanID":"a3ce929d0e0e4736"
# }]
# }]
# }]}第6步:配置中心热更新验证
# 修改Consul中的配置(无需重启服务)
$ consul kv put config/order-service/database/max_connections 200
# 验证配置已更新
$ curl http://order-service:8080/actuator/refresh
-H "Content-Type: application/json"
# 预期输出:
# ["config.order-service.database.max-connections"]
# 确认配置已生效
$ curl http://order-service:8080/config/database/max-connections
# 预期输出:
# 200三、常见问题FAQ
Q1: 服务注册了但健康检查一直失败,状态是critical怎么回事?
老手回答:十有八九是健康检查路径配置错了。先用curl手动测一下健康检查URL能不能通:
$ curl -v http://10.0.1.30:8080/health
# 如果返回的不是200,就检查以下几点:
# 1. 防火墙是否放行了端口
# 2. 健康检查端点是否正确实现了
# 3. 服务启动是否真的监听在指定端口
# 检查Consul日志
$ journalctl -u consul -f
# 预期输出:
# agent: Check "service:order-service" status is critical
# agent: Check "service:order-service" failed: Get "http://10.0.1.30:8080/health": dial tcp 10.0.1.30:8080: connect: connection refusedconnection refused就是端口没监听起来,dial timeout就是网络不通或者防火墙拦了。
Q2: 熔断器一直卡在open状态,怎么都切不过去?
老手回答:你这是配置没调好。默认参数在生产环境就是扯淡。看几个关键配置:
# waitDurationInOpenState 设太长了
# 改成30秒足够,别设5分钟等死人
# minimumNumberOfCalls 必须达到这个数量才会判断
# 如果你流量太低,一直触发不了判断逻辑
# 检查服务是否真的恢复了
$ curl http://payment-service:8080/actuator/health
# 如果返回UP但熔断还是open,手动重置一下
$ curl -X POST http://order-service:8080/actuator/circuitbreakers/paymentService/reset
# 预期输出:
# Circuit breaker 'paymentService' resetQ3: Jaeger里看不到链路数据,怎么排查?
老手回答:这问题问的人最多。一步步查:
# 1. 检查微服务是否成功上报到Jaeger
$ curl http://jaeger-collector:14268/api/traces?service=order-service
# 如果返回空,说明OpenTelemetry配置没生效
# 2. 检查Jaeger Collector日志
$ docker logs jaeger-collector 2>&1 | tail -20
# 预期输出:
# 2024/01/15 10:45:30 spans received
# 2024/01/15 10:45:30 Archiving trace with 5 spans
# 如果没有收到,说明网络不通或者端口配置错误
# 3. 确认otel-agent是否在跑(如果用了sidecar模式)
$ ps aux | grep otel-agent
# 4. 检查服务日志里有没有上报错误
$ grep -i "tracing\|opentelemetry\|jaeger" /var/log/app.log实在不行就在本地起个all-in-one版本直接看日志,比排查生产环境简单多了。
四、总结
微服务最佳实践核心就三件事:
- 服务注册发现选型要早定:Consul、Etcd、Nacos都可以,但中途换成本极高。
- 配置必须外部化:写在代码里的配置迟早出事,热更新能力必须要有。
- 链路追踪是救命稻草:出问题的时候,没有链路追踪就只能靠玄学。
熔断、重试、超时这三件套必须配齐,别心存侥幸。流量一上来,服务的脆弱性全暴露出来。
延伸阅读
- 《Building Microservices》by Sam Newman - 经典必读
- Consul官方文档:https://developer.hashicorp.com/consul/docs
- Resilience4j官方指南:https://resilience4j.readme.io/
- OpenTelemetry官方文档:https://opentelemetry.io/docs/
相关推荐
上一篇: Monitoring:监控性能优化
下一篇: SVN:分支管理