SpringCloud入門(簡潔明了)

目錄

一.創建微服務項目

(一)環境準備

(二)項目結構圖

(三)流程

二. Nacos

(一)注冊中心

1.服務注冊

2.服務發現

3.編寫微服務API

4.遠程調用基本實現

5.負載均衡

6.@LoadBalanced注解式注解均衡

7.注冊中心宕機,遠程調用還能成功嗎

(二)配置中心

1.基本用法

2. 動態刷新

3. 配置監聽

4.Nacos中的數據集和application.properties有相同的配置項,哪個生效?

5. 數據隔離

三.?OpenFeign

(一)遠程調用

1.聲明式實現(業務API)

2. 第三方API

3.小技巧與面試題

(二)進階配置

1. 日志

2. 超時控制

3.重試機制

4. 攔截器

5.Fallback

四.Sentinel

(一)基礎

(二)整合使用

(三)異常處理

1.Web接口自定義處理異常

2.?@SentinelResource

3. OpenFeign

(四)流控規則

1. 流量模式-直接

2. 流量模式-鏈路

3. 流量模式-關聯

4. 流量效果-直接

5.流量效果-Warm Up

6. 流量效果-勻速排隊

(五)熔斷規則

1. 斷路器工作原理

2. 熔斷策略-慢調用比例

3.熔斷策略-異常比例

4.熔斷策略-異常數

(六)熱點規則

五.Gateway

(一)網關功能

(二)創建網關

(三)路由

1. 規則配置

2.原理

3. 斷言

(四)過濾器?編輯

1.路徑重寫

2.默認fliter

3.全局過濾器

4. 全局跨域

六. Seata-分布式事務

(一)架構原理?

(二) 二階提交協議

(三)XA模式

(四)AT模式


一.創建微服務項目

(一)環境準備

? 創建微服務架構項目

? 引入 SpringClould、Spring Cloud Alibaba 相關依賴

? 注意版本適配

https://github.com/alibaba/spring-cloud-alibaba/wiki/版本說明

版本選擇:

(二)項目結構圖

?

(三)流程

把這些刪掉:

在pom.xml里加上這一行表示為父項目:

 <packaging>pom</packaging>

把這些依賴刪掉:

