资讯动态

微服务基座搭建实战:Nacos注册配置双中心、Sentinel限流熔断与Seata分布式事务落地

发布时间:2026/10/18 16:19:16 来源:尧图企业网站定制
简介采用前后端分离模式基于若依框架的微服务权限管理系统完整代码面向熟悉Spring Boot但需要落地微服务治理的Java后端与前端开发者。项目以Nacos作为注册与配置中心整合Redis认证、Sentinel限流熔断与Seata分布式事务并提供Vue3 Element Plus Vite版本前端适合学习企业级微服务架构与权限模型。资源包共677个文件约132.24MB主体为261个Java源码与89个Vue页面组件另含75个JS脚本、46个XML配置、7个SQL脚本及Dockerfile、yml等部署文件可支撑从后端逻辑到前端页面再到容器化部署的全链路阅读。辅助脚本如bat、sh可快速启动gateway、auth、system等模块便于本地运行调试。目前已有3578人学习下载对需要借鉴若依微服务版设计思路、改造权限与网关模块的开发者有直接参考价值。1. 若依SpringCloud微服务脚手架一个字先把基座调通再谈业务微服务改造这件事绝大多数团队卡住的不是业务代码而是基座没打通注册中心、配置中心、限流熔断、分布式事务、前端权限每一个单独拎出来都有教程一旦凑到一起版本冲突和隐性配置能把人折磨到怀疑人生。这套基于若依SpringCloud的脚手架把Nacos注册配置、Sentinel限流熔断、Seata分布式事务和Vue3前端预先调通业务开发只需要关注自己的模块。适合两类人一是从单体转微服务、想找个能直接跑的框架起步的团队二是想看清这几个组件在真实项目里怎么协作的开发者。本文不聊理论只讲落地。2. Nacos注册配置双中心服务发现与动态刷新怎么落地2.1 为什么选 Nacos 而不是 Eureka Config微服务基座里注册中心和配置中心通常是两个独立组件Eureka负责服务发现Spring Cloud Config负责配置管理。这套脚手架选Nacos核心原因是它把两件事合并了省掉一套独立配置中心的部署和运维成本。另一个现实因素是Nacos原生支持服务端的配置持久化、命名空间隔离和权限控制这些在Eureka Config组合里要么没有要么得自己用数据库或Git仓库去补。Nacos的服务发现走的是AP模型下的注册表机制客户端定时拉取服务实例列表同时通过心跳维持实例健康状态。配置中心走的是服务端推送加客户端长轮询的组合配置变更后客户端能在几秒内感知到。这套机制在中小团队规模下非常够用而且部署简单standalone模式一条命令就能起来不需要额外依赖数据库。2.2 接入Nacosbootstrap.yml 与 namespace 隔离接入Nacos的第一步是引入依赖。每个微服务模块的pom里需要加上注册中心和配置中心的starter这是这套脚手架的基础依赖版本跟随SpringCloud Alibaba的BOM统一管理不需要手写版本号。dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId /dependency dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-starter-alibaba-nacos-config/artifactId /dependency依赖引入后配置写在bootstrap.yml里。这里有个容易踩的坑Nacos配置中心的地址必须放在bootstrap阶段加载如果写在application.yml里服务启动时配置中心还没初始化动态刷新就不会生效。spring: application: name: system-service cloud: nacos: server-addr: 127.0.0.1:8848 username: nacos password: nacos discovery: namespace: dev group: DEFAULT_GROUP config: namespace: dev group: DEFAULT_GROUP file-extension: yaml shared-configs: ->RefreshScope RestController RequestMapping(/api/gateway) public class GatewayConfigController { Value(${gateway.routes.timeout:3000}) private Integer timeout; GetMapping(/timeout) public Integer getTimeout() { return timeout; } }注意RefreshScope只对加了它的Bean生效不会自动刷新所有配置项。比如数据源连接池、线程池这类在启动时创建且不销毁重建的Bean修改配置后不会自动重建需要配合ConfigurationProperties或者专门的刷新逻辑。这套脚手架里公共配置抽成了shared-configs所有服务共享同一个common.yaml改一处全部刷新适合放日志级别、公共开关这类配置。每个服务的独有配置则放在自己的dataId里dataId命名规则是${spring.application.name}.${file-extension}如果文件后缀配成yamldataId就是system-service.yaml。3. Sentinel流量治理限流规则与熔断兜底配置3.1 资源定义与控制台接入Sentinel的核心概念是「资源」它可以是一个方法、一个接口、一段代码块。这套脚手架里网关层和服务层都接入了Sentinel网关负责入口流量控制服务层负责接口级别保护。接入Sentinel需要引入依赖并配置控制台地址控制台用来查看实时流量和推送规则。dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-starter-alibaba-sentinel/artifactId /dependency控制台地址配置在application.yml里。要注意Sentinel客户端默认是懒加载服务启动后如果不访问任何接口控制台是看不到服务节点的先随意请求一次接口再刷新控制台就能看到。spring: cloud: sentinel: transport: dashboard: 127.0.0.1:8858 port: 8719 eager: true参数说明dashboard是控制台地址port是客户端与控制台通信的本地端口如果被占用会自动1为避免端口漂移问题建议固定。eager设为true可以让客户端启动时立即注册到控制台不用等第一次请求。3.2 限流规则QPS阈值与流控效果限流规则定义在控制台上配置后默认存储在内存里这一点后面避坑章节会细说。先看规则本身。Sentinel支持QPS限流和线程数限流两种模式实际项目里QPS限流用得最多。[ { resource: GET:/api/system/user/list, limitApp: default, grade: 1, count: 100, strategy: 0, controlBehavior: 0 } ]参数说明grade1表示按QPS限流count100表示每秒最多100次请求strategy0表示直接按资源本身限流不涉及调用关系controlBehavior0是直接拒绝1是Warm Up预热模式2是排队等待。接口类限流我一般默认用0预热适合秒杀这类冷启动场景排队等待适合容忍延迟的异步场景。代码层面也可以硬编码规则适合规则不容易变化的场景但生产环境建议用规则持久化后面避坑章会给出接Nacos数据源的具体配置方式。3.3 熔断降级慢调用比例与兜底逻辑熔断和限流是两回事。限流管的是流量大小熔断管的是下游服务是否健康。这套脚手架里用的是慢调用比例熔断当一段时间内接口调用超过指定耗时的比例达到阈值熔断器打开后续请求快速失败不再等待下游超时。[ { resource: POST:/api/order/create, grade: 0, count: 500, timeWindow: 10, minRequestAmount: 5, slowRatioThreshold: 0.5 } ]参数说明grade0表示按慢调用比例熔断count500是最大RT阈值毫秒slowRatioThreshold0.5表示超过500ms的请求占比达到50%就触发熔断timeWindow10表示熔断后10秒内快速失败minRequestAmount5是触发熔断的最小请求数避免流量太小时误判。熔断触发后需要有兜底逻辑这套脚手架里的做法是在被保护的方法上写降级函数。兜底方法必须与原方法签名一致返回值类型也要一致否则会启动报错。SentinelResource(value createOrder, fallback createOrderFallback) public Result createOrder(OrderDTO dto) { // 正常业务逻辑 } public Result createOrderFallback(OrderDTO dto, Throwable ex) { return Result.error(服务繁忙请稍后重试); }注意fallback方法可以接收Throwable参数这样能拿到熔断或异常的具体原因。我遇到过一个坑fallback方法返回值类型和原方法不一致时异常被吞掉接口直接返回500空指针排查了很久才定位到是降级函数签名问题。4. Seata分布式事务AT模式的回滚机制与落地配置4.1 三种模式怎么选AT、TCC、SAGASeata支持AT、TCC、SAGA三种事务模式。这套脚手架默认用AT模式原因是侵入性最小业务代码里只需加一个GlobalTransactional注解不需要像TCC那样写confirm和cancel两套方法。AT模式的原理是代理数据源在业务SQL执行前记录数据快照到undo_log表事务提交时根据undo_log的内容反向补偿。三模式选型参考模式侵入性适用场景主要成本AT低单体拆微服务业务代码不想大改每库需建undo_log表性能有一定损耗TCC高对一致性要求极高需要精细控制业务需写try/confirm/cancel三接口SAGA中长事务链路长且允许最终一致需维护状态机补偿逻辑复杂中小团队从单体重构上来的无脑选AT先把分布式事务跑通后续业务确实复杂到需要精细控制再考虑TCC。4.2 AT模式落地undo_log表与全局事务注解AT模式落地前每个参与事务的数据库都要建undo_log表。这张表是Seata回滚的数据源没建这张表事务执行时不会报错但回滚时会静默失败数据就出现部分提交的情况这是数据不一致最常见的隐患。CREATE TABLE undo_log ( id BIGINT NOT NULL AUTO_INCREMENT, branch_id BIGINT NOT NULL, xid VARCHAR(100) NOT NULL, context VARCHAR(128) NOT NULL, rollback_info LONGTEXT NOT NULL, log_status INT NOT NULL, log_created DATETIME NOT NULL, log_modified DATETIME NOT NULL, PRIMARY KEY (id), UNIQUE KEY ux_undo_log (xid, branch_id) ) ENGINE InnoDB AUTO_INCREMENT 1 DEFAULT CHARSET utf8;建好表后在业务入口方法上声明全局事务。这个方法需要是被外部调用的不能是同类内部调用否则Spring AOP代理失效事务完全不生效。Service public class OrderServiceImpl implements OrderService { GlobalTransactional(rollbackFor Exception.class) public void createOrder(OrderDTO dto) { orderMapper.insert(dto); accountClient.decrease(dto.getAccountId(), dto.getAmount()); inventoryClient.decrease(dto.getProductId(), dto.getCount()); } }代码说明GlobalTransactional是Seata的全局事务注解rollbackForException.class表示任何异常都触发回滚。createOrder方法内部调用远程的扣减账户和扣减库存服务如果第二步或第三步抛异常前面已执行的本地SQL也会通过undo_log反向补偿回滚。4.3 全局事务超时与回滚验证Seata默认全局事务超时时间是60秒如果业务链路里有慢SQL或远程调用超时超过这个值事务会被强制回滚接口还会返回一个不太容易看懂的异常。我一般会在application.yml里显式调大超时时间但也不建议调太大太长会导致全局锁持有时间过久并发性能下降。seata: enabled: true application-id: system-service tx-service-group: my_tx_group registry: type: nacos nacos: server-addr: 127.0.0.1:8848 namespace: public config: type: nacos nacos: server-addr: 127.0.0.1:8848 namespace: public service: vgroup-mapping: my_tx_group: default client: tm: default-global-transaction-timeout: 120000部署完成后一定要做一次回滚验证在createOrder方法第二步后面故意抛一个RuntimeException然后查数据库确认订单、账户、库存三张表的数据都没有变化。这个验证动作我在每次环境迁移后都会强制做一遍。5. 常见问题排查路由、鉴权、跨域与规则失效5.1 现象服务之间Feign调用报错Nacos控制台却能看见实例原因有两个一是namespace不一致服务A在dev命名空间服务B在public命名空间Feign查询时从当前服务所在命名空间查不到对方实例列表二是Nacos 2.x版本客户端向服务端上报实例走的是gRPC端口9848防火墙只放通了8848没放通9848注册表数据能上报但实例列表拉取失败。解决检查所有服务的spring.cloud.nacos.discovery.namespace配置确保指向同一个命名空间ID同时放通Nacos服务器的8848和9848端口。这个坑在换服务器环境时特别常见因为本机部署通常不涉及防火墙问题。5.2 现象Sentinel控制台配置的限流规则服务重启后全部丢失原因Sentinel默认规则存储在客户端内存中控制台推给客户端的规则不会持久化到任何存储介质服务重启即失效。解决引入Sentinel的Nacos数据源扩展让规则先从Nacos配置中心拉取控制台的修改通过Nacos作为中间桥梁同步。spring: cloud: sentinel: datasource: flow: nacos: server-addr: 127.0.0.1:8848 >service.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers[Authorization] Bearer token } return config }) service.interceptors.response.use( response response.data, error { if (error.response error.response.status 401) { localStorage.removeItem(token) window.location.href /login } return Promise.reject(error) } )代码说明请求拦截器从localStorage读取token并写入请求头响应拦截器统一处理401token失效时清空缓存并跳回登录页。注意这里的token键名要和登录接口存储时保持一致不一致的话请求拦截器永远拿不到token这个低级错误排查起来很浪费时间。5.5 现象前端调用后端接口报CORS跨域网关和前端都配置了跨域原因网关层和下游服务都配置了CORS响应头浏览器收到两套Access-Control-Allow-Origin或者网关拦截了预检请求后下游的CORS头没有透传导致浏览器判定跨域失败。解决跨域只保留网关层处理下游服务关闭CORS配置。网关的CORS配置需要显式允许预检请求否则OPTIONS请求会被拦截无法继续。spring: cloud: gateway: globalcors: cors-configurations: [/**]: allowed-origin-patterns: - http://localhost:8080 allowed-methods: - GET - POST - PUT - DELETE allowed-headers: * allow-credentials: true参数说明allowed-origin-patterns可以用通配符匹配前端地址注意allow-credentials和allowed-origins不能同时使用通配符否则浏览器会拒绝响应这是Spring Cloud Gateway一个比较隐蔽的约束。6. 进阶本地联调顺序与Sentinel阈值调优经验本地联调时启动顺序有讲究。正确顺序是先基础设施后应用服务具体如下表顺序组件启动方式关键检查点1Nacossh startup.sh -m standalone访问8848控制台正常2Seata Serversh seata-server.sh -p 80918091端口监听正常3Redis / MySQL依本机环境确认连接配置可访问4网关服务java -jar gateway-service.jar路由表加载日志无报错5业务微服务java -jar system-service.jar控制台能看到注册实例6Vue3前端npm run dev浏览器能正常登录这套顺序我每次拉新环境都强制走一遍跳过任何一步都可能出现“服务注册了但调用404”这种难以归因的怪问题。有次我图省事先启动了业务服务结果Seata还没起来全局事务注解全部报错吓得以为代码有问题排查半天才发现是启动顺序反了。Sentinel阈值调优方面我的经验是从小到大逐步加压不要一上来就拍脑袋定1000 QPS。先用一个较低的阈值比如100跑压测观察执行耗时曲线和控制台的实时流量如果系统CPU和内存都很健康再逐步上调每次调完观察半小时。限流阈值没有普适公式不同业务接口的RT和依赖开销差异很大控制台实时监控比理论估算值可靠得多。最后说一个实际教训别在本地改Nacos的namespace来玩隔离本地就用public命名空间环境隔离交给dev、test、prod的环境配置文件去区分。我有个同事把服务注册到自定义命名空间后又改回public结果配置中心里的shared-configs没跟着迁所有服务启动报错找不到配置花了半天才排查出来。从那以后我每次改完命名空间配置都强制核对一遍discovery和config的namespace是否一致。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