一、服務註冊與發現: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模式保障分佈式事務
- 可觀測性:整合鏈路追蹤、監控告警體系
通過以上組件的有機結合,可以構建出高可用、可擴展、易維護的微服務架構體系。