加上:

 <properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><spring-cloud.version>2023.0.3</spring-cloud.version><spring-cloud-alibaba.version>2023.0.3.2</spring-cloud-alibaba.version></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>${spring-cloud-alibaba.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement>

把springboot版本換成3.3.4:

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.3.4</version><relativePath/> 
</parent>

創建子模塊:

在子項目pom.xml中寫入并刷新并將src刪了:

<packaging>pom</packaging>

在services中創建幾個微服務

在services的pom.xml中寫入:

 <dependencies><!--服務發現--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency>
</dependencies>

二. Nacos

注冊中心:

安裝:

Nacos /nɑ:k??s/ 是 Dynamic Naming and Configuration Service的首 字母簡稱,一個更易于構建云原生應用的動態服務發現、配置管 理和服務管理平臺。

官網:https://nacos.io/zh-cn/docs/v2/quickstart/quick-start.html

啟動命令: startup.cmd -m standalone

下載后解壓進入bin文件夾,打開cmd輸入startup.cmd -m standalone

打開瀏覽器訪問localhost:8848/nacos/可訪問

(一)注冊中心

1.服務注冊

在services-order中的pom.xml里寫:

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
</dependencies>

在services-order中寫啟動類并在resources中新建文件application.properties并寫入,運行啟動類后nacos的服務列表中會自動創建服務

@SpringBootApplication
public class OrderMainApplication {public static void main(String[] args) {SpringApplication.run(OrderMainApplication.class,args);}
}
spring.application.name=service-order
server.port=8000spring.cloud.nacos.server-addr=127.0.0.1:8848

同理services-products中也這么做

idea配置微服務:

點擊運行配置類型選擇springboot

復制服務:

鼠標右鍵點擊復制配置:

點擊修改選項:

點擊程序實參:

寫端口號并點擊應用:

2.服務發現

在啟動類上加注解@EnableDiscoveryClient

@EnableDiscoveryClient // 開啟服務發現功能
@SpringBootApplication
public class ProductsMainApplication {public static void main(String[] args) {SpringApplication.run(ProductsMainApplication.class,args);}
}

導入測試依賴:

 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope>
</dependency>

新建測試類:

@SpringBootTest
public class DiscoveryTest {@AutowiredDiscoveryClient discoveryClient;@AutowiredNacosServiceDiscovery nacosServiceDiscovery;@Testvoid  nacosServiceDiscoveryTest() throws NacosException {for (String service : nacosServiceDiscovery.getServices()){System.out.println("service="+service);//獲取ip+portList<ServiceInstance> instances=nacosServiceDiscovery.getInstances(service);for (ServiceInstance instance : instances){System.out.println("ip:"+instance.getHost()+";"+" post="+instance.getPort());}}}@Testvoid discoveryClientTesr(){for (String service : discoveryClient.getServices()){System.out.println("service="+service);//獲取ip+portList<ServiceInstance> instances=discoveryClient.getInstances(service);for (ServiceInstance instance : instances){System.out.println("ip:"+instance.getHost()+";"+" post="+instance.getPort());}}}
}兩個方法運行都能打印:service=service-orderip:192.168.100.1; post=8000service=service-productsip:192.168.100.1; post=9000

3.編寫微服務API

遠程調用 - 基本流程

遠程調用 - 下單場景:

在services中引入lombook

 <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId>scope>annotationProcessor</scope></dependency>

新建bean,constroller,service

services-product中:

@Data
public class Product {private Long id;private BigDecimal price;private String productName;private int num;
}@RestController
public class ProductController {@AutowiredProductService productService;//查詢商品@GetMapping("/product/{id}")public Product getProduct(@PathVariable("id") Long productId){Product product=productService.getProductById(productId);return product;}
}public interface ProductService {Product getProductById(Long productId);
}@Service
public class ProductServiceimpl implements ProductService {@Overridepublic Product getProductById(Long productId) {Product product=new Product();product.setId(productId);product.setPrice(new BigDecimal("99"));product.setProductName("蘋果"+productId);product.setNum(2);return product;}
}

運行啟動類后:

services-order中:

@Data
public class Order {private Long id;private BigDecimal totalAmount;private Long userId;private  String nickName;private  String address;private List<Object> productList;
}@RestController
public class OrderController {@AutowiredOrderService orderService;//創建訂單@GetMapping("/create")public Order createOrder(@RequestParam("userId") Long userId,@RequestParam("productId")Long productId){Order order = orderService.createOrder(productId,userId);return order;}
}public interface OrderService {Order createOrder(Long productId,Long userId);
}@Service
public class OrderServiceImpl implements OrderService {@Overridepublic Order createOrder(Long productId, Long userId) {Order order = new Order();order.setId(1L);order.setTotalAmount(new BigDecimal("0"));order.setUserId(userId);order.setNickName("zhangsan");order.setAddress("尚硅谷");order.setProductList(null);return order;}
}

運行啟動類后:

4.遠程調用基本實現

訂單和商品都啟動多個實例:

要在訪問訂單時也能訪問到商品的數據

因為在services-order中訪問不到Product類,所有在cloud-demo下一級新建一個model模塊,把訂單模塊和商品模塊的bean都復制到model中并把訂單和商品模塊中的bean刪掉,將model模塊引入lombook,將services中引入model模塊這樣在訂單和商品模塊就能用model中的bean了

在訂單模塊創建一個配置類:

@Configuration
public class OrderConfig {@BeanRestTemplate restTemplate(){return new RestTemplate();  //restTemplate用于給遠程發送請求}
}

OrderServiceImpl:

@Service
@Slf4j
public class OrderServiceImpl implements OrderService {@AutowiredDiscoveryClient discoveryClient;@AutowiredRestTemplate restTemplate;@Overridepublic Order createOrder(Long productId, Long userId) {Product product=getProductFromRemote(productId);Order order = new Order();order.setId(1L);//總金額order.setTotalAmount(product.getPrice().multiply(new BigDecimal(product.getNum())));order.setUserId(userId);order.setNickName("zhangsan");order.setAddress("尚硅谷");//遠程查詢商品列表order.setProductList(Arrays.asList( product));return order;}private Product getProductFromRemote(Long productId){//1.獲取到商品服務所在的所有機器ip+portList<ServiceInstance> instances=discoveryClient.getInstances("service-products");ServiceInstance instance=instances.get(0);//遠程URLString url="http://"+instance.getHost()+":"+instance.getPort()+"/product/"+productId;log.info("遠程請求:{}",url);//2.給遠程發送請求Product product=restTemplate.getForObject(url,Product.class);return product;}
}

將Order類中的集合類型改為Product:

@Data
public class Order {private Long id;private BigDecimal totalAmount;private Long userId;private  String nickName;private  String address;private List<Product> productList;
}

將所有服務全部重啟:

瀏覽器向訂單發起請求:

如果把9001,9002,,9003關掉一個或兩個那也能照常運行,比如關掉9001就會使用9002或9003。

缺點:每次都會給固定位置發請求,比如第一次給9001,那以后都是9001,除非9001被關掉

5.負載均衡

在services-order中引入spring-cloud-starter-loadbalancer以及測試類

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId>
</dependency>

新增測試類:

@SpringBootTest
public class LoadBalancerTest {@AutowiredLoadBalancerClient loadBalancerClient;@Testvoid test(){ServiceInstance choose=loadBalancerClient.choose("service-products");System.out.println("choose =" +choose.getHost()+": "+choose.getPort());ServiceInstance choose2=loadBalancerClient.choose("service-products");System.out.println("choose =" +choose2.getHost()+": "+choose2.getPort());ServiceInstance choose3=loadBalancerClient.choose("service-products");System.out.println("choose =" +choose3.getHost()+": "+choose3.getPort());ServiceInstance choose4=loadBalancerClient.choose("service-products");System.out.println("choose =" +choose4.getHost()+": "+choose4.getPort());}
}

運行顯示:

OrderServiceImpl:

@Service
@Slf4j
public class OrderServiceImpl implements OrderService {@AutowiredRestTemplate restTemplate;@Autowired  //一定導入spring-cloud-starter-loadbalancerLoadBalancerClient loadBalancerClient;@Overridepublic Order createOrder(Long productId, Long userId) {Product product=getProductFromRemoteWithLoadBalance(productId);Order order = new Order();order.setId(1L);//總金額order.setTotalAmount(product.getPrice().multiply(new BigDecimal(product.getNum())));order.setUserId(userId);order.setNickName("zhangsan");order.setAddress("尚硅谷");//遠程查詢商品列表order.setProductList(Arrays.asList( product));return order;}//完成負載均衡發送請求private Product getProductFromRemoteWithLoadBalance(Long productId){//1.獲取到商品服務所在的所有機器ip+portServiceInstance choose = loadBalancerClient.choose("service-products");//遠程URLString url="http://"+choose.getHost()+":"+choose.getPort()+"/product/"+productId;log.info("遠程請求:{}",url);//2.給遠程發送請求Product product=restTemplate.getForObject(url,Product.class);return product;}
}

多次向訂單發起請求后端口一直在循環:

6.@LoadBalanced注解式注解均衡

在配置類中加上注解:

@Configuration
public class OrderConfig {@LoadBalanced //注解式負載均衡@BeanRestTemplate restTemplate(){return new RestTemplate();}
}

OrderServiceImpl:

@Service
@Slf4j
public class OrderServiceImpl implements OrderService {@AutowiredRestTemplate restTemplate;@Overridepublic Order createOrder(Long productId, Long userId) {Product product=getProductFromRemoteWithLoadBalanceAnnotation(productId);Order order = new Order();order.setId(1L);//總金額order.setTotalAmount(product.getPrice().multiply(new BigDecimal(product.getNum())));order.setUserId(userId);order.setNickName("zhangsan");order.setAddress("尚硅谷");//遠程查詢商品列表order.setProductList(Arrays.asList( product));return order;}//基于注解的負載均衡private Product getProductFromRemoteWithLoadBalanceAnnotation(Long productId){String url="http://service-products/product/"+productId;//2.給遠程發送請求   service-products(微服務名字)會被動態替換Product product=restTemplate.getForObject(url,Product.class);return product;}
}

在ProductController中添加輸出語句:

@RestController
public class ProductController {@AutowiredProductService productService;//查詢商品@GetMapping("/product/{id}")public Product getProduct(@PathVariable("id") Long productId){System.out.println("hello");Product product=productService.getProductById(productId);return product;}
}

運行后多次請求會發現循環在9001,9002,9003三個控制臺輸入hello

7.注冊中心宕機,遠程調用還能成功嗎

沒調?過如果宕機,調?會失敗

調?過如果宕機,因為會緩存名單,遠程調用不在依賴注冊中心,所以調?會成功

(二)配置中心

1.基本用法

配置中心 - 基本使用:

在services下引入nacos作為配置中心的依賴:

<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

在service-order中的application.properties中寫入:

spring.cloud.nacos.server-addr=127.0.0.1:8848
spring.config.import=nacos:service-order.properties

點擊創建配置:

輸入Date ID 配置格式和配置內容并點擊發布:

在OrderController中獲取配置文件中的配置值,

@RefreshScope  //自動刷新
@RestController
public class OrderController {@AutowiredOrderService orderService;@Value("${order.timeout}")String orderTimeout;@Value("${order.auto-confirm}")String orderAutoConfirm;@GetMapping("/config")public String config(){return "order.timeout="+orderTimeout+": order.auto-confirm="+orderAutoConfirm;}//創建訂單@GetMapping("/create")public Order createOrder(@RequestParam("userId") Long userId,@RequestParam("productId")Long productId){Order order = orderService.createOrder(productId,userId);return order;}
}

運行啟動類并在瀏覽器輸入http://localhost:8000/config則可以看到,@RefreshScope注解表示激活配置屬性的自動刷新功能,就是如果在nacos中修改了配置,刷新瀏覽器就可以自動修改值,如果不加這個注解值就不會變

注意:如果引入了配置中心但項目啟動沒有導入任何配置就會報錯,這時候需要在application.properties中寫:

#禁用導入檢查
spring.cloud.nacos.config.import-check.enabled=false

2. 動態刷新

使用步驟

  • @Value(“${xx}”) 獲取配置 + @RefreshScope 實現自動刷新
  • @ConfigurationProperties 無感自動刷新
  • NacosConfigManager 監聽配置變化

將經常用的配置可以抽取到一個Properties類中,新建OrderProperties類

@Component
@ConfigurationProperties(prefix = "order")   //prefix寫配置項中.前面的
//配置批量綁定在nacos中,可以無需@RefreshScope就能實現自動刷新
@Data
public class OrderProperties {String timeout;   //屬性名寫配置項中.后面的。String autoConfirm; //如果是短橫線寫法就寫成駝峰命名方式
}

OrderController中:

@RestController
public class OrderController {@AutowiredOrderService orderService;@AutowiredOrderProperties orderProperties;@GetMapping("/config")public String config(){return "order.timeout="+orderProperties.getTimeout()+": order.auto-confirm="+orderProperties.getAutoConfirm();}//創建訂單@GetMapping("/create")public Order createOrder(@RequestParam("userId") Long userId,@RequestParam("productId")Long productId){Order order = orderService.createOrder(productId,userId);return order;}
}

3. 配置監聽

OrderMainApplication中:

@EnableDiscoveryClient
@SpringBootApplication
public class OrderMainApplication {public static void main(String[] args) {SpringApplication.run(OrderMainApplication.class,args);}//1. 項目啟動就監聽配置文件變化//2. 發生變化后拿到變化值//3. 發送郵件@BeanApplicationRunner applicationRunner(NacosConfigManager nacosConfigManager){return  args-> {ConfigService configService= nacosConfigManager.getConfigService();configService.addListener("service-order.properties","DEFAULT_GROUP", new Listener() {@Overridepublic Executor getExecutor() {return Executors.newFixedThreadPool(4);}@Overridepublic void receiveConfigInfo(String configInfo) {System.out.println("變化的配置信息:"+configInfo);System.out.println("郵件通知...");}});System.out.println("啟動");};}
}

啟動服務后修改nocos中配置的值后控制臺打印:

4.Nacos中的數據集和application.properties有相同的配置項,哪個生效?

spring.cloud.nacos.server-addr=127.0.0.1:8848
#導入多個配置
spring.config.import=nacos:service-order.properties,nacos:common.properties

后導入優先,外部優先

5. 數據隔離

需求描述:

  • ? 項目有多套環境:dev,test,prod
  • ? 每個微服務,同一種配置,在每套環境的值都不一樣。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?如:database.properties? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?如:common.properties
  • ??項目可以通過切換環境,加載本環境的配置

難點 :

  • ? ?區分多套環境
  • ? ?區分多種微服務
  • ? ?區分多種配置
  • ? ?按需加載配置

把application.properties去掉換成application.yml,注意yml里不能出現注釋,有注釋會報錯,復制下面的時候要把注釋刪了

server:port: 8000
spring:profiles:active: prod  #激活哪個環境application:name: service-ordercloud:nacos:server-addr: 127.0.0.1:8848config:namespace: ${spring.profiles.active:public}   #動態取值,:表示默認public---   #---是多文檔模式
spring:config:import:- nacos:common.properties?group=order  #?后面表示導入哪個組命名空間下的配置文件- nacos:database.properties?group=orderactivate:  #在哪種環境下生效on-profile: dev
---
spring:config:import:- nacos:common.properties?group=order- nacos:database.properties?group=order- nacos:haha.properties?group=orderactivate:on-profile: test
---
spring:config:import:- nacos:common.properties?group=order- nacos:database.properties?group=order- nacos:haha.properties?group=orderactivate:on-profile: prod

三.?OpenFeign

(一)遠程調用

1.聲明式實現(業務API)

Declarative REST Client

聲明式 REST 客戶端 vs 編程式 REST 客戶端(RestTemplate)

注解驅動 :?

  • 指定遠程地址:@FeignClient?
  • 指定請求方式:@GetMapping、@PostMapping、@DeleteMapping
  • 指定攜帶數據:@RequestHeader、@RequestParam、@RequestBody?
  • 指定結果返回:響應模型

在services中引入依賴:

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

遠程調用 - 業務API:

在訂單的啟動類中加上注解@EnableFeignClients

@EnableFeignClients //開啟Feign的遠程調用功能
@EnableDiscoveryClient
@SpringBootApplication
public class OrderMainApplication {public static void main(String[] args) {SpringApplication.run(OrderMainApplication.class,args);}//1. 項目啟動就監聽配置文件變化//2. 發生變化后拿到變化值//3. 發送郵件@BeanApplicationRunner applicationRunner(NacosConfigManager nacosConfigManager){return  args-> {ConfigService configService= nacosConfigManager.getConfigService();configService.addListener("service-order.properties","DEFAULT_GROUP", new Listener() {@Overridepublic Executor getExecutor() {return Executors.newFixedThreadPool(4);}@Overridepublic void receiveConfigInfo(String configInfo) {System.out.println("變化的配置信息:"+configInfo);System.out.println("郵件通知...");}});System.out.println("啟動");};}
}

編寫一個遠程調用的客戶端:

@FeignClient(value = "service-products") //feign客戶端
public interface ProductFeignClient {//mvc注解的兩套使用邏輯//1. 標注在Controller上,是接受這樣的請求//2. 標注在FeignClient上,是發送這樣的請求@GetMapping("/product/{id}")Product getProductById(@PathVariable("id")Long id);
}

修改OrderServiceImpl中創建訂單的邏輯:

@Service
@Slf4j
public class OrderServiceImpl implements OrderService {@AutowiredProductFeignClient productFeignClient;@Overridepublic Order createOrder(Long productId, Long userId) {//使用Feign完成遠程調用Product product=productFeignClient.getProductById(productId);Order order = new Order();order.setId(1L);//總金額order.setTotalAmount(product.getPrice().multiply(new BigDecimal(product.getNum())));order.setUserId(userId);order.setNickName("zhangsan");order.setAddress("尚硅谷");//遠程查詢商品列表order.setProductList(Arrays.asList( product));return order;}
}

運行后瀏覽器訪問:

OpenFeign能自動實現負載均衡

2. 第三方API

編寫一個遠程調用的客戶端:

//http://aliv18.data.moji.com/whapi/json/alicityweather/condition
@FeignClient(value = "weather-client",url ="http://aliv18.data.moji.com" )
//因為是第三方api,沒有注冊中心的名字,所以value隨便寫
public interface WeatherFeignCilent {@PostMapping("/whapi/json/alicityweather/condition")String getWeather(@RequestHeader("Authorization") String auth,@RequestParam("token") String Token,@RequestParam("cityId") String cityId);
}

新增測試類:

@SpringBootTest
public class WeatherTest {@AutowiredWeatherFeignCilent weatherFeignCilent;@Testvoid test01(){String weather=weatherFeignCilent.getWeather("APPCODE 93b7e19861a24c519a7548b17dc16d75","50b53ff8dd7d9fa320d3d3ca32cf8ed1","2182");System.out.println("weather = "+weather);}
}

3.小技巧與面試題

如何編寫好OpenFeign聲明式的遠程調用接口:

? ? ? 業務API:直接復制對方Controller簽名即可

? ? ? 第三方API:根據接口文檔確定請求如何發

客戶端負載均衡與服務端負載均衡區別:

(二)進階配置

1. 日志

在yml文件添加:

logging:level:com.itheima.feign: debug

注意:這里的com.itheima.feign是自己定義的feign客戶端的包名

包名這樣取:

在配置類中添加:

@Bean
Logger.Level feignLoggerLevel() {return Logger.Level.FULL;
}

2. 超時控制

在ProductServiceimpl中添加睡眠代碼:

@Service
public class ProductServiceimpl implements ProductService {@Overridepublic Product getProductById(Long productId) {Product product=new Product();product.setId(productId);product.setPrice(new BigDecimal("99"));product.setProductName("蘋果"+productId);product.setNum(2);try {TimeUnit.SECONDS.sleep(100);} catch (InterruptedException e) {throw new RuntimeException(e);}return product;}
}

打開瀏覽器訪問會等待60秒,然后顯示:

控制臺報錯:

超時配置:

services-order的application.yml中增加:

server:port: 8000
spring:profiles:active: prod#include是包含的意思,包含feign,feign就是下面新建的文件application-feign的-后面部分include: feign   application:name: service-ordercloud:nacos:server-addr: 127.0.0.1:8848config:namespace: ${spring.profiles.active:pubilc}logging:level:com.itheima.feign: debug---
spring:config:import:- nacos:common.properties?group=order- nacos:database.properties?group=orderactivate:on-profile: dev
---
spring:config:import:- nacos:common.properties?group=order- nacos:database.properties?group=order- nacos:haha.properties?group=orderactivate:on-profile: test
---
spring:config:import:- nacos:common.properties?group=order- nacos:database.properties?group=order- nacos:haha.properties?group=orderactivate:on-profile: prod

新建application-feign.yml文件:

spring:cloud:openfeign:client:config:default: #默認設置logger-level: fullconnect-timeout: 1000  #連接超時read-timeout: 2000   #讀取超時service-products:  #精確設置logger-level: fullconnect-timeout: 3000read-timeout: 5000

3.重試機制

遠程調用超時失敗后,還可以進行多次嘗試,如果某次成功返回ok,如果多次依然失敗則結束調用,返回錯誤

第一次請求失敗后間隔100毫秒重新發送,第二次請求失敗后間隔(100*1.5)毫秒重新發送,第三次請求失敗后間隔(100*1.5*1.5)毫秒后重新發送......最大不能超過1秒,超過按1秒算。


在配置類中加上:

 @BeanRetryer retryer(){return new Retryer.Default();}//不傳參數就是間隔100毫秒,最大間隔1秒,最多嘗試5次

4. 攔截器

創建一個攔截器:

@Component
public class XTokenRequestInterceptor implements RequestInterceptor {/*** 請求攔截器* @param requestTemplate */@Overridepublic void apply(RequestTemplate requestTemplate) {System.out.println("請求攔截器啟動");requestTemplate.header("X-Token","123456");}
}

在ProductController中可以取出X-token:

@RestController
public class ProductController {@AutowiredProductService productService;//查詢商品@GetMapping("/product/{id}")public Product getProduct(@PathVariable("id") Long productId,HttpServletRequest request){System.out.println(request.getHeader("X-Token"));System.out.println("hello");Product product=productService.getProductById(productId);return product;}
}

重新運行并訪問就能打印值

5.Fallback

引? sentinel:

 <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency>

在yml文件開啟熔斷:

feign:sentinel:enabled: true

兜底回調:

@Component
public class ProductFeignClientFallback implements ProductFeignClient {@Overridepublic Product getProductById(Long id){System.out.println("兜底回調");Product product=new Product();product.setId(id);product.setPrice(new BigDecimal("0"));product.setProductName("未知商品");product.setNum(0);return  product;}
}

修改ProductFeignClient接口:

@FeignClient(value = "service-products",fallback = ProductFeignClientFallback.class)
//feign客戶端    fallback表示該客戶端調用失敗了用哪個做兜底
public interface ProductFeignClient {//mvc注解的兩套使用邏輯//1. 標注在Controller上,是接受這樣的請求//2. 標注在FeignClient上,是發送這樣的請求@GetMapping("/product/{id}")Product getProductById(@PathVariable("id")Long id);
}

把服務關了并請求:

四.Sentinel

(一)基礎

功能介紹:隨著微服務的流行,服務和服務之間的穩定性變得越來越重要。Spring Cloud Alibaba Sentinel 以流量為切入點,從流量控制、流量路由、熔斷降級、系統自適應過載保護、熱點流量防護等多個維度保護服務的穩定性

架構原理:

資源&規則:

定義資源:

  • 主流框架自動適配(Web Servlet、Dubbo、Spring Cloud、gRPC、Spring WebFlux、Reactor); 所有Web接口均為資源
  • ?編程式:SphU API
  • 聲明式:@SentinelResource

定義規則:

  • 流量控制(FlowRule)
  • 熔斷降級(DegradeRule)
  • 系統保護(SystemRule)
  • 來源訪問控制(AuthorityRule) ?
  • 熱點參數(ParamFlowRule)

工作原理:

(二)整合使用

下載控制臺:https://security.feishu.cn/link/safety?target=https%3A%2F%2Fgithub.com%2Falibaba%2FSentinel%2Freleases&scene=ccm&logParams=%7B%22location%22%3A%22ccm_docs%22%7D&lang=zh-CN

在下載后存放jar的文件夾輸入cmd,在cmd輸入java -jar sentinel-dashboard-1.8.8.jar

訪問8080就是sentinel控制臺,默認賬號密碼就是sentinel

在services中引入sentinel依賴

<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

在兩個微服務模塊的application-feign.yml和application.properties中寫入:

spring:cloud:openfeign:client:config:default:logger-level : fullconnect-timeout: 1000read-timeout: 2000service-products:logger-level: fullconnect-timeout: 3000read-timeout: 5000sentinel:transport:dashboard: localhost:8080eager: true
feign:sentinel:enabled: true
spring.application.name=service-products
server.port=9001spring.cloud.nacos.server-addr=127.0.0.1:8848spring.cloud.nacos.config.import-check.enabled=falsespring.cloud.sentinel.transport.dashboard=localhost:8080
spring.cloud.sentinel.eager=true

運行訂單和商品模塊瀏覽器控制臺就會顯示:

在OrderServiceImpl中給createOrder添加注解?@SentinelResource(value = "createOrder"):

@Service
@Slf4j
public class OrderServiceImpl implements OrderService {@AutowiredProductFeignClient productFeignClient;@SentinelResource(value = "createOrder")@Overridepublic Order createOrder(Long productId, Long userId) {//使用Feign完成遠程調用Product product=productFeignClient.getProductById(productId);Order order = new Order();order.setId(1L);//總金額order.setTotalAmount(product.getPrice().multiply(new BigDecimal(product.getNum())));order.setUserId(userId);order.setNickName("zhangsan");order.setAddress("尚硅谷");//遠程查詢商品列表order.setProductList(Arrays.asList( product));return order;}
}

重新運行訂單模塊并在瀏覽器請求

sentinel控制臺的簇點鏈路會出現:

點擊create右邊的流控,并把單機閾值設為1(QPS表示每秒請求數量,單機閾值為1表示每秒最多請求1次)并點擊新增:

流控規則中會顯示:

用瀏覽器頻繁刷新(每秒超過一個請求)會顯示:

(三)異常處理

1.Web接口自定義處理異常

在service-order中?定義異常處理類BlockExceptionHandler:

@Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {private ObjectMapper objectMapper=new ObjectMapper();@Overridepublic void handle(HttpServletRequest request,HttpServletResponse response,String resourseName, BlockException e) throws Exception {response.setContentType("application/json;charset=utf-8");PrintWriter writer = response.getWriter();R error=R.error(500,resourseName+"被Sentinel限制了,原因:"+e.getClass());String json=objectMapper.writeValueAsString(error); //將對象轉成字符串writer.write(json);writer.flush();writer.close();}
}

在model模塊新建R對象:

@Data
public class R {private Integer code;private String msg;private Object data;public static R ok() {R r = new R();r.setCode(200);return r;}public static R ok(String msg, Object data) {R r = new R();r.setCode(200);r.setMsg(msg);r.setData(data);return r;}public static R error() {R r = new R();r.setCode(500);return r;}public static R error(Integer code, String msg) {R r = new R();r.setCode(code);r.setMsg(msg);return r;}
}

一秒內頻繁刷新瀏覽器會就會顯示:

2.?@SentinelResource

給createOrder添加流控規則:

為了方便測試把之前/create的流程規則刪了

如果在一秒內頻繁刷新瀏覽器會顯示一個默認的錯誤頁:

修改OrderServiceImpl(如果被@SentinelResource標注的資源沒用違反規則則調用真實業務邏輯并返回真實數據,如果違反了規則被Sentinel限制了,則調用blockHandler指定的方法返回兜底數據):

@Service
@Slf4j
public class OrderServiceImpl implements OrderService {@AutowiredProductFeignClient productFeignClient;@SentinelResource(value = "createOrder",blockHandler = "createOrderFallback")//blockHandler指定兜底回調@Overridepublic Order createOrder(Long productId, Long userId) {//使用Feign完成遠程調用Product product=productFeignClient.getProductById(productId);Order order = new Order();order.setId(1L);//總金額order.setTotalAmount(product.getPrice().multiply(new BigDecimal(product.getNum())));order.setUserId(userId);order.setNickName("zhangsan");order.setAddress("尚硅谷");//遠程查詢商品列表order.setProductList(Arrays.asList( product));return order;}//執行兜底回調public Order createOrderFallBack(Long productId, Long userId, BlockException e) {Order order = new Order();order.setId(0L);order.setTotalAmount(new BigDecimal(0));order.setUserId(userId);order.setNickName("未知用戶");order.setAddress("異常信息"+e.getClass());return order;}
}

重新啟動訂單服務,并在一秒內頻繁刷新頁面顯示:

3. OpenFeign

為遠程調用添加流控:

因為之前編寫OpenFeign客戶端的時候指定了一個Fallback回調,所以只要失敗了就會調用兜底回調

@FeignClient(value = "service-products",fallback = ProductFeignClientFallback.class) //feign客戶端
public interface ProductFeignClient {//mvc注解的兩套使用邏輯//1. 標注在Controller上,是接受這樣的請求//2. 標注在FeignClient上,是發送這樣的請求@GetMapping("/product/{id}")Product getProductById(@PathVariable("id")Long id);
}
@Component
public class ProductFeignClientFallback implements ProductFeignClient {@Overridepublic Product getProductById(Long id){System.out.println("兜底回調");Product product=new Product();product.setId(id);product.setPrice(new BigDecimal("0"));product.setProductName("未知商品");product.setNum(0);return  product;}
}

一秒內多次刷新就會顯示:

(四)流控規則

1. 流量模式-直接

限制多余請求,從而保護系統資源不被耗盡

QPS: 統計每秒請求數

并發線程數:?統計并發線程數

2. 流量模式-鏈路

調用關系包括調用方、被調用方;一個方法又可能會調用其它方法,形成一個調用鏈路的層次關 系;有了調用鏈路的統計信息,我們可以衍生出多種流量控制手段

在OrderController中新增方法sekill表示秒殺創建訂單:

@RestController
public class OrderController {@AutowiredOrderService orderService;@AutowiredOrderProperties orderProperties;@GetMapping("/config")public String config(){return "order.timeout="+orderProperties.getTimeout()+": order.auto-confirm="+orderProperties.getAutoConfirm()+": "+"order.db-url="+orderProperties.getDbUrl();}//創建訂單@GetMapping("/create")public Order createOrder(@RequestParam("userId") Long userId,@RequestParam("productId")Long productId){Order order = orderService.createOrder(productId,userId);return order;}//秒殺創建訂單@GetMapping("/sekill")public Order sekill(@RequestParam("userId") Long userId,@RequestParam("productId")Long productId){Order order = orderService.createOrder(productId,userId);order.setId(Long.MAX_VALUE);return order;}
}

在yml文件新增配置web-context-unify: false表示不統一web上下文:

spring:cloud:openfeign:client:config:default:logger-level : fullconnect-timeout: 1000read-timeout: 2000service-products:logger-level: fullconnect-timeout: 3000read-timeout: 5000sentinel:transport:dashboard: localhost:8080eager: trueweb-context-unify: falsefeign:sentinel:enabled: true

重新啟動Order模塊后Sentinel 控制臺有兩個鏈路:

對createOrder進行限流

這時候如果訪問/create沒有流量限制,但請求/sekill就有限制

一秒內訪問多次/sekill:

3. 流量模式-關聯

在OrderController中新增兩個方法:

@GetMapping("writeDb")
public String writeDb(){return "writeDb";
}
@GetMapping("readDb")
public String readDb(){return "readDb";
}

給readDb添加流控:

當/writeDb訪問量極大時再訪問/readDb就會:

4. 流量效果-直接

注意:只有快速失敗支持流控模式(直接、 關聯、鏈路)的設置

給/readDb新增流控:

利用apipost進行壓測:

5.流量效果-Warm Up

QPS表示每秒通過幾個請求,Period表示預熱時常是幾秒,比如QPS=3,Period=3,那么如果遇到超高峰流量到達,請求數量會從第一秒1個第二秒2個第三秒3個遞增,一直到設置的峰值

重新設置/readDb的流控:

用apipost測壓(設成每秒最多并發10個,持續5秒):

查看idea控制臺:

第一秒打印3個第一秒還沒開始統計,第二秒打印3個,第三秒打印5個,第四秒打印9個,第五秒10個,第六秒10個,idea控制臺有誤差,但整體趨勢是對的

6. 流量效果-勻速排隊

每秒兩個請求,多余的排隊,timeout表示超時時間,超過這個時間就會被丟棄

重新設置/readDb的流控:

使用apipost進行壓力測試:

idea控制臺:

(五)熔斷規則

1. 斷路器工作原理

熔斷降級(DegradeRule):

2. 熔斷策略-慢調用比例

設置熔斷:

表示5秒內如果有80%的請求響應時間大于1秒就是慢調用(最少有5個請求),一旦發生慢調用就認為對方是不可靠的就開啟熔斷30秒,這30秒內的所有請求都不會發給遠程服務。

修改ProductController(誰調用商品模塊都會休眠2秒):

@RestController
public class ProductController {@AutowiredProductService productService;//查詢商品@GetMapping("/product/{id}")public Product getProduct(@PathVariable("id") Long productId,HttpServletRequest request){System.out.println(request.getHeader("X-Token"));System.out.println("hello");Product product=productService.getProductById(productId);try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {throw new RuntimeException(e);}return product;}
}

重新啟動商品模塊,瀏覽器請求http://localhost:8888/create?userId=1&productId=777,5秒內多次刷新,會出現兜底數據,然后30秒內一直是這個數據并且不會像商品模塊發送請求。

3.熔斷策略-異常比例

修改ProductController故意制造錯誤:

@RestController
public class ProductController {@AutowiredProductService productService;//查詢商品@GetMapping("/product/{id}")public Product getProduct(@PathVariable("id") Long productId,HttpServletRequest request){System.out.println(request.getHeader("X-Token"));System.out.println("hello");Product product=productService.getProductById(productId);int i=10/0;return product;}
}

給GET:http://service-products/product/{id}設置新熔斷:

5秒內如果異常比例占80%就熔斷30秒,30秒內不給商品模塊發請求

重啟商品模塊并在瀏覽器請求,前五秒頻繁刷新會觸發熔斷,導致30不對商品模塊發請求,30秒后會嘗試發請求,這時候再不斷刷新就又會觸發熔斷

4.熔斷策略-異常數

5秒內異常數超過10個就觸發熔斷30秒

(六)熱點規則

熱點參數限流

熱點參數:

需求1:

修改OrderController中的sekill方法(添加@SentinelResource注解):

@GetMapping("/sekill")
@SentinelResource(value = "sekill-order",fallback = "sekillFallBack")
// required表示不必填,defaultValue表示默認值
public Order sekill(@RequestParam(value = "userId",defaultValue = "888")Long userId,@RequestParam(value = "productId",required = false)Long productId){Order order = orderService.createOrder(productId,userId);order.setId(Long.MAX_VALUE);return order;
}
public Order sekillFallback(Long userId, Long productId,Throwable exception){System.out.println("sekillFallback...");Order order=new Order();order.setId(productId);order.setUserId(userId);order.setAddress("異常信息:"+exception.getClass());return order;
}fallback與blockHandler兜底回調區別:
使用fallback是有blockHandler優先使用blockHandler,沒有blockHandler再使用fallback
fallback可以處理業務異常,如果使用fallback那么兜底回調的異常要寫成Throwable
如果使用blockHandler那兜底異常要使用BlockException
否則兜底回調不生效,限流會返回一個默認錯誤頁

添加熱點規則:

表示限制第一個參數每秒只能一個,瀏覽器訪問并頻繁刷新會:

如果去掉userId參數就沒有熱點參數限流

需求2:

修改熱點規則:

這樣6號用戶就不被限流了

需求3:

新增熱點:

編輯:

五.Gateway

(一)網關功能

Spring Cloud Gateway:

需求:

? ?1. 客戶端發送 /api/order/** 轉到 service-order

? ?2. 客戶端發送 /api/product/** 轉到 service-product

? ?3. 以上轉發有負載均衡效果

(二)創建網關

在cloud-demo下創建gateway模塊

引入依賴:

<dependencies><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency>
</dependencies>

新建application.yml文件:

spring:application:name: gatewaycloud:nacos:server-addr: 127.0.0.1:8848server:port: 80

新建GatewayMainApplication啟動類:

@EnableDiscoveryClient  //服務發現
@SpringBootApplication
public class GatewayMainApplication {public  static  void main(String[] args) {SpringApplication.run(GatewayMainApplication.class,args);}
}

運行并打開nocos:

(三)路由

1. 規則配置

新建路由規則文件application-route.yml:

spring:cloud:gateway:routes:- id: order-route  #路由規則id,自定義,唯一uri: lb://service-order  #路由目標微服務,lb代表負載均衡predicates:  #路由斷言,判斷請求是否符合規則,符合則路由到目標- Path=/api/order/**  #以請求路徑做判斷- id: products-routeuri: lb://service-productspredicates:- Path=/api/products/**#id表示路由的名字
#uri表示把請求轉到哪
#predicates表示路由的匹配規則
#-Path表示路徑為api/order/開頭的都轉給uri

讓application.yml包含該文件:

spring:profiles:include: routeapplication:name: gatewaycloud:nacos:server-addr: 127.0.0.1:8848server:port: 80

在OrderController類上加上@RequestMapping("/api/order")

在ProductController類上加上@RequestMapping("/api/products")

在ProductFeignClient類的getProductById的注解改為@GetMapping("/api/products/product/{id}")

瀏覽器訪問http://localhost/api/order/writeDb:

2.原理

3. 斷言

長短寫法:

spring:cloud:gateway:routes:- id: order-routeuri: lb://service-orderpredicates:     #長斷言- name: Pathargs:patterns: /api/order/**match-trailing-slash: true- id: products-route  uri: lb://service-productspredicates:     #短斷言- Path=/api/products/**

(四)過濾器

1.路徑重寫

這樣就不用在控制層寫@RequestMapping()了

spring:cloud:gateway:routes:- id: order-routeuri: lb://service-orderpredicates:- name: Pathargs:patterns: /api/order/**match-trailing-slash: truefilters:- RewritePath=/api/order/(?<segment>.*), /$\{segment}- id: products-routeuri: lb://service-productspredicates:- Path=/api/products/**filters:- RewritePath=/api/products/(?<segment>.*), /$\{segment}

2.默認fliter

spring:cloud:gateway:default-filters: #默認filters,如果其他沒有設置就使用這個- AddResponseHeader=X-Response-Abc,123

3.全局過濾器

新建RtGlobalFilter類做全局過濾器

@Component
@Slf4j
public class RtGlobalFilter implements GlobalFilter, Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request = exchange.getRequest();ServerHttpResponse response = exchange.getResponse();String uri = request.getURI().toString();long start=System.currentTimeMillis();log.info("請求:"+uri+" 開始時間:"+start);//---------以上是前置邏輯--------------//Mono<Void> filter=chain.filter(exchange).doFinally((result)->{//----------以下是后置邏輯-------//long end=System.currentTimeMillis();log.info("請求"+uri+" 結束時間:"+end+" 耗時"+(end-start));});//放行return filter;}@Overridepublic int getOrder() {return 0;}
}

這樣控制臺就可以輸出每個請求的路徑和耗時時間

4. 全局跨域

spring:cloud:gateway:globalcors:cors-configurations:'[/**]':allowed-origins: "*"allowed-headers: "*"allowed-methods: "*"

六. Seata-分布式事務

(一)架構原理?

下載Seata:Seata Java Download | Apache Seata

2.1.0版本下載后解壓并進入bin目錄,使用cmd輸入seata-server.bat

訪問http://localhost:7091/#/login進入頁面,賬號密碼都是seata

在所有微服務模塊引入:

<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>

每個微服務創建 file.conf ?件:

service {#transaction service group mappingvgroupMapping.default_tx_group = "default"#only support when registry.type=file, please don't set multiple addressesdefault.grouplist = "127.0.0.1:8091"#degrade, current not supportenableDegrade = false#disable seatadisableGlobalTransaction = false
}

在最大的方法入口標注注解@GlobalTransactional就會實現報錯所有數據回滾

(二) 二階提交協議

(三)XA模式

設置XA模式:

(四)AT模式

設置AT模式:

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/94136.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/94136.shtml
英文地址,請注明出處:http://en.pswp.cn/web/94136.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

集成算法學習筆記

一、集成算法簡介1. 核心思想類比“多個專家綜合判斷優于單個專家”&#xff0c;通過構建并結合多個個體學習器&#xff0c;提升模型的泛化能力&#xff08;降低過擬合風險、提高預測準確性&#xff09;&#xff0c;完成復雜的學習任務。2. 個體學習器與結合模塊個體學習器&…

讓Chrome信任自簽名證書

讓Chrome信任自簽名證書&#xff08;Unix系列OS&#xff09; 背景 想在本地測試自己寫的基于HTTPS連接的Web應用&#xff0c;跑在3001端口。但使用Chrome瀏覽器訪問https://localhost:3001時顯示連接不安全。解決了但沒解決 使用mkcert一鍵創建證書&#xff1a; mkcert localho…

[江科大庫]基于 OpenMV 的矩形識別與 STM32 串口通信(電子設計大賽實用教程)

?? 基于 OpenMV 的矩形識別與 STM32 串口通信(電子設計大賽實用教程) 一、前言 在本科生電子設計大賽中,經常會遇到圖像識別相關的任務,例如: 識別 矩形框(如識別一個 A4 紙、黑色標記框等); 將識別結果傳輸到 STM32 單片機,用于后續控制(舵機、移動小車、機械臂…

人臉識別驅動的工廠人體屬性檢測與預警機制

人體屬性檢測&#xff1a;人臉識別智慧檢測驅動的工廠管理革新&#xff08;所有圖片均為真實項目案例&#xff09;在制造業數字化轉型浪潮中&#xff0c;人體屬性檢測技術已成為破解傳統工廠管理難題的核心工具。通過融合人臉識別智慧檢測、目標檢測算法與多模態數據分析&#…

數據工程師——ETL

ETL面試題01 一、基礎概念與理論類 1. 請解釋什么是 ETL?它在數據處理流程中扮演什么角色? 答:ETL就是數據抽取、轉化、加載。目的是將分散的數據源集中在一起進行處理分析。 數據抽取:是指各種數據源中抽取數據,包括關系型數據庫(MySQL、Oracle等)、日志文件、Exce…

Oracle APEX 經典報表中的Checkbox

目錄 1. 建表&#xff06;投入測試數據 2. 經典報表做成 2-1. 畫面布局如下?編輯 2-2. 報表使用的SQL 2-3. RS列的Heading設定 2-4. Function and Global Variable Declaration 2-5. Execute when Page Loads 2-6. Process 3. 運行效果?編輯 1. 建表&#xff06;投入…

Codeforces Round 1043 (Div.3)

比賽連接&#xff1a;Codeforces Round 1043 (Div.3) A. Homework 題目鏈接&#xff1a;A - Homework Vlad and Dima have been assigned a task in school for their English class. They were given two strings aaa and bbb and asked to append all characters from bbb …

GPS欺騙式干擾的產生

我們在GNSS抗干擾天線的選型、測試方法以及為什么不能做RTK&#xff1f;&#xff08;抗干擾內容全集&#xff09;中提到的抗干擾天線&#xff0c;針對的是GPS壓制式干擾。對于GPS欺騙式干擾&#xff0c;抗干擾天線是無能為力的。 簡單來說&#xff0c;壓制式干擾是通過發射強功…

[PV]AXI R/W/RW帶寬計算的tcl腳本

AXI R/W/RW帶寬計算的tcl腳本 我基于前述的axi_read_bw_per_id.tcl腳本進行了修改,使其支持: 讀通道(Read Channel):計算基于rvalid && rready的有效周期(已在前述實現)。 寫通道(Write Channel):計算基于wvalid && wready的有效周期,考慮wstrb的ac…

阿里云AnalyticDB同步數據至華為云taurusdb

1 概述 AnalyticDB和taurusdb都是高度兼容mysql協議的數據庫&#xff0c;從現有的AnalyticDB官方數據同步方案來看&#xff0c;只有FlinkSQL合適。 同步方案官方文檔&#xff1a; https://help.aliyun.com/zh/analyticdb/analyticdb-for-mysql/user-guide/flink-subscribes-b…

學習嵌入式之驅動——系統移植(二)

一、uboot常用命令與環境變量1.命令&#xff1a;&#xff08;1&#xff09;環境變量操作命令命令功能格式printenv 查看環境變量printenvsetenv新建/修改環境變量setenv 環境變量名 環境變量值saveenv保存環境變量saveenv&#xff08;2&#xff09;內存操作命令命令功能格式示例…

EasyExcel 合并單元格最佳實踐:基于注解的自動合并與樣式控制

EasyExcel 合并單元格最佳實踐&#xff1a;基于注解的自動合并與樣式控制 前言 在日常開發中&#xff0c;我們經常需要導出 Excel 報表&#xff0c;而合并單元格是提升報表可讀性的常見需求。本文將介紹如何基于 EasyExcel 實現智能的單元格合并功能&#xff0c;通過自定義注解…

Unity設置UI顯示區域

系列文章目錄 untiy工具 文章目錄 系列文章目錄 ??前言 ??一、效果圖 ??二、制作過程(檢測中心點位置) ??2-1、代碼實現 ??三、優化為檢測整個UI四個角點 ??四、性能優化建議 ??壁紙分享 ??總結 ??前言 思路: 獲取屏幕的寬度和高度,定義中間區域的范圍…

Qt中用于圖像縮放的核??法QPixmap::scaled

QPixmap::scaled是Qt中用于圖像縮放的核??法&#xff0c;其作?和?法如下&#xff1a;?一、核心作用??圖像尺寸調整?根據指定尺寸對圖像進?等?例或?等?例縮放&#xff0c;?持放?和縮?操作。?保持寬高比?通過AspectRatioMode參數控制是否保持原始圖像的寬??。…

SQL Workbench/J:一款免費開源、跨平臺的通用SQL查詢工具

SQL Workbench/J 是一款基于 Java 開發的免費開源、跨平臺的通用 SQL 查詢工具。 SQL Workbench/J 主要專注于 SQL 腳本開發和數據導入導出功能&#xff0c;不提供各種數據庫管理功能。 功能特性 跨平臺&#xff1a;可以在任何安裝了 Java 運行時環境的操作系統上運行&#xf…

DOLO 上漲:Berachain 生態爆發的前奏?

在 Berachain 生態逐漸進入公眾視野之際&#xff0c;Dolomite&#xff08;簡稱 Dolomite&#xff0c;代幣 DOLO&#xff09;成為鏈上表現最為突出的明星協議。其代幣價格在短短兩個月內&#xff0c;從 $0.03 飆升至 $0.3&#xff0c;漲幅接近 10 倍。市場不僅將其視作 Berachai…

吉利汽車與芯鼎微成立聯合創新實驗室共譜車規級LCoS顯示新篇章

2025年8月20日&#xff0c;吉利汽車研究院技術規劃中心副主任李莉、光學實驗室負責人李金樺博士等一行四人蒞臨芯鼎微&#xff0c;雙方共同為"吉利汽車-芯鼎微聯合創新實驗室"揭牌&#xff0c;標志著兩家企業在車載先進顯示技術領域邁入深度協同創新的新階段。 在這汽…

NPM組件 @angular_devkit/core 等竊取主機敏感信息

【高危】NPM組件 angular_devkit/core 等竊取主機敏感信息 漏洞描述 當用戶安裝受影響版本的 angular_devkit/core 等NPM組件包時會竊取用戶的主機名、用戶名、IP地址信息并發送到攻擊者可控的服務器地址。 MPS編號MPS-1jf5-s6ix處置建議強烈建議修復發現時間2025-08-14投毒…

docker cuda版安裝 dockercuda版安裝

目錄 1.一鍵安裝docker 測試ok 2.安裝cuda支持 通用的應該沒問題 安裝工具包 配置 runtime&#xff1a; 3.檢查 Docker 是否支持 NVIDIA 運行時 1.一鍵安裝docker 測試ok curl -fsSL https://get.docker.com | sh 2.安裝cuda支持 通用的應該沒問題 也可以搜索安裝 cuda版d…

Spring發布訂閱模式詳解

Spring 的發布訂閱模式&#xff08;Publish-Subscribe Pattern&#xff09;是一種基于事件驅動的設計模式&#xff0c;通過 "事件" 作為中間載體實現組件間的解耦。在這種模式中&#xff0c;"發布者"&#xff08;Publisher&#xff09;負責產生事件并發布&…