服务公告

服务公告 > 综合新闻 > 微服务:最佳实践

微服务:最佳实践

发布时间: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 refused

connection 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' reset

Q3: 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都可以,但中途换成本极高。
  • 配置必须外部化:写在代码里的配置迟早出事,热更新能力必须要有。
  • 链路追踪是救命稻草:出问题的时候,没有链路追踪就只能靠玄学。

熔断、重试、超时这三件套必须配齐,别心存侥幸。流量一上来,服务的脆弱性全暴露出来。

延伸阅读