概述
主要包含以下組件
Sentinel 流量控制和服務降級
Nacos 服務注冊與發現
Nacos 分布式配置中心
RocketMQ 消息驅動
Seate 分布式事務
Dubbo RPC通信
OSS 阿里雲對象存儲
springboot自動裝配原理
eg:將redis整合到springboot中:
1.添加starter依賴:spring-boot-starter-data-redis
2.在application.properties中配置redis數據源
3.使用@Autowried引入redisTemplate
4.使用
當使用@Autowried注入redisTemplate實例時.說明IOC容器中已經存在RedisTemplate,這是Springboot自動裝配而來的
所以,存在一個機制,這個機制的實現基於某種約定或者規范,只要Starter組件符合SpringBoot中自動裝配的規范,就能實現自動裝配
自動裝配的實現
自動裝配在SpringBoot中是通過@EnableAutoConfiguration注解開啟的,這個注解聲明在@SpringBootApplication中
@Enable注解:主要作用是把相關組件的Bean轉配到IOC容器中
@Enable注解對JavaConfig進一步完善,常見的@Enable注解有
@EnableWebMvc和@EnableScheduling等
每個@Enable類的注解都包含@Import
@ImportSelector的作用
自動裝配的核心是掃描約定目錄下的文件進行解析,解析完成后把得到的Configuration配置類通過ImportSelector進行導入,從而完成Bean的自動裝配過程
SpringFactoriesLoaderss是Spring內部提供的一種預定俗成的加載方式,類似於Java中的SPI,它會掃描classpath下的METE-INF/spring.factories文件,這個文件的數據由key=value方式存儲
Conditional條件注解
- springboot中的@Conditional做了一些擴展
手工實現一個starter
1.命名規范:
官方: spring-boot-starter-模塊名稱
自定義: 模塊名稱-spring-boot-starter
官方命名模塊名稱放最后,自定義模塊名稱放前面
2.創建一個工程,命名為redis-spring-boot-starter
3.添加jar包依賴
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.11.1</version>
</dependency>
4.定義屬性
@ConfigurationProperties(prefix = "gp.redisson")
public class RedissonProperties {
private String host = "localhost";
private String password;
private int port = 6379;
private int timeout;
private boolean ssl;
public String getHost() {return host;}
public void setHost(String host) {this.host = host;}
public String getPassword() {return password;}
public void setPassword(String password) {this.password = password;}
public int getPort() {return port;}
public void setPort(int port) {this.port = port;}
public boolean isSsl() {return ssl;}
public void setSsl(boolean ssl) {this.ssl = ssl;}
public int getTimeout() {return timeout;}
public void setTimeout(int timeout) {this.timeout = timeout;}
}
5.定義需要自動裝配的配置類,主要是把RedissonClient裝配到IOC容器
@ConditionalOnClass(Redisson.class)表示只有classpath下存在Redisson這個類,RedissonAutoConfiguration 才會實現自動裝配
@Configuration
@ConditionalOnClass(Redisson.class)
@EnableConfigurationProperties(RedissonProperties.class)
public class RedissonAutoConfiguration {
@Autowired
RedissonProperties redissonProperties;
@Bean
RedissonClient redissonClient(){
Config config=new Config();
String prefix="redis://";
if(redissonProperties.isSsl()){
prefix="rediss://";
}
SingleServerConfig singleServerConfig=config.useSingleServer()
.setAddress(prefix+redissonProperties.getHost()+":"+redissonProperties.getPort())
.setConnectTimeout(redissonProperties.getTimeout());
if(!StringUtils.isEmpty(redissonProperties.getPassword())){
singleServerConfig.setPassword(redissonProperties.getPassword());
}
return Redisson.create(config);
}
}
6.在resource下創建METE-INF/spring.factories文件,使得SpringBoot程序可以掃描到該文件完成自動裝配
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.gupaoedu.book.RedissonAutoConfiguration
7.使用的時候,直接添加依賴
<groupId>com.gupaoedu.book</groupId>
<artifactId>redis-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
8.添加屬性
gp.redisson.host=192.168.56.111
gp.redisson.port=6379
springboot集成dubbo
- 生產者
1.啟動方法要加上@DubboComponentScan
2.服務加上@Service注解,該注解是dubbo包下的,不是spring的
3.添加dubbo依賴
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.5</version>
</dependency>
4.加上配置文件
dubbo.application.name=springboot-provider
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
dubbo.registry.address=N/A
- 消費者
聲明服務時使用@Reference注解獲取一個遠程代理對象
@Reference(url = "dubbo://127.0.0.1:20880/com.gupaoedu.book.dubbo.IHelloService")
private IHelloService helloService;
- dubbo使用nacos作為注冊中心
1.依賴nacos組件
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-discovery-spring-boot-starter</artifactId>
<version>0.2.4</version>
</dependency>
2.dubbo注冊地址加上nacos協議
dubbo.registry.address=nacos://192.168.56.111:8848
3.啟動類加上Dubbo注解
@DubboComponentScan
- dubbo使用nacos作為注冊中心
1.依賴nacos組件
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-discovery-spring-boot-starter</artifactId>
<version>0.2.4</version>
</dependency>
2.dubbo注冊地址加上nacos協議
dubbo.registry.address=nacos://192.168.56.111:8848
3.啟動類加上Dubbo注解
@DubboComponentScan
- springcloud使用nacos作為注冊中心
1.引入服務發現依賴
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
</dependency>
2.配置
spring.cloud.nacos.discovery.server-addr=192.168.56.111:8848
Nacos服務注冊與發現實現原理
nacos源碼分析
- 服務注冊
- 服務地址獲取
- 服務地址變化感知
spring-cloud-common中有個ServiceRegistry接口,是服務注冊的標准
package org.springframework.cloud.client.serviceregistry;
public interface ServiceRegistry<R extends Registration> {
void register(R registration);
void deregister(R registration);
void close();
void setStatus(R registration, String status);
<T> T getStatus(R registration);
}
其中一個實現類是NacosServiceRegistry
在spring-cloud-commons包的META-INF/spring.factories中包含自動裝配信息
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.alibaba.cloud.nacos.NacosDiscoveryAutoConfiguration,\
com.alibaba.cloud.nacos.ribbon.RibbonNacosAutoConfiguration,\
com.alibaba.cloud.nacos.endpoint.NacosDiscoveryEndpointAutoConfiguration,\
com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientAutoConfiguration,\
com.alibaba.cloud.nacos.discovery.configclient.NacosConfigServerAutoConfiguration
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
com.alibaba.cloud.nacos.discovery.configclient.NacosDiscoveryClientConfigServiceBootstrapConfiguration
sentinel微服務熔斷和限流
1.限流規則配置
public class FlowRuleInitFunc implements InitFunc{
@Override
public void init() throws Exception {
List<FlowRule> rules=new ArrayList<>();
FlowRule rule=new FlowRule();
rule.setCount(1);
rule.setResource("hello");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setLimitApp("default");
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
}
2.請求方法設置限流注解,增加限流后返回的方法
@RestController
public class HelloController {
@SentinelResource(value = "hello",blockHandler = "blockHandlerHello")
@GetMapping("/say")
public String hello(){
return "hello ,Mic";
}
public String blockHandlerHello(BlockException e){
return "被限流了";
}
}
3.在META-INF.services增加限流類,設置擴展點
com.gupaoedu.book.springcloud.sentinel.springcloudsentinelsample.FlowRuleInitFunc
4.添加限流依賴
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
5.將一類url歸類為一個
@Service
public class CustomerUrlCleaner implements UrlCleaner{
@Override
public String clean(String originUrl) {
if(StringUtils.isEmpty(originUrl)){
return originUrl;
}
if(originUrl.startsWith("/clean/")){
return "/clean/*";
}
return originUrl;
}
}
- Sentinel集成Nacos動態流控規則
1.nacos配置
[{
"resource":"/dynamic",
"limitApp":"default",
"grade":1,
"count":1,
"strategy":0,
"controlBehavior":0,
"clusterMode":false
}]
2.項目配置文件中配置
spring:
application:
name: spring-cloud-sentinel-dynamic
cloud:
sentinel:
transport:
dashboard: 127.0.0.1:7777
datasource:
- nacos:
server-addr: 192.168.56.111:8848
data-id: ${spring.application.name}-sentinel-flow
group-id: DEFAULT_GROUP
data-type: json
rule-type: flow
3.在sentinel控制台可以看到規則
現在不支持在控制台修改規則同步到nacos
可以通過修改源碼,對控制台的curd操作的結果保存到nacos實現將控制台的規則持久化到nacos中
Sentinel工作原理
分布式事務
分布式事務指事務的參與者,支持事務的服務器分別位於不同的節點上
分布式事務常見解決方案:
1.兩階段提交協議
第一階段是事務准備階段
第二階段是事務提交或者回滾階段
准備階段:事務管理器(TM)通知資源管理器(RM)准備分支事務,記錄事務日志,並告知事務管理器准備結果
提交/回滾階段:如果所有資源管理器(RM)在准備階段都明確返回成功,則事務管理器向所有資源管理器發起事務提交指令完成數據變更,反之,如果任何一個資源管理器明確返回失敗,則事務管理器向所有資源管理器發送事務回滾指令
缺點: 同步阻塞,過於保守(任意一個節點失敗都會回滾)
事務協調者單點故障:如果協調者第二階段出現故障,那么其他參與者會處於鎖定狀態
腦裂導致數據不一致: 在第二階段中,事務協調者向所有參與者發送commit請求
發生局部網絡異常導致只有一部分參與者收到commit請求,這部分參與者收到請求后會執行commit操作,但是未收到commit請求的節點由於事務無法提交
導致數據出現不一致問題
2.三階段提交協議
比二階段多一個詢問階段
事務協調者向參與者發送事務執行請求,詢問是否可以執行指令
Base理論
通過犧牲數據的強一致性來獲取高可用性
Base Avaliable(基本可用): 出現故障時,允許損失一部分功能可用性,保證核心功能可用
Soft State(軟狀態) : 允許系統中數據存在中間狀態,這個狀態不影響系統可用性,就是允許系統中不同節點的數據副本存在延時
Eventually Consistent(最終一致性):中間狀態數據經過一段時間之后達到最終數據一致性
分布式事務常見解決方案
- TCC補償型方案(屬於兩段式)(關鍵字:事先凍結):
2.基於可靠性消息的最終一致性方案(基於中間件實現)
支付服務的本地事務與發送消息這個操作的原子性問題:
1.先發送消息,再執行數據庫事務
會出現消息發送成功但是本地事務更新失敗的情況
2.先執行數據庫事務,再發送消息
出現mq響應超時導致異常,從而將本地事務回滾,但消息可能已經發送成功,也存在數據不一致問題
最大努力通知型
分布式事務框架seata
AT模式
分為三大模塊:TM(事務管理器) RM(資源管理器) TC(事務控制器),
TM: 負責向TC注冊一個全局事務,並生成一個全局唯一的XID
在AT模式下,每個數據庫資源被當做一個RM,在業務層面通過JDBC標准接口訪問RM時,Seata會對所有的請求進行攔截,每個本地事務提交時,RM會向TC注冊一個分支事務
Saga模式
把一個業務流程中的長事務分為多個本地短事務,業務流程中每個參與者都提交真實的提交給本地短事務,
當其中一個參與者事務執行失敗,則通過補償機制補償前面已經成功的參與者
常見兩種協調方式
- 事件/編排式
- 命令/協調式
Seata AT實現原理
AT模式是基於XA事務模型演進而來,所以它的整體機制也是一個改進版的兩階段提交協議
第一階段: 業務數據和回滾日志記錄在同一個本地事務中提交,釋放本地鎖和連接資源
第二階段: 提交異步化,非常快速完成,回滾通過第一階段的回滾日志進行反向補償