从组件的角度梳理微服务技术栈(1)
一、服务注册与发现:Nacos
组件定位:微服务架构里的“服务通讯录+配置大管家”,是整个服务体系的基础。
核心价值:主要解决两个头疼问题——一是服务间“找谁通话”的问题:服务提供方启动后会自动把自己的地址信息登记到Nacos上,消费方不用死记硬背对方地址,随时能查到可用的服务实例;二是配置“散养难管”的问题:把多个服务共用的配置集中放在这里管,还能按开发、测试、生产等环境分开存,改配置不用挨个服务改。而且它能把这些数据存起来不会丢,从根上解决了服务地址写死、配置到处藏的麻烦。
1.1 Nacos部署详解
MySQL表准备
Nacos支持将配置数据持久化到MySQL,需要先创建相关表结构:
-- 创建nacos数据库
CREATE DATABASE nacos CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 使用nacos官方提供的SQL脚本创建表
-- 脚本位置:nacos/conf/nacos-mysql.sql
配置文件详解
custom.env文件配置示例:
# 单机模式运行
MODE=standalone
# 使用MySQL作为数据源
SPRING_DATASOURCE_PLATFORM=mysql
# MySQL连接配置
MYSQL_SERVICE_HOST=192.168.150.101
MYSQL_SERVICE_PORT=3306
MYSQL_SERVICE_DB_NAME=nacos
MYSQL_SERVICE_USER=root
MYSQL_SERVICE_PASSWORD=123456
# 连接池配置
MYSQL_SERVICE_DB_PARAM=characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false
1.2 服务注册与发现机制
服务提供方 vs 消费方配置差异
虽然双方都配置了Nacos地址,但实际作用不同:
服务提供方:
spring:
application:
name: item-service
cloud:
nacos:
server-addr: 192.168.150.101:8848
discovery:
# 服务注册配置
namespace: public
group: DEFAULT_GROUP
# 心跳间隔,默认5秒
heart-beat-interval: 5000
# 健康检查超时时间,默认15秒
heart-beat-timeout: 15000
服务消费方:
spring:
cloud:
nacos:
server-addr: 192.168.150.101:8848
discovery:
# 服务发现配置
server-addr: 192.168.150.101:8848
# 命名空间隔离
namespace: public
# 服务分组
group: DEFAULT_GROUP
核心区别:
- 提供方:注册自身实例信息到Nacos
- 消费方:从Nacos订阅服务列表,获取可用实例
二、服务调用:OpenFeign
组件定位:微服务之间的“智能通信秘书”,专门简化服务间的HTTP调用流程。
核心价值:不用手写复杂的HTTP请求代码,只要给接口加几个注解,就能像调本地方法一样调用其他服务。它还自带负载均衡能力(搭配Spring Cloud LoadBalancer),能自动把请求分到不同的服务实例上,避免某一个实例忙不过来。如果配上OKHttp这类工具做连接池优化,还能减少重复建立TCP连接的开销,既让代码好懂好维护,又能提高调用效率。
2.1 负载均衡策略详解
OpenFeign整合了Ribbon(现为Spring Cloud LoadBalancer)提供负载均衡能力:
三种常用负载均衡策略
1. 轮询策略(RoundRobin)
# 默认策略,按顺序轮流访问服务实例
spring:
cloud:
loadbalancer:
configurations: round-robin
2. 随机策略(Random)
spring:
cloud:
loadbalancer:
configurations: random
3. 权重策略(Weighted)
# 根据实例权重分配流量
spring:
cloud:
loadbalancer:
configurations: weighted
自定义负载均衡配置
@Configuration
public class LoadBalancerConfig {
@Bean
public ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(
Environment environment, LoadBalancerClientFactory factory) {
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
return new RandomLoadBalancer(factory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);
}
}
2.2 连接池化思想
为什么需要连接池?
- 减少TCP握手开销:TCP三次握手耗时约1.5RTT
- 资源复用:避免频繁创建销毁连接
- 连接管理:统一管理连接生命周期
OKHttp连接池配置
feign:
okhttp:
enabled: true
# 连接池配置
max-connections: 200
max-connections-per-route: 50
# 连接超时
connect-timeout: 3000
# 读取超时
read-timeout: 10000
# 写入超时
write-timeout: 10000
连接池参数调优
@Configuration
public class OkHttpConfig {
@Bean
public okhttp3.OkHttpClient okHttpClient() {
return new okhttp3.OkHttpClient.Builder()
.connectionPool(new ConnectionPool(200, 5, TimeUnit.MINUTES))
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.retryOnConnectionFailure(true)
.build();
}
}
三、API网关:Gateway
组件定位:微服务集群的“大门卫+流量调度中心”,所有外部请求都得从它这里进系统。
核心价值:主要干三件事:一是“指路”,把请求精准转发到对应的微服务,比如把下单请求转给订单服务,支付请求转给支付服务;二是“安检”,帮着做登录鉴权、记录请求日志、处理跨域问题,不让非法请求进来;三是“限流”,遇到突发大流量时能控制请求速度,还能修改请求路径、加请求头信息。对前端来说不用记一堆服务地址,对后端来说能把服务藏在网关后面,安全性更有保障。
3.1 网关核心功能详解
路由配置增强
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/user/**
- Method=GET,POST
- Header=X-Request-Id, \d+
- Query=version, v1
filters:
- StripPrefix=1 # 去除路径前缀
- AddRequestHeader=X-Gateway-Request, true
- AddResponseHeader=X-Gateway-Response, true
- PrefixPath=/api # 添加路径前缀
全局过滤器链详解
@Component
public class GlobalFilterChain implements GlobalFilter, Ordered {
private final List<GlobalFilter> filters;
public GlobalFilterChain(List<GlobalFilter> filters) {
this.filters = filters.stream()
.sorted(Comparator.comparingInt(Ordered::getOrder))
.collect(Collectors.toList());
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
return Flux.fromIterable(filters)
.reduce(chain, (currentChain, filter) ->
new GatewayFilterChain() {
@Override
public Mono<Void> filter(ServerWebExchange exchange) {
return filter.filter(exchange, currentChain);
}
})
.filter(exchange);
}
}
3.2 用户信息传递机制
ThreadLocal使用详解
public class UserContext {
private static final ThreadLocal<Long> USER_CONTEXT = new ThreadLocal<>();
public static void setUserId(Long userId) {
USER_CONTEXT.set(userId);
}
public static Long getUserId() {
return USER_CONTEXT.get();
}
public static void clear() {
USER_CONTEXT.remove();
}
}
拦截器配置
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new UserInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/login", "/register");
}
}
public class UserInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) {
String userId = request.getHeader("user-id");
if (userId != null && !userId.trim().isEmpty()) {
try {
UserContext.setUserId(Long.valueOf(userId));
} catch (NumberFormatException e) {
// 记录日志,但不中断请求
log.warn("Invalid user-id header: {}", userId);
}
}
return true;
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler, Exception ex) {
// 必须清理,防止内存泄漏
UserContext.clear();
}
}
四、配置中心:Nacos进阶使用
组件定位:基于Nacos升级的“配置动态管理平台”,专治配置重复、改配置要重启服务的毛病。
核心价值:把多个服务都要用的配置(比如数据库连接信息)抽出来统一管理,不用每个服务都写一遍。支持按环境隔离配置,开发环境改配置不会影响生产环境;最关键的是配置改完能实时生效,不用重启服务,比如改个限流阈值、开关参数,立马就能用。还能监听配置变化,业务需要动态调参时特别方便。
4.1 配置共享原理
配置加载优先级
Spring Cloud配置加载顺序:
bootstrap.yml(最高优先级)- Nacos共享配置(
shared-configs) - Nacos扩展配置(
extension-configs) - 应用专属配置(
spring.application.name) application.yml(最低优先级)
多环境配置管理
# bootstrap.yaml
spring:
application:
name: order-service
profiles:
active: dev # 环境标识
cloud:
nacos:
config:
file-extension: yaml
shared-configs:
- dataId: shared-jdbc-${spring.profiles.active}.yaml
- dataId: shared-log-${spring.profiles.active}.yaml
extension-configs:
- dataId: ${spring.application.name}-${spring.profiles.active}.yaml
group: DEFAULT_GROUP
refresh: true
4.2 配置热更新原理
@ConfigurationProperties工作原理
@ConfigurationProperties(prefix = "business")
@Data
@Component
@RefreshScope // 关键注解,启用配置刷新
public class BusinessProperties {
/**
* 最大数量限制
* 配置示例:business.max-count=100
*/
private Integer maxCount = 10; // 默认值
/**
* 超时时间(毫秒)
*/
private Integer timeout = 3000;
/**
* 是否启用功能
*/
private Boolean enabled = true;
}
配置变更监听机制
@Component
public class ConfigChangeListener {
@Autowired
private BusinessProperties businessProperties;
@EventListener
public void handleRefreshEvent(EnvironmentChangeEvent event) {
// 配置变更时的处理逻辑
log.info("配置发生变化: {}", event.getKeys());
// 重新加载相关配置
reloadBusinessConfig();
}
private void reloadBusinessConfig() {
log.info("当前配置 - maxCount: {}, timeout: {}",
businessProperties.getMaxCount(),
businessProperties.getTimeout());
}
}
五、服务保护:Sentinel
组件定位:微服务的“安全卫士”,专门守护服务不被流量冲垮,保障系统高可用。
核心价值:有三大核心技能:一是限流,比如限制某个接口每秒最多处理100个请求,避免请求太多把服务压崩;二是熔断降级,要是某个依赖的服务挂了,不会一直等着它响应,而是快速返回失败,防止故障像多米诺骨牌一样扩散;三是线程隔离,给每个依赖服务分配独立的线程池,就算A服务故障,也不会占用B服务的资源。支持多种限流和熔断策略,能精准保护每个服务节点。
5.1 Sentinel核心概念详解
请求限流(Flow Control)
限流算法对比:
| 算法 | 特点 | 适用场景 |
|---|---|---|
| 漏桶算法 | 恒定速率处理,平滑流量 | 保护系统不被突发流量冲垮 |
| 令牌桶算法 | 允许突发流量,有弹性 | 保证系统处理能力的同时允许突发 |
| 计数器算法 | 简单粗暴,固定窗口 | 简单限流场景 |
配置示例:
// 资源定义
@SentinelResource(value = "getUserInfo",
blockHandler = "handleBlock",
fallback = "handleFallback")
public UserInfo getUserInfo(Long userId) {
// 业务逻辑
}
// 限流处理
public UserInfo handleBlock(Long userId, BlockException ex) {
log.warn("触发限流保护,userId: {}", userId);
return UserInfo.defaultUser();
}
// 降级处理
public UserInfo handleFallback(Long userId, Throwable ex) {
log.error("服务降级,userId: {}", userId, ex);
return UserInfo.defaultUser();
}
线程隔离(Thread Isolation)
线程池隔离 vs 信号量隔离:
# 线程池隔离配置
spring:
cloud:
sentinel:
filter:
enabled: false
thread-pool:
# 核心线程数
core-size: 20
# 最大线程数
max-size: 50
# 队列容量
queue-capacity: 100
# 线程存活时间
keep-alive-time: 60s
信号量隔离配置:
// 使用@SentinelResource配置信号量隔离
@SentinelResource(value = "queryOrder",
fallback = "queryOrderFallback",
blockHandler = "queryOrderBlockHandler",
// 信号量隔离
execution:
isolation:
strategy: SEMAPHORE
semaphore:
maxConcurrentRequests: 100)
public OrderInfo queryOrder(Long orderId) {
// 业务逻辑
}
服务熔断和降级策略
熔断器三种状态:
- 关闭状态:正常处理请求
- 打开状态:所有请求被熔断,直接降级
- 半开状态:尝试放行部分请求,测试服务是否恢复
熔断策略配置:
// 基于响应时间的熔断
DegradeRule rule = new DegradeRule("resourceName")
.setGrade(RuleConstant.DEGRADE_GRADE_RT) // 响应时间模式
.setCount(100) // 响应时间阈值(ms)
.setTimeWindow(10) // 熔断时间窗口(s)
.setRtSlowRequestAmount(5) // 最小请求数
.setMinRequestAmount(5); // 触发熔断的最小请求数
// 基于异常比例的熔断
DegradeRule rule2 = new DegradeRule("resourceName")
.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO)
.setCount(0.5) // 异常比例阈值(0.5=50%)
.setTimeWindow(10)
.setMinRequestAmount(10);
六、分布式事务:Seata
组件定位:微服务跨服务操作的“数据一致性管家”,解决多个服务操作时“要么都成,要么都败”的问题。
核心价值:比如下单时,要同时扣减库存(库存服务)和扣减余额(用户服务),这两个操作必须同时成功或同时失败,不然就会出现“订单建好了但库存没扣”“钱扣了但订单没生成”的烂账。Seata支持两种模式:AT模式不用改太多代码,自动帮你管事务;TCC模式更灵活,适合复杂业务场景。它通过全局事务协调器,统一指挥各个服务的本地事务提交或回滚,保证跨服务操作的数据一致。
6.1 Seata分布式事务模式
AT模式(自动模式)原理
工作流程:
-
一阶段:
- 解析SQL,生成前后镜像
- 执行业务SQL
- 提交前镜像到undo_log
- 本地事务提交
-
二阶段提交:
- 删除undo_log记录
- 异步清理
-
二阶段回滚:
- 根据undo_log生成反向SQL
- 执行回滚操作
- 删除undo_log记录
配置示例:
@Service
public class OrderService {
@GlobalTransactional // 开启全局事务
public void createOrder(OrderDTO orderDTO) {
// 1. 扣减库存
stockFeignClient.reduceStock(orderDTO.getSkuId(), orderDTO.getCount());
// 2. 创建订单
orderMapper.insert(orderDTO);
// 3. 扣减余额
accountFeignClient.reduceBalance(orderDTO.getUserId(), orderDTO.getAmount());
}
}
TCC模式(手动模式)
Try-Confirm-Cancel三个阶段:
public interface TccOrderService {
@TwoPhaseBusinessAction(name = "createOrder", commitMethod = "confirm", rollbackMethod = "cancel")
boolean tryCreateOrder(BusinessActionContext actionContext,
@BusinessActionContextParameter(paramName = "orderId") Long orderId,
@BusinessActionContextParameter(paramName = "amount") BigDecimal amount);
boolean confirm(BusinessActionContext actionContext);
boolean cancel(BusinessActionContext actionContext);
}
6.2 Seata表结构说明
全局事务表(global_table)
CREATE TABLE `global_table` (
`xid` varchar(128) NOT NULL,
`transaction_id` bigint(20) DEFAULT NULL,
`status` tinyint(4) NOT NULL,
`application_id` varchar(32) DEFAULT NULL,
`transaction_service_group` varchar(32) DEFAULT NULL,
`transaction_name` varchar(128) DEFAULT NULL,
`timeout` int(11) DEFAULT NULL,
`begin_time` bigint(20) DEFAULT NULL,
`application_data` varchar(2000) DEFAULT NULL,
`gmt_create` datetime DEFAULT NULL,
`gmt_modified` datetime DEFAULT NULL,
PRIMARY KEY (`xid`),
KEY `idx_status_gmt_modified` (`status`,`gmt_modified`),
KEY `idx_transaction_id` (`transaction_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
分支事务表(branch_table)
CREATE TABLE `branch_table` (
`xid` varchar(128) NOT NULL,
`branch_id` bigint(20) NOT NULL,
`transaction_id` bigint(20) DEFAULT NULL,
`resource_group_id` varchar(32) DEFAULT NULL,
`resource_id` varchar(256) DEFAULT NULL,
`branch_type` varchar(8) DEFAULT NULL,
`status` tinyint(4) DEFAULT NULL,
`client_id` varchar(64) DEFAULT NULL,
`application_data` varchar(2000) DEFAULT NULL,
`gmt_create` datetime DEFAULT NULL,
`gmt_modified` datetime DEFAULT NULL,
PRIMARY KEY (`branch_id`),
KEY `idx_xid` (`xid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
undo_log表(每个业务数据库)
CREATE TABLE `undo_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`branch_id` bigint(20) NOT NULL,
`xid` varchar(100) NOT NULL,
`context` varchar(128) NOT NULL,
`rollback_info` longblob NOT NULL,
`log_status` int(11) NOT NULL,
`log_created` datetime NOT NULL,
`log_modified` datetime NOT NULL,
`ext` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
七、微服务技术栈整合实践
7.1 完整的微服务架构
前端/客户端
↓
Gateway网关(统一入口、鉴权、限流)
↓
微服务集群
├── 用户服务(Nacos注册 + Config配置)
├── 商品服务(Feign调用 + Sentinel保护)
├── 订单服务(Seata分布式事务)
└── 库存服务(负载均衡 + 熔断降级)
↓
数据层
├── MySQL(主从复制)
├── Redis(缓存)
└── Elasticsearch(搜索)
7.2 最佳实践总结
- 服务治理:Nacos实现服务注册发现和配置管理
- 服务通信:OpenFeign + LoadBalancer实现声明式调用
- 流量控制:Gateway统一入口 + Sentinel多层次保护
- 数据一致性:Seata AT/TCC模式保障分布式事务
- 可观测性:整合链路追踪、监控告警体系
通过以上组件的有机结合,可以构建出高可用、可扩展、易维护的微服务架构体系。

浙公网安备 33010602011771号