版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
微服务架构实战指南
服务拆分·通信·治理分模块
从单体到微服务的完整落地方法论
10大章节·60+代码示例·100条最佳实践
微服务实战系列
目录
第一章微服务架构概述与演进
第二章服务拆分方法论与实战
第三章服务通信机制详解
第四章服务注册与发现
第五章配置中心与动态配置
第六章API网关设计
第七章服务容错与治理
第八章分布式事务与数据一致性
第九章可观测性与全链路监控
第十章实战案例与常见问题速查
微服务架构实战指南·服务拆分/通信/治理分模块
第一章微服务架构概述与演进
1.1从单体到微服务
单体架构是软件系统最原始的形态:所有功能模块打包在一个应用中,共享同一个数据库,统一部署。这种架
构在系统规模较小、团队人数较少时效率很高:开发简单、部署方便、调试容易。但当业务复杂度增长、团队规模
扩大时,单体的弊端就暴露出来:代码库庞大难以维护、编译部署耗时、扩展只能整体扩展、技术栈难以升级、团
队协作冲突频繁。
微服务架构的核心思想是把一个大系统拆分为多个小服务,每个服务独立开发、独立部署、独立扩展。服务
之间通过轻量级通信机制(通常是HTTP/RPC)交互。这种架构带来的好处是:每个服务可以独立演进、可以按需
扩展、故障可以隔离、团队可以独立协作。
但微服务不是银弹。它引入了新的复杂度:分布式系统的固有复杂度(网络不可靠、部分失败)、服务治理的
复杂度(注册发现、配置管理、链路追踪)、运维的复杂度(部署、监控、扩缩容)。很多团队在微服务化的过程
中走了弯路,把原本简单的系统搞得复杂无比。微服务化的核心不是"拆",而是"如何拆得合理、如何治理得好"。
1.2微服务架构的演进路径
阶段特征用户规模技术栈
单体应用单一代码库、单一数据库<10万SpringBoot/Django
垂直拆分按业务线拆分应用10万-100万多应用+主从复制
服务化按业务能力拆分服务100万-1000万Dubbo/SpringCloud
微服务细粒度服务+完整治理1000万-1亿K8s+Istio+全家桶
服务网格服务治理与业务解耦>1亿Istio/Linkerd
1.3微服务架构的核心组件
微服务架构全景图:
┌─────────────────────────────────────────────────┐
│客户端层│
│App/Web/小程序/第三方│
└────────────────────┬────────────────────────────┘
│
┌────────────────────▼────────────────────────────┐
│API网关│
│路由/鉴权/限流/熔断/日志│
└────────────────────┬────────────────────────────┘
│
┌────────────────────▼────────────────────────────┐
│业务服务层│
│┌──────┐┌──────┐┌──────┐┌──────┐│
││用户││订单││商品││支付││
││服务││服务││服务││服务││
│└──────┘└──────┘└──────┘└──────┘│
└────────────────────┬────────────────────────────┘
│
┌────────────────────▼────────────────────────────┐
│基础设施层│
│┌──────────┐┌──────────┐┌──────────┐│
││注册中心││配置中心││链路追踪││
││Nacos││Nacos││Jaeger││
│└──────────┘└──────────┘└──────────┘│
│┌──────────┐┌──────────┐┌──────────┐│
││消息队列││缓存││数据库││
││Kafka││Redis││MySQL││
│└──────────┘└──────────┘└──────────┘│
└─────────────────────────────────────────────────┘
1.4微服务vs单体:如何选择
维度单体架构微服务架构
开发效率初期高,后期低初期低,后期高
部署复杂度简单复杂
扩展能力整体扩展按需扩展
故障隔离差好
技术异构困难容易
运维成本低高
适用规模小团队、小系统大团队、大系统
推荐场景MVP、创业初期业务复杂、团队分工
微服务不是越早越好:很多团队在业务还没跑通、团队不到10人的时候就引入微服务,结果把自己拖入了
分布式系统的泥潭。微服务的价值只有在系统规模和团队规模达到一定程度时才体现出来。一般来说,当出现
以下信号时,才考虑微服务化:代码库超过50万行、团队超过20人、编译部署超过30分钟、不同模块的扩展
需求差异明显、需要技术栈异构。
1.5微服务的四大核心挑战
挑战一:服务拆分。拆得太粗,达不到微服务的价值;拆得太细,运维成本剧增。如何找到合适的粒度,是
微服务设计的第一个难题。需要综合考虑业务边界、数据边界、团队边界。
挑战二:服务通信。服务之间如何通信?同步还是异步?用HTTP还是RPC?如何处理超时、重试、幂等?
网络不可靠是分布式系统的根本假设,通信设计必须考虑各种失败场景。
挑战三:服务治理。服务数量增加后,如何管理?注册发现、配置管理、限流熔断、链路追踪、灰度发布,
这些都是治理范畴。没有好的治理,微服务会变成"分布式单体"。
挑战四:数据一致性。单体时代,一个数据库事务就能保证一致性。微服务时代,数据分散在多个服务中,
如何保证跨服务的数据一致性?这是分布式系统最难的问题之一。
第二章服务拆分方法论与实战
2.1服务拆分的核心原则
服务拆分的本质是找到业务的高内聚边界,把相关的功能聚在一起,把不相关的功能分开。好的拆分让服
务之间低耦合、高内聚;坏的拆分让服务之间相互依赖、牵一发而动全身。
原则说明违反后果
单一职责一个服务只做一件事服务臃肿、难以维护
高内聚低耦合相关功能聚集、无关功能分离服务之间依赖复杂
数据独立服务拥有自己的数据数据耦合、难以演进
业务能力对齐按业务能力划分而非技术分层服务边界不合理
团队匹配服务边界与团队边界一致协作成本增加
适度粒度不过粗也不过细过粗无价值、过细难运维
演进式拆分先粗后细、逐步演进一次拆太细难落地
2.2拆分方法论:DDD领域驱动设计
领域驱动设计(Domain-DrivenDesign,DDD)是微服务拆分的核心方法论。它通过对业务领域的深入分析,找
到业务的边界,进而指导服务拆分。
DDD核心概念:
【领域Domain】
-核心域:业务的核心竞争力所在
-支撑域:支持核心业务,但不直接产生价值
-通用域:通用能力,可以购买或复用
【子域Subdomain】
-将领域进一步细分,每个子域对应一个业务能力
-示例:电商领域→商品子域、订单子域、支付子域
【限界上下文BoundedContext】
-子域的边界,边界内的模型有明确的含义
-同一个词在不同上下文中可能有不同含义
-示例:"商品"在商品上下文是SKU,在订单上下文是订单项
【聚合Aggregate】
-一组相关对象的集合,作为数据修改的单元
-聚合根是外部访问的唯一入口
-示例:订单聚合=订单+订单项+收货地址
【领域事件DomainEvent】
-领域中发生的重要事件
-用于服务之间的异步通信
-示例:OrderCreated、PaymentCompleted
2.3实战:电商系统的服务拆分
电商系统服务拆分示例:
【业务分析】
核心域:交易(下单、支付、履约)
支撑域:商品、用户、营销
通用域:消息、日志、配置
【限界上下文识别】
1.用户上下文:用户注册、登录、信息管理
2.商品上下文:商品管理、库存、价格
3.订单上下文:订单创建、状态流转、查询
4.支付上下文:支付发起、回调、退款
5.营销上下文:优惠券、活动、促销
6.履约上下文:发货、物流、签收
【服务拆分结果】
┌──────────────────────────────────────┐
│用户服务(User)│
│-用户注册/登录│
│-用户信息管理│
│-权限管理│
└──────────────────────────────────────┘
┌──────────────────────────────────────┐
│商品服务(Product)│
│-商品信息管理│
│-库存管理│
│-价格管理│
└──────────────────────────────────────┘
┌──────────────────────────────────────┐
│订单服务(Order)│
│-订单创建│
│-订单状态管理│
│-订单查询│
└──────────────────────────────────────┘
┌──────────────────────────────────────┐
│支付服务(Payment)│
│-支付发起│
│-支付回调│
│-退款处理│
└──────────────────────────────────────┘
┌──────────────────────────────────────┐
│营销服务(Marketing)│
│-优惠券管理│
│-活动管理│
│-促销规则│
└──────────────────────────────────────┘
┌──────────────────────────────────────┐
│履约服务(Fulfillment)│
│-发货管理│
│-物流跟踪│
│-签收确认│
└──────────────────────────────────────┘
【服务依赖关系】
订单服务→商品服务(查商品、扣库存)
订单服务→用户服务(查用户)
订单服务→营销服务(核销优惠券)
订单服务→支付服务(发起支付)
支付服务→订单服务(支付结果通知)
履约服务→订单服务(订单状态更新)
2.4拆分粒度判断
判断维度拆不拆
业务独立性业务能力独立强关联、经常一起变化
数据独立性数据模型独立共享数据、事务强相关
团队独立性有独立团队负责同一团队维护
扩展需求扩展需求差异大扩展需求一致
变更频率变更频率差异大变更频率相近
技术异构需要不同技术栈技术栈统一
2.5拆分的常见错误
错误一:按技术分层拆分。把系统拆成Controller服务、Service服务、DAO服务。这是最典型的反模式,把
原本在一个进程内的调用变成了跨网络调用,性能急剧下降,且没有任何业务价值。
错误二:拆得太细。每个实体一个服务,导致服务数量爆炸。一个简单的业务操作需要调用十几个服务,链
路长、延迟高、故障点多。业界经验是:一个服务由2-5人团队负责,代码量在1万-10万行之间。
错误三:共享数据库。多个服务访问同一个数据库。这看似"方便",实则是最严重的问题:数据库成为耦合
点,任何表结构变更都影响多个服务,无法独立演进。
错误四:循环依赖。A服务调用B,B服务又调用A。这会导致启动依赖、部署耦合、故障传播。应该通过事
件驱动或提取公共逻辑来打破循环。
错误五:忽略分布式事务。拆分时只考虑业务功能,不考虑数据一致性。拆分后发现原本一个事务能搞定的
事情,现在需要分布式事务,复杂度陡增。
拆分的正确姿势:从粗到细,先按业务线拆分(比如电商的商详、购物车、订单),再按业务能力细分(比
如订单拆成订单创建、订单查询、订单履约)。不要一上来就追求细粒度,先跑通,再根据实际情况调整。拆
分的边界不是固定的,可以随着业务发展重新调整。
第三章服务通信机制详解
3.1通信方式全景
服务通信是微服务架构的基础设施。选择合适的通信方式,需要考虑:性能要求、可靠性要求、耦合度要求、
团队技术栈。
分类方式特点典型场景
同步通信REST/HTTP简单通用、生态好对外API、简单调用
gRPC高性能、强类型、支持流内部服务、高性能场景
GraphQL灵活查询、减少请求BFF层、前端聚合
异步通信消息队列解耦、削峰、异步异步任务、事件驱动
事件流持续处理、实时数据管道、实时计算
Webhook反向通知支付回调、事件通知
3.2RESTvsgRPC深度对比
对比维度REST/HTTPgRPC
协议HTTP/1.1或HTTP/2HTTP/2
数据格式JSON(文本)Protobuf(二进制)
性能中等高(快5-10倍)
类型安全弱强(编译时检查)
流式支持SSE/WebSocket原生支持双向流
浏览器支持原生需要grpc-web
可读性好(文本)差(二进制)
生态极丰富良好
适用场景对外API、简单调用内部服务、高性能
#gRPC服务定义(.proto文件)
syntax="proto3";
packageorder;
//定义服务
serviceOrderService{
//简单RPC
rpcGetOrder(GetOrderRequest)returns(OrderResponse);
//服务端流
rpcListOrders(ListOrdersRequest)returns(streamOrderResponse);
//客户端流
rpcBatchCreate(streamCreateOrderRequest)returns(BatchResponse);
//双向流
rpcSyncOrders(streamSyncRequest)returns(streamSyncResponse);
}
//定义消息
messageGetOrderRequest{
int64order_id=1;
int64user_id=2;
}
messageOrderResponse{
int64order_id=1;
stringorder_no=2;
int64user_id=3;
repeatedOrderItemitems=4;
doubletotal_amount=5;
OrderStatusstatus=6;
int64created_at=7;
}
messageOrderItem{
int64product_id=1;
stringproduct_name=2;
int32quantity=3;
doubleprice=4;
}
enumOrderStatus{
PENDING=0;
PAID=1;
SHIPPED=2;
DELIVERED=3;
CANCELLED=4;
}
#Go服务端实现
func(s*orderServer)GetOrder(ctxcontext.Context,req*pb.GetOrderRequest)
(*pb.OrderResponse,error){
order,err:=s.repo.FindByID(ctx,req.OrderId)
iferr!=nil{
returnnil,status.Errorf(codes.NotFound,"ordernotfound:%v",err)
}
returnconvertToProto(order),nil
}
#Java客户端调用
ManagedChannelchannel=ManagedChannelBuilder
.forAddress("order-service",9090)
.usePlaintext()
.build();
OrderServiceGrpc.OrderServiceBlockingStubstub=
OrderServiceGrpc.newBlockingStub(channel);
OrderResponseresponse=stub.getOrder(
GetOrderRequest.newBuilder()
.setOrderId(123L)
.setUserId(456L)
.build()
);
3.3通信可靠性设计
#通信可靠性核心机制
##机制一:超时控制
#任何跨服务调用都必须设置超时
#超时时间要根据业务特点设置,不能太长也不能太短
#Java示例:OkHttp超时
OkHttpClientclient=newOkHttpClient.Builder()
.connectTimeout(1,TimeUnit.SECONDS)//连接超时
.readTimeout(3,TimeUnit.SECONDS)//读超时
.writeTimeout(3,TimeUnit.SECONDS)//写超时
.callTimeout(5,TimeUnit.SECONDS)//总超时
.build();
#Go示例:context超时
ctx,cancel:=context.WithTimeout(context.Background(),3*time.Second)
defercancel()
resp,err:=client.GetOrder(ctx,req)
iferr!=nil{
iferrors.Is(err,context.DeadlineExceeded){
//超时处理
}
}
##机制二:重试策略
#重试必须满足:幂等、有退避、有上限
#非幂等操作(如创建订单)不要自动重试
defcall_with_retry(func,max_retries=3,base_delay=0.1):
"""带指数退避的重试"""
forattemptinrange(max_retries+1):
try:
returnfunc()
exceptRetryableErrorase:
ifattempt==max_retries:
raise
delay=base_delay*(2**attempt)
delay=delay*(0.5+random.random())#抖动
time.sleep(delay)
exceptFatalError:
raise#不可重试的错误直接抛出
#重试注意事项:
#1.只重试可恢复的错误(网络超时、5xx)
#2.不重试客户端错误(4xx)
#3.重试次数要有限制(避免雪崩)
#4.使用指数退避+抖动(避免惊群)
##机制三:幂等性保证
#任何可能被重试的操作都必须幂等
#方案一:唯一键约束
CREATETABLEorders(
idBIGINTPRIMARYKEY,
order_noVARCHAR(32)UNIQUE,--唯一约束
...
);
#方案二:幂等表
CREATETABLEidempotent_record(
idempotent_keyVARCHAR(64)PRIMARYKEY,
resultTEXT,
created_atTIMESTAMP
);
defcreate_order(request):
#检查是否已处理
record=idempotent_repo.find(request.idempotent_key)
ifrecord:
returnrecord.result#返回上次的结果
#处理业务
result=do_create_order(request)
#记录幂等
idempotent_repo.save(request.idempotent_key,result)
returnresult
#方案三:状态机
#状态只能单向流转,已完成的不能再执行
defupdate_order_status(order_id,new_status):
order=find_order(order_id)
iforder.status==new_status:
return#已经是目标状态,直接返回
ifnotcan_transition(order.status,new_status):
raiseInvalidTransition()
#执行状态变更
...
3.4异步通信与消息队列
#消息队列使用场景与最佳实践
##场景一:异步解耦
#下单成功后需要:发短信、加积分、通知物流、更新报表
#同步方式:串行调用,任一失败影响下单
#异步方式:发消息,下游各自消费
#生产者
defcreate_order(user_id,items):
order=save_order(user_id,items)
kafka.send("order.created",{
"order_id":order.id,
"user_id":user_id,
"amount":order.amount,
"items":items,
"timestamp":time.time()
})
returnorder
#消费者(独立部署)
@kafka_consumer("order.created")
defsend_sms(message):
sms_service.send(message["user_id"],"订单创建成功")
@kafka_consumer("order.created")
defadd_points(message):
points_service.add(message["user_id"],int(message["amount"]/10))
@kafka_consumer("order.created")
defnotify_logistics(message):
logistics_service.create_delivery(message["order_id"])
##场景二:削峰填谷
#秒杀活动瞬时流量是平时的100倍
defseckill(user_id,product_id):
#快速校验
ifnotcheck_seckill_eligibility(user_id,product_id):
return{"code":400,"msg":"无资格"}
#入队
kafka.send("seckill.requests",{
"user_id":user_id,
"product_id":product_id,
"timestamp":time.time()
})
return{"code":200,"msg":"排队中"}
#消费者按处理能力消费
@kafka_consumer("seckill.requests",max_poll_records=100)
defprocess_seckill(messages):
formessageinmessages:
try:
ifinventory_service.deduct(message["product_id"]):
order_service.create(message["user_id"],message["product_id"])
exceptExceptionase:
#失败重试或进入死信队列
send_to_dlq(message,e)
##消息可靠性保证
#生产者:ack机制
producer.send(topic,message,acks="all")#等待所有副本确认
#消费者:手动提交offset
defconsume():
whileTrue:
messages=consumer.poll(timeout_ms=1000)
formsginmessages:
try:
process(msg)
mit(msg)#处理成功才提交
exceptException:
#不提交,下次重新消费
pass
##消息顺序性保证
#同一分区内消息有序
#按业务键选择分区
producer.send(
topic="order.events",
key=str(order_id),#同一订单的消息进同一分区
value=message
)
3.5通信协议选型决策树
通信协议选型决策:
开始
│
├─是否需要对外暴露?
│├─是→REST/HTTP
│└─否→继续
│
├─是否对性能要求极高?
│├─是→gRPC
│└─否→继续
│
├─是否需要流式通信?
│├─是→gRPC/WebSocket
│└─否→继续
│
├─是否需要解耦、削峰?
│├─是→消息队列
│└─否→继续
│
├─是否前端聚合多个后端?
│├─是→GraphQL/BFF
│└─否→REST/HTTP
│
└─最终选择
第四章服务注册与发现
4.1为什么需要服务注册发现
在微服务架构中,服务实例的地址是动态变化的:服务扩容时增加实例、缩容时减少实例、故障时实例下线、
升级时实例重启。如果客户端硬编码服务地址,就无法适应这些变化。服务注册与发现机制解决了这个问题:服务
启动时把地址注册到注册中心,客户端从注册中心获取可用服务列表,并在服务变化时及时更新。
4.2注册中心核心能力
能力说明重要性
服务注册服务启动时注册自身信息核心
服务发现客户端查询可用服务列表核心
健康检查检测服务实例是否存活核心
变更推送服务列表变化时通知客户端重要
负载均衡提供客户端负载均衡重要
元数据管理存储服务的版本、环境等信息辅助
4.3主流注册中心对比
注册中心一致性健康检查CAP特点
Nacos支持AP/CP切换心跳+主动探测AP为主功能全,阿里开源
EurekaAP心跳APNetflix开源,成熟
ConsulCP主动探测CPHashiCorp出品
ZooKeeperCP会话CP强一致,运维复杂
etcdCP租约CPK8s默认
4.4Nacos实战
#Nacos服务注册与发现
##服务端启动
#单机模式
shstartup.sh-mstandalone
#集群模式
shstartup.sh-mcluster
#访问控制台
#http://localhost:8848/nacos
##SpringCloud集成
#application.yml
spring:
application:
name:order-service
cloud:
nacos:
discovery:
server-addr:localhost:8848
namespace:production
group:DEFAULT_GROUP
cluster-name:beijing
metadata:
version:v1.0
env:prod
#启用服务注册
@SpringBootApplication
@EnableDiscoveryClient
publicclassOrderApplication{
publicstaticvoidmain(String[]args){
SpringApplication.run(OrderApplication.class,args);
}
}
##服务调用
@RestController
publicclassOrderController{
@Autowired
privateRestTemplaterestTemplate;
@Autowired
privateDiscoveryClientdiscoveryClient;
@GetMapping("/order/{id}")
publicOrdergetOrder(@PathVariableLongid){
//方式一:通过服务名调用(推荐)
Stringurl="http://product-service/product/"+id;
Productproduct=restTemplate.getForObject(url,Product.class);
//方式二:手动获取实例
Listinstances=
discoveryClient.getInstances("product-service");
ServiceInstanceinstance=instances.get(0);
Stringurl2="http://"+instance.getHost()+":"+
instance.getPort()+"/product/"+id;
returnorder;
}
}
##负载均衡策略
#配置负载均衡规则
@Configuration
publicclassLoadBalancerConfig{
@Bean
publicIRuleloadBalancerRule(){
//加权轮询
returnnewWeightedResponseTimeRule();
//可选:
//RoundRobinRule-轮询
//RandomRule-随机
//RetryRule-重试
//BestAvailableRule-最少连接
//ZoneAvoidanceRule-区域感知
}
}
##健康检查
#客户端心跳配置
spring:
cloud:
nacos:
discovery:
heartbeat-interval:5000#心跳间隔(ms)
heart-beat-timeout:15000#心跳超时(ms)
ip-delete-timeout:30000#实例删除超时(ms)
##服务降级与容错
@FeignClient(
name="product-service",
fallback=ProductFallback.class
)
publicinterfaceProductClient{
@GetMapping("/product/{id}")
ProductgetProduct(@PathVariableLongid);
}
@Component
publicclassProductFallbackimplementsProductClient{
@Override
publicProductgetProduct(Longid){
//降级返回默认值
returnProduct.defaultProduct();
}
}
4.5健康检查机制
#健康检查三种模式
##模式一:客户端心跳
#服务实例定期向注册中心发送心跳
#注册中心在超时后剔除实例
#SpringCloud配置
eureka:
instance:
lease-renewal-interval-in-seconds:30#心跳间隔
lease-expiration-duration-in-seconds:90#过期时间
#优点:简单
#缺点:网络抖动可能误判
##模式二:服务端主动探测
#注册中心定期探测服务实例的健康端点
#Consul配置
{
"service":{
"name":"order-service",
"port":8080,
"check":{
"http":"http://localhost:8080/health",
"interval":"10s",
"timeout":"3s",
"deregister_critical_service_after":"1m"
}
}
}
#优点:准确
#缺点:增加注册中心负担
##模式三:混合模式
#心跳+主动探测,兼顾准确性和效率
##健康检查端点设计
@RestController
publicclassHealthController{
@Autowired
privateDataSourcedataSource;
@Autowired
privateRedisTemplateredisTemplate;
@GetMapping("/health/live")
publicResponseEntityliveness(){
//存活检查:进程是否还在运行
returnResponseEntity.ok().build();
}
@GetMapping("/health/ready")
publicResponseEntityreadiness(){
//就绪检查:是否准备好接收流量
Mapstatus=newHashMap<>();
//检查数据库
try{
dataSource.getConnection().isValid(1);
status.put("database","UP");
}catch(Exceptione){
status.put("database","DOWN");
returnResponseEntity.status(503).body(status);
}
//检查Redis
try{
redisTemplate.opsForValue().get("health-check");
status.put("redis","UP");
}catch(Exceptione){
status.put("redis","DOWN");
returnResponseEntity.status(503).body(status);
}
returnResponseEntity.ok(status);
}
}
第五章配置中心与动态配置
5.1为什么需要配置中心
在微服务架构中,配置管理面临几个挑战。第一,配置项分散:几十个服务,每个服务有自己的配置文件,修
改配置需要逐个修改。第二,环境差异:开发、测试、生产环境的配置不同,需要分别管理。第三,动态调整:数
据库连接池大小、限流阈值、开关配置等,需要在不重启服务的情况下动态调整。第四,敏感信息:数据库密码、
API密钥等敏感配置,不能明文存储在代码库中。
5.2配置中心核心能力
能力说明
集中管理所有配置在一个地方管理
环境隔离不同环境使用不同配置
动态更新配置变更实时推送到服务
版本管理配置变更可追溯、可回滚
权限控制控制谁可以修改哪些配置
加密存储敏感配置加密存储
5.3Nacos配置中心实战
#Nacos配置中心使用
##配置格式
#DataID:order-service-prod.yaml
#Group:DEFAULT_GROUP
#命名空间:production
#配置内容
server:
port:8080
tomcat:
max-connections:10000
threads:
max:200
min-spare:20
spring:
datasource:
url:jdbc:mysql://prod-db:3306/order
username:order_user
password:ENC(encrypted_password)
hikari:
maximum-pool-size:20
minimum-idle:5
connection-timeout:30000
redis:
host:prod-redis
port:6379
password:ENC(encrypted_password)
lettuce:
pool:
max-active:50
max-idle:10
min-idle:5
#业务配置
order:
timeout-minutes:30#订单超时时间
max-items:100#最大商品数
auto-cancel:true#自动取消
notification:
sms-enabled:true
email-enabled:false
#限流配置
rate-limit:
enabled:true
default-qps:1000
apis:
-path:/api/order/create
qps:500
-path:/api/order/query
qps:2000
##SpringCloud集成
#bootstrap.yml(优先级高于application.yml)
spring:
application:
name:order-service
cloud:
nacos:
config:
server-addr:localhost:8848
namespace:production
group:DEFAULT_GROUP
file-extension:yaml
refresh-enabled:true#开启动态刷新
shared-configs:#共享配置
-data-id:common.yaml
refresh:true
-data-id:datasource.yaml
refresh:false
##动态刷新配置
@RestController
@RefreshScope#支持配置动态刷新
publicclassOrderController{
@Value("${order.timeout-minutes:30}")
privateinttimeoutMinutes;
@Value("${order.max-items:100}")
privateintmaxItems;
@Autowired
privateOrderPropertiesorderProperties;
@GetMapping("/config")
publicMapgetConfig(){
Mapconfig=newHashMap<>();
config.put("timeoutMinutes",timeoutMinutes);
config.put("maxItems",maxItems);
returnconfig;
}
}
#配置类绑定
@Component
@ConfigurationProperties(prefix="order")
@RefreshScope
publicclassOrderProperties{
privateinttimeoutMinutes=30;
privateintmaxItems=100;
privatebooleanautoCancel=true;
privateNotificationnotification=newNotification();
//gettersandsetters
publicstaticclassNotification{
privatebooleansmsEnabled=true;
privatebooleanemailEnabled=false;
//gettersandsetters
}
}
5.4配置加密与安全
#敏感配置加密方案
##方案一:Jasypt加密
#添加依赖
com.github.ulisesbocchio
jasypt-spring-boot-starter
3.0.5
#加密配置值
java-cpjasypt-1.9.3.jar\
f.cli.JasyptPBEStringEncryptionCLI\
input="my_password"\
password="master_key"\
algorithm="PBEWithMD5AndDES"
#输出:ENC(encrypted_value)
#配置文件
spring:
datasource:
password:ENC(encrypted_value)
#启动时提供主密钥
java-jarapp.jar\
-Djasypt.encryptor.password=master_key
##方案二:Vault集成
#配置Vault
spring:
cloud:
vault:
host:vault-server
port:8200
scheme:https
authentication:TOKEN
token:${VAULT_TOKEN}
kv:
enabled:true
backend:secret
default-context:order-service
#Vault中存储
vaultkvputsecret/order-service\
db.password=my_password\
redis.password=redis_password
#使用
@Value("${db.password}")
privateStringdbPassword;
##方案三:K8sSecret
apiVersion:v1
kind:Secret
metadata:
name:order-service-secret
type:Opaque
data:
db-password:
redis-password:
---
apiVersion:apps/v1
kind:Deployment
spec:
template:
spec:
containers:
-name:order-service
env:
-name:DB_PASSWORD
valueFrom:
secretKeyRef:
name:order-service-secret
key:db-password
5.5配置管理最佳实践
配置分类管理:通用配置、环境配置、服务配置、敏感配置分开管理
配置命名规范:{服务名}-{环境}.{格式},如order-service-prod.yaml
配置版本控制:所有配置变更记录版本,支持回滚
配置变更审计:记录谁在什么时候修改了什么配置
配置灰度发布:新配置先在小范围验证,再全量推送
配置监控告警:配置变更时发送通知
敏感配置加密:密码、密钥等必须加密存储
配置降级预案:配置中心不可用时的兜底方案
第六章API网关设计
6.1API网关的定位
API网关是微服务架构的统一入口,所有外部请求都经过网关路由到内部服务。网关承担了横切关注点的处
理:认证、鉴权、限流、熔断、日志、监控。把这些问题从业务服务中抽离出来,让业务服务专注于业务逻辑。
6.2网关核心功能
功能说明重要性
路由转发根据
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 运维管理系统项目分析方案
- APCUPS电源Silcon客户工程师培训
- 幻灯片演示技术动画课件
- 焦虑健康宣教
- 汗蒸健康注意事项
- 2026年实验室安全知识题库及参考答案
- 糖尿病酮症酸中毒急诊救治共识
- 2026司炉试题库及参考答案
- 糖尿病下肢动脉病变共识
- 高中二年级数学“微探究:与椭圆有关的轨迹问题”教学设计
- 2026酒店艺术品陈设价值提升与文化营销报告
- 2026 年校园口腔健康科普全国爱牙日课件
- 2026中国农产品质量安全追溯体系建设与实施效果报告
- 2026年东莞市属国有企业招聘笔试试题(含答案)
- 2026中国医疗服务行业现状供需问题及投资风险评估规划分析报告
- AQ 3026-2026《化工企业设备检修作业安全规范》中国化学品安全协会解读
- 虚拟电厂接入侧电能计量管理规范
- 2025年河南水利二级造价师计量与计价实务真题及参考答案
- 公司业务暂停申请书模板
- 事务所内控制度
- 《焙烤食品加工技术》高职全套教学课件
评论
0/150
提交评论