17 Introduction to SpringCloud Alibaba
17.1 why SpringCloud alibaba appears
- Spring Cloud Netflix project enters maintenance mode
-
https://spring.io/blog/2018/12/12/spring-cloud-greenwich-rc1-available-now
-
illustrate
-
- Spring Cloud Netflix Projects Entering Maintenance Mode
- What is maintenance mode
- Putting a module into maintenance mode means that the Spring Cloud team will no longer add new features to the module. We will fix block-level bugs and security issues, and we will also consider and review small pull requests from the community.
- Putting a module into maintenance mode means that the Spring Cloud team will no longer add new features to the module. We will fix block-level bugs and security issues, and we will also consider and review small pull requests from the community.
- What does it mean to enter maintenance mode?
- Spring Cloud Netflix will no longer develop new components
- We all know that Spring Cloud version iteration is relatively fast, so when there are many major ISSUEs, another Release is pushed before it is too late to fix them. Entering maintenance mode means that there are only so many services and functions provided by Spring Cloud Netflix for a while now, and new components and functions will no longer be developed. In the future, maintenance and Merge branch Full Request will be the main focus.
- New component functions will be implemented by replacing them with other alternatives
- What is maintenance mode
17.2 What does SpringCloud alibaba bring?
what is
- Official website:
https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md
- Birth:
- On October 31, 2018, Spring Cloud Alibaba officially entered the Spring Cloud official incubator and released the first version in the Maven central library.
- On October 31, 2018, Spring Cloud Alibaba officially entered the Spring Cloud official incubator and released the first version in the Maven central library.
Where to go:
https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md
- This dependency has been introduced in the pom file before
What can you do:
- Service current limiting and downgrading: Supports access to the current limiting and downgrading functions of Servlet, Feign, RestTemplate, Dubbo and RocketMQ by default. You can modify the current limiting and downgrading rules in real time through the console at runtime. It also supports viewing the current limiting and downgrading Metrics monitoring.
- Service registration and discovery: Adapts to Spring Cloud service registration and discovery standards, and integrates Ribbon support by default.
- Distributed configuration management: supports externalized configuration in distributed systems and automatically refreshes when configuration changes.
- Message-driven capabilities: Build message-driven capabilities for microservice applications based on Spring Cloud Stream.
- Alibaba Cloud Object Storage: Alibaba Cloud provides massive, secure, low-cost, and highly reliable cloud storage services. Supports storage and access of any type of data from any application, anytime, anywhere.
- Distributed task scheduling: Provides second-level, accurate, highly reliable, and highly available scheduled (based on Cron expression) task scheduling services. It also provides a distributed task execution model, such as grid tasks. Grid tasks support the even distribution of massive quantum tasks to all Workers (schedulerx-client) for execution.
How to play
- As shown below:
17.3 Obtaining SpringCloud alibaba learning materials
-
Official website: https://spring.io/projects/spring-cloud-alibaba#overview
- Spring Cloud Alibaba is committed to providing a one-stop solution for microservice development. This project contains the necessary components to develop distributed application microservices, making it easy for developers to use these components to develop distributed application services through the Spring Cloud programming model.
- Relying on Spring Cloud Alibaba, you only need to add some annotations and a small amount of configuration to connect Spring Cloud applications to Alibaba microservice solutions and quickly build a distributed application system through Alibaba middleware.
- SpringCloud Alibaba entered the SpringCloud official incubator and graduated
- That is: this URL is the URL before the revision. After the revision, it was added to Spring Cloud, so you can check Alibaba in Spring Cloud later.
-
English
-
https://github.com/alibaba/spring-cloud-alibaba
-
English documentation: https://spring-cloud-alibaba-group.github.io/github-pages/greenwich/spring-cloud-alibaba.html
-
-
Chinese
- Chinese documentation: https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md
- Chinese documentation: https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md
18 Nacos Service Registration and Configuration Center
- SpringCloud Alibaba----Nacos service registration and configuration center
18.1 Introduction to Nacos
18.1.1 Why is it called Nacos?
- The first four letters are the first two letters of Naming and Configuration respectively, and the last s is Service.
- github URL: https://github.com/alibaba/Nacos
18.1.2 What is
- A dynamic service discovery, configuration management and service management platform that makes it easier to build cloud-native applications.
- Nacos: Dynamic Naming and Configuration Service
- Nacos is a combination of registration center + configuration center
- Equivalent to: Nacos = Eureka+Config +Bus
18.1.3 What can you do?
- Replace Eureka as service registration center
- Replace Config as service configuration center
18.1.4 Where to go
-
Official website: https://nacos.io/zh-cn/index.html
-
download link:
https://github.com/alibaba/nacos/releases
-
Spring-cloud-alibaba's general documentation on GitHub : Using Nacos
https://spring-cloud-alibaba-group.github.io/github-pages/greenwich/spring-cloud-alibaba.html#_spring_cloud_alibaba_nacos_discovery
-
You can also view the documentation directly on the Nacos official website:
18.1.5 Comparison of various registration centers (simple explanation)
It is said that Nacos has more than 100,000 instances running within Alibaba, and has passed the test of various large-scale traffic such as Double Eleven.
18.2 Install and run Nacos
18.2.1 Description of old and new versions
-
Check the version corresponding to each component on GitHub official website:
https://github.com/alibaba/spring-cloud-alibaba
-
Just start the old version directly
-
The new version needs to modify the configuration file to start successfully:
-
Official documentation explains:
-
Reason: The old version has a default value for authentication. The new version has removed the default value for security reasons, so manual configuration is required.
-
How to modify and view: B station power node SpringCloud video
-
18.2.2 Operation
-
After downloading, unzip the compressed package
-
本地Java8+Maven环境已经OK
-
Enter cmd in the bin directory to enter the command line window
- Start command:
startup.cmd -m standalone
- standalone represents stand-alone mode operation, non-cluster mode
- Start command:
-
After the command runs successfully, access directly:
http://localhost:8848/nacos
- The default account password is nacos
- The default account password is nacos
18.3 Nacos as a service registration center demonstration
18.3.1 Official website documents
- https://spring.io/projects/spring-cloud-alibaba
- Alibaba Instruction Manual:
18.3.2 Nacos-based service provider
1) Create a new Module: cloudalibaba-provider-payment9001
2)POM
- Parent POM: It has been introduced before, so the sub-project does not need to be introduced every time.
<!--spring cloud alibaba-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
- This module POM
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cloud2020</artifactId>
<groupId>com.angenin.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.angenin.springcloud.alibaba</groupId>
<artifactId>cloudalibaba-provider-payment9001</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!--SpringCloud ailibaba nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringBoot整合Web组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--日常通用jar包配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
- Check the official website documentation:
- spring cloud alibaba depends on coordinates
- SpringCloud ailibaba nacos depends on coordinates
- spring cloud alibaba depends on coordinates
3)YML
server:
port: 9001
spring:
application:
name: nacos-payment-provider
cloud:
nacos:
discovery:
server-addr: localhost:8848 #配置Nacos地址
management:
endpoints:
web:
exposure:
include: '*' #暴露监控所有的端点
- Official documentation:
4) Main startup
package com.angenin.springcloud.alibaba;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient //这个注解和之前的不一样,开启服务注册功能
@SpringBootApplication
public class PaymentMain9001 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain9001.class, args);
}
}
- Official documentation
5) Business category
package com.angenin.springcloud.alibaba.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class PaymentController {
@Value("${server.port}")
private String serverPort;
@GetMapping(value = "/payment/nacos/{id}")
public String getPayment(@PathVariable("id") Integer id) {
return "nacos registry, serverPort: "+ serverPort+"\t id"+id;
}
}
6) Test
-
Start Nacos8848 registration center and start 9001 producer
- Unlike Eureka, which needs to build its own service module before it can be used, this one only needs to be installed and used.
-
Access control layer method: http://localhost:9001/payment/nacos/1
-
nacos console: http://localhost:8848/nacos
- The default account password is nacos
- The default account password is nacos
-
nacos service registration center + service provider 9001 are all OK
7) Create 9002 in advance
-
nacos comes with its own load balancing function: To demonstrate the load balancing of nacos in the next chapter, refer to 9001 and create a new 9002
-
Method 1: To avoid duplicating manual labor by creating a new one, copy the virtual port mapping directly.
- Sometimes an error may be reported.
- Sometimes an error may be reported.
-
Method 2: Manually create a new
cloudalibaba-provider-payment9002
-
Creation steps: omitted
-
Effect:
-
-
Start 9001 and 9002 to view the background management interface:
18.3.3 Nacos-based service consumer
1) Create a new Module: cloudalibaba-consumer-nacos-order83
2)POM
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cloud2020</artifactId>
<groupId>com.angenin.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.angenin.springcloud.alibaba</groupId>
<artifactId>cloudalibaba-consumer-nacos-order83</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!--SpringCloud ailibaba nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
<dependency>
<groupId>com.angenin.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<!-- SpringBoot整合Web组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--日常通用jar包配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
- Why nacos supports load balancing: Ribbon is automatically integrated ( not in the new version, it has been replaced by LoadBalancer )
3)YML
server:
port: 83
spring:
application:
name: nacos-order-consumer
cloud:
nacos:
discovery:
server-addr: localhost:8848 #Nacos注册中心的地址
#消费者将要去访问的微服务名称(注册成功进nacos的微服务提供者)
#之前直接写的是生产者集群服务的名称 写死了,现在是写在配置文件中通过注解@Value读取获得
service-url:
nacos-user-service: http://nacos-payment-provider
4) Main startup
package com.angenin.springcloud.alibaba;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@SpringBootApplication
public class OrderNacosMain83 {
public static void main(String[] args) {
SpringApplication.run(OrderNacosMain83.class,args);
}
}
5) Configuration class
package com.angenin.springcloud.alibaba.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class ApplicationContextBean {
@Bean
@LoadBalanced //使用@LoadBalanced注解赋予RestTemplate负载均衡的能力
public RestTemplate getRestTemplate() {
//RestTemplate提供了多种便捷访问远程http访问的方法
return new RestTemplate();
}
}
6) Business category
package com.angenin.springcloud.alibaba.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
@RestController
public class OrderNacosController {
@Resource
private RestTemplate restTemplate;
//之前直接写的是生产者集群服务的名称 写死了,现在是写在配置文件中通过注解@Value读取获得
@Value("${service-url.nacos-user-service}")
private String serverURL;
@GetMapping("/consumer/payment/nacos/{id}")
public String paymentInfo(@PathVariable("id") Long id) {
//getForObject两个参数:请求地址,返回的对象类型----读操作
return restTemplate.getForObject(serverURL+"/payment/nacos/"+id,String.class);
}
}
7) Test
-
Start nacos, 9001 producer, 9002 producer, 83 consumer
-
nacos console
-
http://localhost:83/consumer/payment/nacos/13
-
83 accesses 9001/9002, polling load OK
18.3.4 Comparison of service registration centers (detailed explanation)
-
Nacos panorama shown
-
Nacos and CAP
-
Nacos supports switching between AP and CP modes
C是所有节点在同一时间看到的数据是一致的;而A的定义是所有的请求都会收到响应。
何时选择使用何种模式?
- Generally speaking, if there is no need to store service level information and the service instance is registered through nacos-client and can maintain heartbeat reporting, then you can choose AP mode. Current mainstream services such as Spring cloud and Dubbo services are all suitable for AP mode. AP mode weakens consistency for the sake of service possibility, so AP mode only supports registration of temporary instances.
- If you need to edit or store configuration information at the service level, then CP is required, and K8S services and DNS services are suitable for CP mode.
- CP mode supports the registration of persistent instances. At this time, the Raft protocol is used as the cluster operating mode. In this mode, the service must be registered before registering the instance. If the service does not exist, an error will be returned.
curl -X PUT '$NACOS_SERVER:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=CP'
18.4 Nacos as a service configuration center demonstration
18.4.1 Nacos as configuration center-basic configuration
1) Create new: cloudalibaba-config-nacos-client3377
2)POM
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cloud2020</artifactId>
<groupId>com.angenin.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloudalibaba-config-nacos-client3377</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!--nacos-config-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!--nacos-discovery-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--web + actuator-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--一般基础配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
3)YML
- why configure two
- Nacos is the same as springcloud-config. When initializing the project, you must first pull the configuration from the configuration center. Only after pulling the configuration can the normal startup of the project be guaranteed.
- There is a priority order for loading configuration files in springboot.
bootstrap优先级高于application
- That is: bootstrap stores the shared ones pulled to the configuration center, and application stores its own local ones.
- bootstrap.yml
# nacos配置
server:
port: 3377
spring:
application:
name: nacos-config-client
cloud:
nacos:
discovery:
server-addr: localhost:8848 #Nacos服务注册中心地址
config:
server-addr: localhost:8848 #Nacos作为配置中心地址
file-extension: yaml #指定yaml格式的配置(3377就可以到8848上去读取,后缀名指定为yaml格式的文件)
# ${spring.application.name}-${spring.profile.active}.${spring.cloud.nacos.config.file-extension}
# nacos-config-client-dev.yaml (不识别yml)
- application.yml
spring:
profiles:
active: dev #表示开发环境
# 这样bootstrap+application结合起来就相当于:3377到8848配置中心上去读取,一个什么样的yml文件
4) Main startup
package com.angenin.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@SpringBootApplication
public class NacosConfigClientMain3377
{
public static void main(String[] args) {
SpringApplication.run(NacosConfigClientMain3377.class, args);
}
}
5) Business category
Automatically update the configuration through Spring Cloud's native annotation @RefreshScope:
- Previously, it was solved in the SpringCloud Config distributed configuration center: you can manually refresh the function without restarting, and then you need to send a post request to take effect.
package com.angenin.springcloud.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RefreshScope //在控制器类加入@RefreshScope注解使当前类下的配置支持Nacos的动态刷新功能。
public class ConfigClientController {
/**
* 和之前学习SpringCloud Config分布式配置中心一样:
* 分布式配置中心可以,将配置信息以REST接口的形式暴露:post、curl访问刷新均可......
* 既然配置信息暴漏了,那么3355就可以通过REST风格读取到3344配置中心的消息和内容的配置。
*/
@Value("${config.info}")
private String configInfo;
@GetMapping("/config/info")
public String getConfigInfo() {
return configInfo;
}
}
6) Add configuration information in Nacos: matching rules in Nacos
theory:
-
The composition format of data id in Nacos and the matching rules in the SpringBoot configuration file
-
Official website: https://nacos.io/zh-cn/docs/v2/ecology/use-nacos-with-spring-cloud.html
-
Final formula:
${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
- Corresponding configuration in the configuration file:
nacos-config-client-dev.yaml
Practical operation:
-
Configuration new:
nacos-config-client-dev
-
Nacos interface configuration correspondence
config:
info: nacos config center,version = 1
-
Click Publish: the configuration list will have one more line of configuration information.
-
Summary: Set DataId
- official:
${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
- prefix defaults to the value of spring.application.name
- spring.profile.active is the profile corresponding to the current environment, which can be configured through the configuration item spring.profile.active.
- file-exetension is the data format of the configuration content, which can be configured through the configuration item spring.cloud.nacos.config.file-extension
- Drawing instructions:
- official:
-
Historical configuration
- Nacos will record the historical version of the configuration file and keep it for 30 days by default. In addition, there is a one-click rollback function. The rollback operation will trigger a configuration update.
- rollback
7) Test
- Before starting, you need to have the corresponding yaml configuration file under the nacos client-configuration management-configuration management column.
- Start nacos
- Run the main startup class of cloud-config-nacos-client3377
- Call the interface to view configuration information: http://localhost:3377/config/info
8) Comes with dynamic refresh
- Modify the yaml configuration file in Nacos and call the interface to view the configuration again. You will find that the configuration has been refreshed.
18.4.2 Nacos as a configuration center - classified configuration
1) Problem: Multi-environment and multi-project management
- Question 1:
- In actual development, usually a system will prepare
- dev development environment
- test test environment
- prod production environment.
- How to ensure that the service can correctly read the configuration file of the corresponding environment on Nacos when the specified environment is started?
- In actual development, usually a system will prepare
- Question 2:
- A large-scale distributed microservice system will have many microservice sub-projects, and each microservice project will have corresponding development environment, test environment, pre-release environment, formal environment...
- So how to manage these microservice configurations?
2) Nacos graphical management interface
-
Configuration management
-
Namespaces
3) What is the relationship between Namespace+Group+Data ID? Why is it designed like this?
-
what is
- Similar to the package name and class name in Java, the outermost namespace can be used to distinguish the deployment environment. Group and DataID logically distinguish the two target objects.
-
Three situations
-
Default:
Namespace=public,Group=DEFAULT_GROUP, 默认Cluster是DEFAULT
- The default namespace of Nacos is public, and Namespace is mainly used to achieve isolation.
- For example, if we now have three environments: development, testing, and production environments, we can create three Namespaces, and different Namespaces are isolated from each other.
- The default Group is DEFAULT_GROUP. Group can divide different microservices into the same group.
- Service is a microservice; a Service can contain multiple Clusters (clusters). Nacos' default Cluster is DEFAULT, and Cluster is a virtual division of a specified microservice.
- For example, for disaster recovery, the Service microservice is deployed in the Hangzhou computer room and the Guangzhou computer room respectively. At this time, you can give a cluster name (HZ) to the Service microservice in the Hangzhou computer room, and give a cluster name to the Service microservice in the Guangzhou computer room. (GZ), you can also try to let microservices in the same computer room call each other to improve performance.
- Finally, there is Instance, which is the instance of the microservice.
18.4.3 Case: three options for loading configuration
1) DataID scheme
-
Specify spring.profile.active and the DataID of the configuration file to read different configurations in different environments
-
Default space + default group + new two DataIDs dev and test
- Create a new dev configuration DataID: the one created above
- Create a new test configuration DataID
-
Configuration files can be read in multiple environments through the spring.profile.active property.
-
test
-
Restart 3377
-
http://localhost:3377/config/info
-
Load whatever the configuration is: test
-
2) Group plan
-
Implement environment differentiation through Group: Create a new Group
-
Create a new configuration file DataID on the nacos graphical interface console
-
bootstrap+application
- Just add a group configuration under config.
Configurable as DEV_GROUP or TEST_GROUP
- Just add a group configuration under config.
-
test
- Start Nacos
- Restart 3377
- http://localhost:3377/config/info
-
process:
nacos-config-client + TEST_GROUP + info + yaml
- It means that you are looking for files under the TEST_GROUP group under the nacos-config-client microservice, with the prefix info and the suffix yaml
- It means that you are looking for files under the TEST_GROUP group under the nacos-config-client microservice, with the prefix info and the suffix yaml
3) Namespace solution
-
Create a new Namespace for dev/test
-
Return to service management-service list view
-
Fill in according to domain name configuration
-
YML
-
bootstrap
-
application
-
-
test:
-
Starting Nacos, 3377
-
http://localhost:3377/config/info
-
What I am looking for at this time is: +dev prefix +yaml suffix file under the +TEST_GROUP group under the dev namespace
18.5 Nacos cluster and persistence configuration (important)
- Previously, using the eureka registration center required manual creation of modules, but Nacos does not require creation and only needs to be decompressed and used.
- Eureka has self-protection mechanism problems, but Nacos has blocked him without these problems.
18.5.1 Official website description
-
Official documentation 2.x: https://nacos.io/zh-cn/docs/v2/guide/admin/cluster-mode-quick-start.html
-
Official website architecture diagram (written o(╥﹏╥)o) (vip: virtual ip)
-
The above picture is translated from the official website, the real situation
-
illustrate:
- By default, Nacos uses an embedded database to store data. Therefore, if you start multiple Nacos nodes with default configuration, there will be consistency issues in data storage.
To solve this problem, Nacos uses集中式存储的方式来支持集群化部署,目前只支持MySQL的存储。
- That is: memory things are generally gone when the power is turned off, but the yml configuration file we configured in nacos as the configuration center was found to still exist after restarting nacos. Reason: nacos comes with a built-in database derby. Problem: If each nacos in cluster mode carries a derby, there will be problems with data consistency. Solution: Store all data in a mysql database cluster.
- As above, we need mysql database
- Official documentation 2.x:
-
https://nacos.io/zh-cn/docs/v2/guide/admin/deployment.html
-
Key points
-
- By default, Nacos uses an embedded database to store data. Therefore, if you start multiple Nacos nodes with default configuration, there will be consistency issues in data storage.
18.5.2 Nacos persistence configuration explanation
1) Nacos comes with its own database derby
- Nacos comes with the embedded database derby by default.
- Nacos source code pom file: https://github.com/alibaba/nacos/blob/develop/config/pom.xml
- Nacos source code pom file: https://github.com/alibaba/nacos/blob/develop/config/pom.xml
2) Configuration steps for switching from derby to mysql
-
Step 1: Find the sql script in the nacos-server-1.1.4\nacos\conf directory
-
nacos-mysql.sql
-
Execute the script: First create a database nacos_config (check it from the script file, you can just write a name yourself)
-
-
Step 2: Find application.properties in the nacos-server-1.1.4\nacos\conf directory (you need to add an additional time zone or an error will be reported:
startup.cmd -m standalone
)
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?&serverTimezone=UTC&characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=root
- The configuration comes from the official website documentation:
2) Restart Nacos for testing
-
Enter cmd in the bin directory to enter the command line window
- Start command:
startup.cmd -m standalone
- standalone represents stand-alone mode operation, non-cluster mode
- Start command:
-
After the command runs successfully, access directly:
http://localhost:8848/nacos
- The default account password is nacos
- The default account password is nacos
-
Effect: Restart Nacos, you can see a new empty recording interface, which used to be recorded into derby
-
test:
- Add a configuration information in the configuration; list
- You can see that the data has been stored in the mysql database
- Add a configuration information in the configuration; list
18.5.3 Linux version Nacos+MySQL production environment configuration
This virtual machine SpringCloud was previously configured with
- Zookeeper service registration center, the operating environment depends on jdk, so you need to configure Zookeeper and jdk
- When learning the SpringCloud Bus message bus to shield the differences between different message middleware, RabbitMQ is configured and depends on the erlang environment.
1) Nacos cluster deployment architecture description
- Note : According to the instructions on configuring the cluster on the Nacos official website, nginx should be configured as a cluster, Nacos should be configured as a cluster, and MySQL should be configured as high availability. At this time, for the convenience of testing during the learning phase, it is configured as 1 Nginx + 3 nacos registration centers + 1 mysql
-
The conditions are limited and there is only one computer. If configured as three virtual machines, it will take up too much memory. So we configured it as a pseudo cluster and configured three Nacos nodes on the current virtual machine.
-
Official website cluster environment requirements:
2) nginx download and installation configuration (linux system)
Check out the details: Another blog I wrote: https://blog.csdn.net/aa35434/article/details/124853852
- After the installation is complete, visit: http://192.168.10.140/
- start up:
-
Enter the sbin directory after installation:
cd /usr/local/src/Nginx/sbin/
-
./nginx start
-
./nginx -s stop quick stop
-
./nginx -v View nginx version number
-
3) mysql download and installation configuration (linux system)
Check out the details: Another blog I wrote: https://blog.csdn.net/aa35434/article/details/124716035
-
Set to start automatically at boot
-
After the installation is complete, use sqlyog remote login connection
4) Nacos Linux version installation
-
Download steps
-
https://github.com/alibaba/nacos/releases
-
nacos-server-1.4.6.tar.gz
-
Upload to directory: /usr/local/src/Nacos/
-
Enter this directory, unzip and install:
tar -zxvf nacos-server-1.4.6.tar.gz
-
-
Check the directory: Windows startup uses startup.cmd, and Linux uses startup.sh.
-
Before configuring, save an original configuration to avoid trouble when correcting and restoring the configuration later. (To develop this habit)
-
Problem: Originally there was only one Nacos, which could be started directly using the command. Now there are three Nacos clusters, so how to use the command to distinguish which Nacos in the cluster is started? ? ?
-
Solution: Modify the nacos script in Linux to distinguish by port number.
5) Nacos cluster configuration (Part 1)
The first one: Like Windows before, Nacos persistence configuration is also required in Linux, with the purpose of migrating data from the default derby to MySQL.
-
View the SQL script in Nacos under linux: in the conf directory after installation
-
Copy the contents of this file to Mysql and execute this script: Create the database first.
Here I use the sqlyog remote tool to connect to mysql8.0 under Linux.
-
Also modify the application.properties configuration in the conf directory
-
Back up this file before changing it
#127.0.0.1代表的是linux系统下的本机
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?&serverTimezone=UTC&characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=root
Second: cluster configuration cluster.conf of nacos on Linux server
-
Sort out the different service port numbers of 3 nacos concentrators
-
Copy the cluster.conf.example file to cluster.conf:
cp cluster.conf.example cluster.conf
-
What we modified is the newly copied file cluster.conf
192.168.10.140: 3333
192.168.10.140: 4444
192.168.10.140: 5555
- This IP cannot be written as 127.0.0.1, it must be
hostname -i
an IP that can be recognized by Linux commands.
Third: Edit Nacos startup script startup.sh so that it can accept different startup ports
-
There is startup.sh in the /mynacos/nacos/bin directory
-
Where, what to modify, how to modify
-
think
-
Modify
line 59: add parameter p, indicating that the p) branch will be executed.
Finally: clearly tell Nacos which node to start.
-
New version: p is already occupied, just change any letter to o
PORT=$OPTARG;;
-Dserver.port=${PORT}
-
Execution method: in the bin directory
./startup.sh -o 3333
6) Nacos cluster configuration (Part 2)
The first: Nginx configuration, using it as a load balancer
-
nginx.conf
Modify the nginx configuration file: the file in the conf directory of the nginx installation path
-
nginx.conf: before modification
-
nginx.conf: after modification
-
Nginx server specifies the startup configuration file command:
7) Test 1: Whether the cluster is successfully established
As of now, 1 Nginx + 3 nacos registration centers + 1 mysql
-
Start 3 Nacos:/usr/local/src/Nacos/nacos/bin/
- ./startup.sh -o 3333
- ./startup.sh -o 4444
- ./startup.sh -o 5555
- Check the progress:
ps -ef|grep nacos | grep -v grep | wc -l
-
Nginx server specifies the startup configuration file command: in the /usr/local/nginx/sbin/ directory
./nginx -c /usr/local/nginx/conf/nginx.conf
查看进程:ps -ef | grep nginx
- the file pointed to
- the file pointed to
-
Start mysql: start automatically at boot
-
Test access to nacos through nginx:
http://192.168.10.140:1111/nacos/#/login
the default account password is nacos
-
Create a new configuration test
-
Mysql of linux server inserts a record
8) Test 2: 9002 starts and registers into the nacos cluster
Microservice cloudalibaba-provider-payment9002 starts and registers into the nacos cluster
- yml
#server-addr: localhost:8848 #配置Nacos地址 配置在windows本机上的
server-addr: 192.168.10.140:1111 #配置在linux上的nginx1111,由nginx在转发给3333 4444 5555Nacos
- Start 9001
- Result: Viewing the service list, it was found that 9002 was successfully registered to the Nacos registration center installed on the Linux system.
9) Summary of high availability
19 Sentinel implements fusing and current limiting
- SpringCloud Alibaba Sentinel implements circuit breaker and current limiting
19.1 Sentinel
19.1.1 Official website
-
https://github.com/alibaba/Sentinel
-
Chinese: https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D
19.1.2 What is
- One sentence explanation, Hystrix that we explained before
- Comparison with Hystrix
19.1.3 Where to go
- https://github.com/alibaba/Sentinel/releases
- Version during video study:
- Version as of: 2323/9/2 (Pre-release: the pre-release version is v2.0.0-alpha, Latest: the latest version is v1.8.6)
- Version during video study:
19.1.4 What can you do?
19.1.5 How to play
-
document:
https://spring-cloud-alibaba-group.github.io/github-pages/greenwich/spring-cloud-alibaba.html#_spring_cloud_alibaba_sentinel
-
Various problems in using the service
- Service avalanche
- Service downgrade
- Service circuit breaker
- Service current limit
19.2 Install Sentinel console
19.2.1 The sentinel component consists of 2 parts
Sentinel is divided into two parts:
- The core library (Java client) does not depend on any framework/library and can run in all Java runtime environments. It also has good support for frameworks such as Dubbo/Spring Cloud.
- The console (Dashboard) is developed based on Spring Boot and can be run directly after packaging without the need for additional application containers such as Tomcat.
19.2.2 Installation startup-steps
download
- This time we take version 1.8.6 as an example
Run command
- premise
- java8 environment OK
- Port 8080 cannot be occupied (
注意tomact默认端口号也是8080
) - It is a jar package and
java -jar
can be run directly without installation.
- Order:
java -jar sentinel-dashboard-1.8.6.jar
Access sentinel management interface
-
http://localhost:8080
-
Login account password is sentinel
19.3 Initialize demonstration project
19.3.1 Start Nacos8848 successfully
-
start up
-
Visit: http://localhost:8848/nacos/#/login
19.3.2 Create: Module
1)cloudalibaba-sentinel-service8401
2)POM
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cloud2020</artifactId>
<groupId>com.angenin.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloudalibaba-sentinel-service8401</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
<groupId>com.angenin.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<!--SpringCloud ailibaba nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--SpringCloud ailibaba sentinel-datasource-nacos 后续做持久化用到-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<!--SpringCloud ailibaba sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--openfeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- SpringBoot整合Web组件+actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--日常通用jar包配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.6.3</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
3)YML
server:
port: 8401
spring:
application:
name: cloudalibaba-sentinal-service
cloud:
nacos:
discovery:
#Nacos服务注册中心地址(即:把此服务注册到注册中心8848)
server-addr: 127.0.0.1:8848
sentinel:
transport:
#配置Sentin dashboard地址(配置sentinel8080监控8401服务)
dashboard: 127.0.0.1:8080
# 默认8719端口,假如被占用了会自动从8719端口+1进行扫描,直到找到未被占用的 端口
port: 8719 #指定应用与Sentinel控制台交互的端口,应用本地会起一个该端口占用的HttpServer
management:
endpoints:
web:
exposure:
include: '*'
4) Main startup
package com.angenin.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@SpringBootApplication
public class MainApp8401 {
public static void main(String[] args) {
SpringApplication.run(MainApp8401.class, args);
}
}
5) Business class FlowLimitController
package com.angenin.springcloud.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class FlowLimitController {
@GetMapping("/testA")
public String testA() {
return "------testA";
}
@GetMapping("/testB")
public String testB() {
return "------testB";
}
}
6) Test
-
nacos has started
-
sentinel console started
-
Check the sentienl console after starting the 8401 microservice
-
Empty, nothing
-
The lazy loading mechanism used by Sentinel requires one visit to be monitored.
- Just perform one visit
- http://localhost:8401/testA
-
http://localhost:8401/testB
-
Click testA several times to see the effect:
-
-
Conclusion: sentinel8080 is monitoring microservices8401
-
In the graphical interface, you can see the access status of each microservice's restful style interface call.
19.4 Flow control rules
It is a flow restriction control rule, not a process control.
19.4.1 Basic introduction
-
Location:
-
explain:
19.4.2 Flow control mode
1) Direct (default)
-
System default: direct -> fail quickly
-
That is: if that resource triggers the threshold, I will limit the current flow of that resource.
-
Configuration and description:
It means that querying once within 1 second is OK. If the number exceeds 1, it will fail quickly and report a default error.
-
Test 1: QPS
-
Quickly click to visit http://localhost:8401/testA
-
Result: Blocked by Sentinel (flow limiting)
-
think???
- Directly calling the default error message is technically OK
but should we have our own follow-up processing? - Is there a fallback method like this? (That is: do not use the default error message, but use customized error message.)
- Directly calling the default error message is technically OK
-
-
Test 2: Number of concurrent threads
-
Clicked multiple times and found that the result remained unchanged.
-
The difference between QPS and the number of concurrent threads: QPS means that the request is blocked before it comes in. The number of concurrent threads comes in randomly but only one thread can be processed.
-
Add pause time in method A:
-
If you click multiple times, an error message will appear: Only one thread is allowed to come in within 1 second.
-
2) Association
-
what is
- When the associated resource reaches the threshold, it limits itself.
- When resource B associated with A reaches the threshold, A itself will be restricted.
- B caused trouble and A died.
-
Recovery code:
-
Configuration A
-
postman simulates concurrent intensive access to testB
-
Successful access to testB
-
Create a new multi-threaded collection group in postman
-
Add the access address to the new thread group
-
Run: A large number of threads access B concurrently, causing A to fail.
-
-
After running, it was found that testA hung up.
- Click to visit http://localhost:8401/testA
- Result: Blocked by Sentinel (flow limiting)
-
After these 20 threads have finished running, access will return to normal again.
3) link
- Multiple requests call the same microservice
- For example: There are three resources a, b, and c. Both a and b need to access resource c. However, when I count resource c, I only count the requests from A, and ignore the requests from b. Therefore, this flow control mode is to judge and limit the source of the request.
19.4.3 Flow control effect
1) Direct->Fast failure (default flow control processing)
- Fails directly and throws an exception: Blocked by Sentinel (flow limiting)
- Source code:
- com.alibaba.csp.sentinel.slots.block.flow.controller.DefaultController
2) Preheat
-
illustrate
- Formula: The threshold is divided by coldFactor (default value is 3). The threshold will be reached after the warm-up time.
-
Official website:
https://github.com/alibaba/Sentinel/wiki/%E6%B5%81%E9%87%8F%E6%8E%A7%E5%88%B6
- The default coldFactor is 3, that is, the requested QPS starts from threshold / 3 and gradually increases to the set QPS threshold after the warm-up time.
- Current limiting cold start:
https://github.com/alibaba/Sentinel/wiki/%E9%99%90%E6%B5%81---%E5%86%B7%E5%90%AF%E5%8A%A8
-
Source code
- com.alibaba.csp.sentinel.slots.block.flow.controller.WarmUpController
- com.alibaba.csp.sentinel.slots.block.flow.controller.WarmUpController
-
WarmUp configuration
-
I clicked http://localhost:8401/testB multiple times. It didn’t work at first, but then it got OK gradually.
-
Application scenarios:
- For example: when the flash sale system is turned on, there will be a lot of traffic, which is very likely to kill the system. The preheating method is to protect the system by slowly letting in the traffic and slowly increasing the threshold to the set value. threshold value.
3) Wait in line
-
For uniform queuing, the threshold must be set to QPS
-
Official website:
https://github.com/alibaba/Sentinel/wiki/%E6%B5%81%E9%87%8F%E6%8E%A7%E5%88%B6
-
Source code:
com.alibaba.csp.sentinel.slots.block.flow.controller.RateLimiterController
-
test
19.5 Downgrade rules
19.5.1 Official website
https://github.com/alibaba/Sentinel/wiki/%E7%86%94%E6%96%AD%E9%99%8D%E7%BA%A7
19.5.2 Basic introduction
1) Old version:
- Further explanation
- Sentinel circuit breaker downgrade will limit the call of this resource when a resource in the call link is in an unstable state (such as call timeout or an increase in abnormal ratio), so that the request fails quickly and avoids affecting other resources and causing degradation. Connection error.
- When a resource is downgraded, calls to the resource will be automatically disconnected within the next downgrade time window (the default behavior is to throw a DegradeException).
- Sentinel's circuit breaker is
没有半开
status quo- In the half-open state, the system automatically detects whether there is an abnormality in the request. If there is no abnormality, it will close the circuit breaker and resume use. If there is an abnormality, it will continue to open the circuit breaker and make it unavailable. For details, please refer to Hystrix
新版本1.8.0开始有半开状态了。
- Review of Hystrix: There is a half-open state
2) New version:
Slow call:
noun explanation:
-
Circuit breaker degradation: Circuit breaker degradation is an important means to solve the avalanche problem. The idea is that
断路器
if the abnormal proportion and slow request proportion called by the statistical service exceed the threshold,熔断
the service will be disabled. That is, all requests to access the service are intercepted; and when the service is restored, the circuit breaker will release requests to access the service.
-
Circuit breaker strategy: If the circuit breaker wants to change from open to close state, it needs to determine whether the service has conditions that trigger circuit breaker, and the judgment of circuit breaker conditions is based on the circuit breaker strategy.
-
Slow call ratio: It looks at the response time. If the response time RT (response time) is too long and exceeds the specified time, then your call is a slow call. If the request is slow, additional resources will be called, which will slow down the entire service.
-
Maximum RT: response time, indicating that any response exceeding 500 milliseconds is considered a slow call.
-
Ratio threshold: The threshold is triggered when the ratio of slow calls exceeds 0.5 and reaches more than half.
-
Fuse duration: Once the fuse is blown, the fuse duration lasts for 5 seconds, and it enters the Half-Open state after 5 seconds.
-
Minimum number of requests, statistical duration: It means that I will count at least 10 requests in the last 1 second. If the proportion of slow calls exceeding 500ms among the 10 times reaches more than half, then I will trigger the circuit breaker, and the circuit breaker time is 5 seconds. bell.
Abnormal proportion and number of anomalies:
- Exception ratio: It doesn’t depend on how fast or slow your call is, but whether you throw an exception. According to the ratio of exceptions.
- The meaning of the above configuration: 10 requests are counted within 1 second. If 4 out of 10 requests throw exceptions, then the circuit breaker is triggered, and the circuit breaker lasts for 5 seconds.
- Number of exceptions: by the number of exceptions
- The meaning of the above configuration: 10 requests are counted within 1 second. If 2 of the 10 requests throw exceptions, then the circuit breaker is triggered, and the circuit breaker lasts for 5 seconds.
19.5.3 Demotion strategy in practice
- Here I am using Sentinel version 1.8.6, while the teacher is using version 1.7.0, so the configuration methods will be slightly different.
1)RT
test
- code
@GetMapping("/testD")
public String testD() {
//暂停几秒钟线程
try {
TimeUnit.MILLISECONDS.sleep(60);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("testD 测试RT");
return "------testD";
}
-
Configuration: It means that I will count at least 5 requests in the last 1 second. If the proportion of slow calls exceeding 50ms among the 5 times reaches more than 2 times, then I will trigger the circuit breaker, and the circuit breaker time is 5 seconds.
-
Test: There is no need to use a stress testing tool, just click it yourself. As long as there are 5 requests per second, only 2 triggers are required.
2) Abnormal ratio
test
- code
@GetMapping("/testE")
public String testE() {
log.info("testD 测试RT");
int age = 10/0;
return "------testD";
}
- Configuration: Count 5 requests within 1 second. If 2 of the 5 requests throw exceptions, then the circuit breaker is triggered, and the circuit breaker lasts for 5 seconds.
- There is also no need for jmeter. Manual testing only requires 2 triggers for 5 requests per second.
3) Number of exceptions
- By the number of exceptions
- code
@GetMapping("/testF")
public String testF() {
log.info("testD 测试RT");
int age = 10/0;
return "------testD";
}
- Configuration: Count 5 requests within 1 second. If 2 of the 5 requests throw exceptions, then the circuit breaker is triggered, and the circuit breaker lasts for 5 seconds.
- There is also no need for jmeter. Manual testing only requires 2 triggers for 5 requests per second.
19.6 Hotspot key current limit
19.6.1 Basic introduction
- What is hot spot
- Hotspots are frequently accessed data. Many times we want to count or limit the TopN data with the highest access frequency in a certain hotspot data, and perform current limiting or other operations on their access.
- Hotspots are frequently accessed data. Many times we want to count or limit the TopN data with the highest access frequency in a certain hotspot data, and perform current limiting or other operations on their access.
19.6.2 Official website
https://github.com/alibaba/Sentinel/wiki/%E7%83%AD%E7%82%B9%E5%8F%82%E6%95%B0%E9%99%90%E6%B5%81
19.6.3 Review start
How to get the bottom of things: There are two types: system default and customer-defined.
- In the previous cases, after the outflow problem was limited, the default prompt of the sentinel system was used: Blocked by Sentinel (flow limiting).
Can we customize it? Similar to hystrix, if a certain method goes wrong, we will find the corresponding downgrade method? - in conclusion
- From HystrixCommand to @SentinelResource
19.6.4 Code
- Source code: com.alibaba.csp.sentinel.slots.block.BlockException
- code testing
@GetMapping("/testHotKey")
//value:资源的唯一标识,名字任意一般和上面的地址值保持一致。
@SentinelResource(value = "testHotKey",blockHandler = "dealHandler_testHotKey")
public String testHotKey(@RequestParam(value = "p1",required = false) String p1,
@RequestParam(value = "p2",required = false) String p2){
return "------testHotKey";
}
public String dealHandler_testHotKey(String p1, String p2, BlockException exception) {
//sentinel系统默认的提示:Blocked by Sentinel (flow limiting)
return "-----dealHandler_testHotKey";
}
19.6.5 Configuration
19.6.6 Testing
Multiple click test: The first parameter in the method testHotKey will be downgraded immediately as long as the QPS exceeds 1 time per second. Used our own definition
-
error:http://localhost:8401/testHotKey?p1=abc
-
error:http://localhost:8401/testHotKey?p1=abc&p2=33
-
right:http://localhost:8401/testHotKey?p2=abc
If you use the default prompt: the exception hits the front-end user interface and is not friendly.
- Multiple click test: http://localhost:8401/testHotKey?p1=abc
19.6.7 Parameter exceptions
-
The above case demonstrates the first parameter p1. When QPS exceeds 1 click per second, it will be immediately limited.
-
Exceptions
- Normal: after more than 1 second, the current will be limited immediately after reaching the threshold 1
- We expect that when the p1 parameter is a special value, its current limit value will be different from usual
- Special case: If the value of p1 is equal to 5, its threshold can reach 200
-
Configuration: Don’t forget to add a button
-
Test: multiple clicks
-
http://localhost:8401/testHotKey?p1=5
-
http://localhost:8401/testHotKey?p1=3
-
When p1 equals 5, the threshold becomes 200
-
When p1 is not equal to 5, the threshold is the usual 1
-
-
Prerequisite: Note about hotspot parameters. The parameters must be basic types or String.
19.6.8 Others
-
Let’s take a look at adding exceptions.../(ㄒoㄒ)/~~
-
Effect: It was found that the customized prompt method was not executed.
-
@SentinelResource
handles violations configured in the Sentinel console, and is handled by the blockHandler method configuration; -
RuntimeException
int age = 10/0, this is the runtime exception RunTimeException raised when java is running, @SentinelResource does not care -
Summary
@SentinelResource supervisor configuration error, operation error, abnormal operation should be performed -
Later: There are other configurations to solve this problem
19.7 System rules
-
What it is: It used to be a fine-grained method to limit current from the control layer, but now it is a coarse-grained method to limit current.
https://github.com/alibaba/Sentinel/wiki/%E7%B3%BB%E7%BB%9F%E8%87%AA%E9%80%82%E5%BA%94%E9%99%90%E6%B5%81
-
Description of various configuration parameters
-
Configure global QPS
-
Multiple accesses: No matter whether you access p1 or p2, an error will be reported. (The previous configuration was that only p1 would report an error)
19.8 @SentinelResource
19.8.1 Current limiting by resource name + subsequent processing
1) Start
- Start Nacos successfully
- Start Nacos successfully
2) Modification: cloudalibaba-sentinel-service8401
-
pom: introduced before
-
yml: no change
-
Business classRateLimitController
package com.angenin.springcloud.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.angenin.springcloud.entities.CommonResult;
import com.angenin.springcloud.entities.Payment;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class RateLimitController {
//既可以使用url地址来配置:/byResource
//也可以使用@SentinelResource注解中的value 属性来配置
@GetMapping("/byResource")
@SentinelResource(value = "byResource",blockHandler = "handleException")
public CommonResult byResource() {
return new CommonResult(200,"按资源名称限流测试OK",new Payment(2020L,"serial001"));
}
public CommonResult handleException(BlockException exception) {
return new CommonResult(444,exception.getClass().getCanonicalName()+"\t 服务不可用");
}
}
- Main boot: no change
3) Configure flow control rules
-
Configuration steps
-
Graphical configuration and code relationship
-
It means that the number of queries within 1 second is greater than 1, and it will go to our custom flow and limit the flow.
4) Test
- Click once in 1 second, OK
- Exceeded the above, clicked like crazy, returned self-defined current limiting processing information, and current limiting occurred.
5) Extra questions
- At this time, close service 8401 and have a look.
- Sentinel console, flow control rules disappeared? ? ? ? ?
- Temporary/persistent? : Description is temporary
19.8.2 Current limiting based on Url address + subsequent processing
- Limiting the current through the accessed URL will return the default current limiting processing information provided by Sentinel.
- Business classRateLimitController
@GetMapping("/rateLimit/byUrl")
@SentinelResource(value = "byUrl")
public CommonResult byUrl() {
return new CommonResult(200,"按url限流测试OK",new Payment(2020L,"serial002"));
}
-
Visit once: http://localhost:8401/rateLimit/byUrl
-
Sentinel console configuration
-
test
- Crazy click http://localhost:8401/rateLimit/byUrl
- Result: There is no prompt to configure a custom one, just use the one that comes with the system.
19.8.3 Problems caused by the above cover-up plan
- The system default does not reflect our own business requirements.
- According to the existing conditions, our customized processing method is coupled with the business code, which is not intuitive.
- Adding a cover to each business method will increase the code bloat.
- A globally unified approach is not reflected.
19.8.4 Customer-defined current limiting processing logic
- Create a CustomerBlockHandler class to customize current limiting processing logic
package com.angenin.springcloud.myhandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.angenin.springcloud.entities.CommonResult;
public class CustomerBlockHandler {
public static CommonResult handleException1(BlockException exception){
return new CommonResult(2020,"自定义的限流处理信息......CustomerBlockHandler1");
}
public static CommonResult handleExceptio2(BlockException exception){
return new CommonResult(2020,"自定义的限流处理信息......CustomerBlockHandler2");
}
}
- RateLimitController
/**
* 自定义通用的限流处理逻辑,
* blockHandlerClass = CustomerBlockHandler.class
* blockHandler = handleException2
* 上述配置:找CustomerBlockHandler类里的handleException2方法进行兜底处理
*/
@GetMapping("/rateLimit/customerBlockHandler")
//指定哪一个全局类中的的哪一个方法
@SentinelResource(value = "customerBlockHandler",
blockHandlerClass = CustomerBlockHandler.class, blockHandler = "handleExceptio2")
public CommonResult customerBlockHandler() {
return new CommonResult(200,"按客户自定义限流处理逻辑");
}
-
After starting the microservice, call it once: http://localhost:8401/rateLimit/customerBlockHandler
-
Sentinel console configuration
-
After refreshing several times, our customized one came out
-
Further explanation
19.8.5 More annotation attribute descriptions
-
One more thing: In addition to the default system prompts and using annotations to write custom prompts, it also supports writing custom prompt rules using code.
-
Sentinel mainly has three core APIs
- SphU definition resources
- Tracer definition statistics
- ContextUtil defines the context
19.9 Service circuit breaker function
- sentinel integrates ribbon+openFeign+fallback
19.9.1 Ribbon series
- Start nacos and sentinel
- structure
1) Provider 9003/9004
-
Create two new cloudalibaba-provider-payment9003/9004 with the same approach
-
POM
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cloud2020</artifactId>
<groupId>com.angenin.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloudalibaba-provider-payment9003</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!--SpringCloud ailibaba nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
<groupId>com.angenin.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<!-- SpringBoot整合Web组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--日常通用jar包配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
- YML: Remember to modify different port numbers
server:
port: 9003
spring:
application:
name: nacos-payment-provider
cloud:
nacos:
discovery:
server-addr: localhost:8848 #配置Nacos地址
management:
endpoints:
web:
exposure:
include: '*'
- main boot
package com.angenin.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class PaymentMain9003
{
public static void main(String[] args) {
SpringApplication.run(PaymentMain9003.class, args);
}
}
- Business class
package com.angenin.springcloud.controller;
import com.angenin.springcloud.entities.CommonResult;
import com.angenin.springcloud.entities.Payment;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
@RestController
public class PaymentController {
@Value("${server.port}")
private String serverPort;
public static HashMap hashMap = new HashMap();
//模拟连接一个数据库
static {
hashMap.put(1L,new Payment(1L,"28a8c1e3bc2742d8848569891fb42181"));
hashMap.put(2L,new Payment(2L,"bba8c1e3bc2742d8848569891ac32182"));
hashMap.put(3L,new Payment(3L,"6ua8c1e3bc2742d8848569891xt92183"));
}
@GetMapping(value = "/paymentSQL/{id}")
public CommonResult paymentSQL(@PathVariable("id") Long id) {
Payment payment = (Payment)hashMap.get(id);
CommonResult result = new CommonResult(200,"from mysql,serverPort: "+serverPort,payment);
return result;
}
}
- structure
- Test address: http://localhost:9003/paymentSQL/1
- Test address: http://localhost:9004/paymentSQL/1
2) Consumer 84
-
Create new cloudalibaba-consumer-nacos-order84
-
pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cloud2020</artifactId>
<groupId>com.angenin.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloudalibaba-consumer-nacos-order84</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!--SpringCloud ailibaba nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--SpringCloud ailibaba sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
<dependency>
<groupId>com.angenin.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- SpringBoot整合Web组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--日常通用jar包配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
- yml
server:
port: 84
spring:
application:
name: nacos-order-consumer
cloud:
nacos:
discovery:
server-addr: localhost:8848
sentinel:
transport:
#配置Sentinel dashboard地址
dashboard: localhost:8080
#默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
port: 8719
#消费者将要去访问的微服务名称(注册成功进nacos的微服务提供者)
service-url:
nacos-user-service: http://nacos-payment-provider
- main boot
package com.angenin.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@SpringBootApplication
public class OrderNacosMain84 {
public static void main(String[] args) {
SpringApplication.run(OrderNacosMain84.class, args);
}
}
- structure
- See below for business details
- Please restart the microservice after modification
- Hot deployment takes effect at the Java code level in a timely manner
- Annotating properties within @SentinelResource sometimes does not work well
- Purpose
- The fallback pipe runs abnormally
- blockHandler tube configuration violation
3) Configuration class: ApplicationContextConfig
- ApplicationContextConfig
package com.angenin.springcloud.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class ApplicationContextConfig {
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
4) Business class CircleBreakerController: no configuration
package com.angenin.springcloud.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.angenin.springcloud.entities.CommonResult;
import com.angenin.springcloud.entities.Payment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
@RestController
@Slf4j
public class CircleBreakerController {
public static final String SERVICE_URL = "http://nacos-payment-provider";
@Resource
private RestTemplate restTemplate;
@RequestMapping("/consumer/fallback/{id}")
@SentinelResource(value = "fallback")//没有配置
public CommonResult<Payment> fallback(@PathVariable Long id) {
CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id, CommonResult.class,id);
if (id == 4) {
throw new IllegalArgumentException ("IllegalArgumentException,非法参数异常....");
}else if (result.getData() == null) {
throw new NullPointerException ("NullPointerException,该ID没有对应记录,空指针异常");
}
return result;
}
}
- test
-
Test address: http://localhost:84/consumer/fallback/1
Through 84 consumers can access 9003/9004 through load balancing rotation training.
-
There is no configuration: an error page is given to the customer, which is not friendly (access 1, 2, and 3 set in the control layer method are normal, and access 4 and 5 are abnormal)
-
5) Business class CircleBreakerController: only configure fallback
- code
package com.angenin.springcloud.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.angenin.springcloud.entities.CommonResult;
import com.angenin.springcloud.entities.Payment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
@RestController
@Slf4j
public class CircleBreakerController {
public static final String SERVICE_URL = "http://nacos-payment-provider";
@Resource
private RestTemplate restTemplate;
@RequestMapping("/consumer/fallback/{id}")
//@SentinelResource(value = "fallback")//没有配置
@SentinelResource(value = "fallback", fallback = "handlerFallback") //fallback只负责业务异常
public CommonResult<Payment> fallback(@PathVariable Long id) {
CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id, CommonResult.class,id);
if (id == 4) {
throw new IllegalArgumentException ("IllegalArgumentException,非法参数异常....");
}else if (result.getData() == null) {
throw new NullPointerException ("NullPointerException,该ID没有对应记录,空指针异常");
}
return result;
}
//本例是fallback
public CommonResult handlerFallback(@PathVariable Long id,Throwable e) {
Payment payment = new Payment(id,"null");
return new CommonResult<>(444,"兜底异常handlerFallback,exception内容 "+e.getMessage(),payment);
}
}
- Test: http://localhost:84/consumer/fallback/5 (the error page becomes a custom escape method)
6) Business class CircleBreakerController: only configure blockHandler
- code
package com.angenin.springcloud.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.angenin.springcloud.entities.CommonResult;
import com.angenin.springcloud.entities.Payment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
@RestController
@Slf4j
public class CircleBreakerController {
public static final String SERVICE_URL = "http://nacos-payment-provider";
@Resource
private RestTemplate restTemplate;
@RequestMapping("/consumer/fallback/{id}")
//@SentinelResource(value = "fallback")//没有配置
//@SentinelResource(value = "fallback", fallback = "handlerFallback") //fallback只负责业务异常
@SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只负责sentinel控制台配置违规
public CommonResult<Payment> fallback(@PathVariable Long id) {
CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id, CommonResult.class,id);
if (id == 4) {
throw new IllegalArgumentException ("IllegalArgumentException,非法参数异常....");
}else if (result.getData() == null) {
throw new NullPointerException ("NullPointerException,该ID没有对应记录,空指针异常");
}
return result;
}
//本例是fallback
/* public CommonResult handlerFallback(@PathVariable Long id,Throwable e) {
Payment payment = new Payment(id,"null");
return new CommonResult<>(444,"兜底异常handlerFallback,exception内容 "+e.getMessage(),payment);
}*/
//本例是blockHandler
public CommonResult blockHandler(@PathVariable Long id, BlockException blockException) {
Payment payment = new Payment(id,"null");
return new CommonResult<>(445,"blockHandler-sentinel限流,无此流水: blockException "+blockException.getMessage(),payment);
}
}
-
Configuration
-
Test: http://localhost:84/consumer/fallback/4
- first click
- Quick click
- Note: fallback is only responsible for business exceptions, and blockHandler is only responsible for sentinel console configuration violations.
- first click
7) Business class CircleBreakerController: both fallback and blockHandler are configured
- code
package com.angenin.springcloud.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.angenin.springcloud.entities.CommonResult;
import com.angenin.springcloud.entities.Payment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
@RestController
@Slf4j
public class CircleBreakerController {
public static final String SERVICE_URL = "http://nacos-payment-provider";
@Resource
private RestTemplate restTemplate;
@RequestMapping("/consumer/fallback/{id}")
//@SentinelResource(value = "fallback")//没有配置
//@SentinelResource(value = "fallback", fallback = "handlerFallback") //fallback只负责业务异常
//@SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只负责sentinel控制台配置违规
@SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler") //都配置
public CommonResult<Payment> fallback(@PathVariable Long id) {
CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id, CommonResult.class,id);
if (id == 4) {
throw new IllegalArgumentException ("IllegalArgumentException,非法参数异常....");
}else if (result.getData() == null) {
throw new NullPointerException ("NullPointerException,该ID没有对应记录,空指针异常");
}
return result;
}
//本例是fallback
public CommonResult handlerFallback(@PathVariable Long id,Throwable e) {
Payment payment = new Payment(id,"null");
return new CommonResult<>(444,"兜底异常handlerFallback,exception内容 "+e.getMessage(),payment);
}
//本例是blockHandler
public CommonResult blockHandler(@PathVariable Long id, BlockException blockException) {
Payment payment = new Payment(id,"null");
return new CommonResult<>(445,"blockHandler-sentinel限流,无此流水: blockException "+blockException.getMessage(),payment);
}
}
-
Configuration
-
Test 1:
http://localhost:84/consumer/fallback/1
(Access is normal)-
First click: normal access
-
Quick click: If the threshold is exceeded, the custom blockHandler method will be accessed
-
-
Test 2:
http://localhost:84/consumer/fallback/4
(Access exception)-
First click: Return to the custom method marked by the fallback attribute
-
Quick click: exceeds the threshold, and meets both the fallback business exception and the blockHandler console configuration violation. Then the result returned at this time is the method specified by the blockHandler attribute.
-
-
Conclusion: If both blockHandler and fallback are configured, only the blockHandler processing logic will be entered when a BlockException is thrown due to current limiting downgrade.
8) Business class CircleBreakerController: ignore attributes...
- That is: to exclude the specified exception, even if a custom method prompt is configured to be executed after an exception occurs, the system's own prompt information will still be executed when this exception occurs after adding this attribute.
exceptionsToIgnore = {IllegalArgumentException.class}
http://localhost:84/consumer/fallback/4
19.9.2 Feign series
1) Modify the 84 module
-
84 Consumer calls provider 9003
-
Feign components are generally on the consumer side
2)POM
<!--SpringCloud openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
3)YML
server:
port: 84
spring:
application:
name: nacos-order-consumer
cloud:
nacos:
discovery:
server-addr: localhost:8848
sentinel:
transport:
#配置Sentinel dashboard地址
dashboard: localhost:8080
#默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
port: 8719
#消费者将要去访问的微服务名称(注册成功进nacos的微服务提供者)
service-url:
nacos-user-service: http://nacos-payment-provider
# 激活Sentinel对Feign的支持
feign:
sentinel:
enabled: true
4) Business category
- interface
package com.angenin.springcloud.service;
import com.angenin.springcloud.entities.CommonResult;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
/**
* value:找到注册中心上的微服务接口名
* 过程:fallback:相当于去找nacos-payment-provider这个微服务的名字,去调用下面已有的方法,
* 假如出事了去调用PaymentFallbackService里面的方法
*/
@FeignClient(value = "nacos-payment-provider",fallback = PaymentFallbackService.class)//调用中关闭9003服务提供者
public interface PaymentService {
@GetMapping(value = "/paymentSQL/{id}")
public CommonResult paymentSQL(@PathVariable("id") Long id);
}
- Interface implementation class: mixed with business logic? ? ? confusion
package com.angenin.springcloud.service;
import com.angenin.springcloud.entities.CommonResult;
import com.angenin.springcloud.entities.Payment;
import org.springframework.stereotype.Component;
@Component
public class PaymentFallbackService implements PaymentService {
@Override
public CommonResult paymentSQL(Long id) {
return new CommonResult(444,"服务降级返回,没有该流水信息",new Payment(id, "errorSerial......"));
}
}
- Controller
//==================OpenFeign
@Resource
private PaymentService paymentService;
@GetMapping(value = "/consumer/openfeign/{id}")
public CommonResult paymentSQL(@PathVariable("id") Long id) {
if(id == 4) {
throw new RuntimeException("没有该id");
}
return paymentService.paymentSQL(id);
}
5) Main startup
package com.angenin.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients //启用 激活
public class OrderNacosMain84 {
public static void main(String[] args) {
SpringApplication.run(OrderNacosMain84.class, args);
}
}
6) Test
-
Start consumer 84, start producer 9003
-
http://localhost:84/consumer/openfeign/1 (correct access)
-
Test 84 calls 9003. At this time
故意关闭9003微服务提供者
, the consumer side of 84 will be automatically downgraded and will not be consumed.
19.9.3 Comparison of circuit breakers
Sentinel | Hystrix | resilience4j | |
---|---|---|---|
Isolation strategy | Semaphore isolation (limiting the number of concurrent threads) | Thread pool isolation/semaphore isolation | Semaphore isolation |
circuit breaker downgrade strategy | Based on response time, exception ratio, and number of exceptions | Based on abnormal ratio | Based on exception ratio, response time |
Real-time statistics implementation | Sliding window (LeapArray) | Sliding window (based on RxJava) | Ring Bit Buffer |
Dynamic rule configuration | Support multiple data sources | Support multiple data sources | Limited support |
Scalability | multiple extension points | Plug-in form | interface form |
Annotation-based support | support | support | support |
Limiting | Based on QPS, supports current limiting based on calling relationships | limited support | Rate Limiter |
Traffic shaping | Support preheating mode, equalizer mode and preheating queuing mode | not support | Simple Rate Limiter mode |
System adaptive protection | support | not support | not support |
console | Provides an out-of-the-box console that can configure rules, view second-level monitoring, machine discovery, etc. | Simple monitoring and viewing | No console is provided, but can be connected to other monitoring systems |
19.10 Rule persistence
19.10.1 What is
Once we restart the application, the sentinel rules will disappear and the production environment needs to persist the configuration rules.
19.10.2 How to play
Persist the current limiting configuration rules into Nacos. As long as you refresh a rest address of 8401, the flow control rules on the sentinel console can be seen. As long as the configuration in Nacos is not deleted, the flow control rules on sentinel on 8401 will continue to be valid.
19.10.3 Step: Modify cloudalibaba-sentinel-service8401
1)POM
<!--SpringCloud ailibaba sentinel-datasource-nacos 后续做持久化用到-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
2)YML
server:
port: 8401
spring:
application:
name: cloudalibaba-sentinal-service
cloud:
nacos:
discovery:
#Nacos服务注册中心地址(即:把此服务注册到注册中心8848)
server-addr: 127.0.0.1:8848
sentinel:
transport:
#配置Sentin dashboard地址(配置sentinel8080监控8401服务)
dashboard: 127.0.0.1:8080
# 默认8719端口,假如被占用了会自动从8719端口+1进行扫描,直到找到未被占用的 端口
port: 8719 #指定应用与Sentinel控制台交互的端口,应用本地会起一个该端口占用的HttpServer
datasource: #<---------------------------关注点,添加Nacos数据源配置
ds1:
nacos:
server-addr: localhost:8848
dataId: cloudalibaba-sentinel-service
groupId: DEFAULT_GROUP
data-type: json
rule-type: flow
management:
endpoints:
web:
exposure:
include: '*'
3) Add Nacos business rule configuration
- Content analysis
- resource: resource name;
- limitApp: source application;
- grade: threshold type, 0 represents the number of threads, 1 represents QPS;
- count: single machine threshold;
- strategy: flow control mode, 0 means direct, 1 means association, 2 means link;
- controlBehavior: flow control effect, 0 means fast failure, 1 means Warm Up, 2 means waiting in line;
- clusterMode: whether to cluster.
[
{
"resource": "/rateLimit/byUrl",
"limitApp": "default",
"grade": 1,
"count": 1,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}
]
4) Add configuration and start 8401
-
Control layer method: previous method
-
Configure flow control rules
-
Start 8401
5) Quick access to test interface
- http://localhost:8401/rateLimit/byUrl
6) Stop 8401 and look at sentinel again
- After shutting down, I found that the flow control rules were gone.
7) Restart 8401 and check sentinel again
-
At first glance, it still doesn’t exist. Wait a moment.
-
Called multiple times: http://localhost:8401/rateLimit/byUrl
-
Refresh the sentinel page: reconfiguration appears, persistence verification passed
20 Seata handles distributed transactions
- SpringCloud Alibaba Seata handles distributed transactions
阳哥讲的版本太老了,这里我已黑马的版本为例进行学习。
- Blog View:
待发布
- Blog View:
20.1 Seata-Server installation (1.7.0)
20.3.1 Release Notes
- Note: The configurations of different versions of Seata are very different. Before 1.4.2, two configuration files needed to be modified under conf. Now they are integrated into one application.yml file. The following explains how to install and configure using version 1.7.0 (2023 -9-5)
20.1.2 Seata Server storage mode (3 types)
- Unzip seata-server-1.7.0.zip to the specified directory and modify the application.yml configuration file in the conf directory. First, back up the original application.yml file.
- View the application.yml file
# Copyright 1999-2019 Seata.io Group.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
server:
port: 7091 #它是UI界面的端口号,不是对外提供服务的端口号
spring: #服务名
application:
name: seata-server
logging: #日志
config: classpath:logback-spring.xml
file:
path: ${
user.home}/logs/seata
extend:
logstash-appender:
destination: 127.0.0.1:4560
kafka-appender:
bootstrap-servers: 127.0.0.1:9092
topic: logback_to_logstash
console: #平台界面的用户名密码
user:
username: seata
password: seata
seata:
config: #配置中心
# support: nacos, consul, apollo, zk, etcd3
type: file
registry: #注册中心
# support: nacos, eureka, redis, zk, consul, etcd3, sofa
type: file
store: #存储中心
# support: file 、 db 、 redis
mode: file
# server: #这才是对外提供的端口号,默认是7091+1000=8091.所以不用配置
# service-port: 8091 #If not configured, the default is '${server.port} + 1000'
security: #安全
secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
tokenValidityInMilliseconds: 1800000
ignore:
urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.jpeg,/**/*.ico,/api/v1/auth/login
- 3 storage modes : Seata Server needs to store global transactions and branch transactions in order to manage them. Currently, three co-storage modes are supported: file, db and redis (raft and mongodb will be introduced later).
- File mode: will store relevant data in local files, generally used for in-machine testing of Seata Server.
- db mode: will store relevant data in the database, generally used for Seata Server cluster deployment in production environments. The most commonly used mode in production environments.
- redis mode: Relevant data will be stored in redis, generally used for Seata Server cluster deployment in production environments. The performance is slightly higher than that of DB mode. If you have higher performance requirements, you can choose redis mode.
20.1.3 Configuration steps: taking db mode as an example
1) Modify the application.yml configuration file
Note: For modifications to this file, you can refer to the contents of the sample file.
Make a copy of the original file before modifying it.
Modify Storage Center
- Copy the sample file contents
- Modify application.yml
store:
# support: file 、 db 、 redis
mode: db
session:
mode: db
lock:
mode: db
db:
datasource: druid
db-type: mysql
driver-class-name: com.mysql.jdbc.Driver #如果是mysql8.0驱动为:com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/seata?rewriteBatchedStatements=true
user: root
password: root
min-conn: 10
max-conn: 100
global-table: global_table
branch-table: branch_table
lock-table: lock_table
distributed-lock-table: distributed_lock
query-limit: 1000
max-wait: 5000
Modify configuration center
-
Copy the sample file contents
-
Modify application.yml
seata:
config:
# support: nacos, consul, apollo, zk, etcd3
type: nacos
nacos:
server-addr: 127.0.0.1:8848
namespace:
group: fsp_tx_group #分组名称
username: nacos #连接Nacos平台的用户名密码默认都是nacos
password: nacos
context-path:
##if use MSE Nacos with auth, mutex with username/password attribute
#access-key:
#secret-key:
data-id: seataServer.properties #之后需要再nacos配置中心创建此文件。
Modify registration center
-
Copy the sample file contents
-
Modify application.yml
registry:
# support: nacos, eureka, redis, zk, consul, etcd3, sofa
type: nacos
nacos:
application: seata-server #启动后注册到注册中心的服务名
server-addr: 127.0.0.1:8848
group: fsp_tx_group #组名保持一致
namespace:
cluster: default
username: nacos
password: nacos
context-path:
##if use MSE Nacos with auth, mutex with username/password attribute
#access-key:
#secret-key:
2) Create a new library seata and execute the script
-
The previous configuration in the application.yml file was to use the database to manage global transactions and branch transactions, so a library was created and a new table was created in the library.
-
Script location: Note that it is not recommended to find the script from the official website, because the slow update speed on the official website may cause version inconsistency. It is recommended to find it from the downloaded installation package.
-
Create the seata database and execute the script
3)seataServer.properties
-
This file needs to be configured on the nacos platform
-
Configuration content source:
-
Copy the original file and modify the contents of the config.txt file.
#For details about configuration items, see https://seata.io/zh-cn/docs/user/configurations.html
#Transport configuration, for client and server
transport.type=TCP
transport.server=NIO
transport.heartbeat=true
transport.enableTmClientBatchSendRequest=false
transport.enableRmClientBatchSendRequest=true
transport.enableTcServerBatchSendResponse=false
transport.rpcRmRequestTimeout=30000
transport.rpcTmRequestTimeout=30000
transport.rpcTcRequestTimeout=30000
transport.threadFactory.bossThreadPrefix=NettyBoss
transport.threadFactory.workerThreadPrefix=NettyServerNIOWorker
transport.threadFactory.serverExecutorThreadPrefix=NettyServerBizHandler
transport.threadFactory.shareBossWorker=false
transport.threadFactory.clientSelectorThreadPrefix=NettyClientSelector
transport.threadFactory.clientSelectorThreadSize=1
transport.threadFactory.clientWorkerThreadPrefix=NettyClientWorkerThread
transport.threadFactory.bossThreadSize=1
transport.threadFactory.workerThreadSize=default
transport.shutdown.wait=3
transport.serialization=seata
transport.compressor=none
#Transaction routing rules configuration, only for the client
service.vgroupMapping.default_tx_group=default
#If you use a registry, you can ignore it
service.default.grouplist=127.0.0.1:8091
service.enableDegrade=false
service.disableGlobalTransaction=false
#Transaction rule configuration, only for the client
client.rm.asyncCommitBufferLimit=10000
client.rm.lock.retryInterval=10
client.rm.lock.retryTimes=30
client.rm.lock.retryPolicyBranchRollbackOnConflict=true
client.rm.reportRetryCount=5
client.rm.tableMetaCheckEnable=true
client.rm.tableMetaCheckerInterval=60000
client.rm.sqlParserType=druid
client.rm.reportSuccessEnable=false
client.rm.sagaBranchRegisterEnable=false
client.rm.sagaJsonParser=fastjson
client.rm.tccActionInterceptorOrder=-2147482648
client.tm.commitRetryCount=5
client.tm.rollbackRetryCount=5
client.tm.defaultGlobalTransactionTimeout=60000
client.tm.degradeCheck=false
client.tm.degradeCheckAllowTimes=10
client.tm.degradeCheckPeriod=2000
client.tm.interceptorOrder=-2147482648
client.undo.dataValidation=true
client.undo.logSerialization=jackson
client.undo.onlyCareUpdateColumns=true
server.undo.logSaveDays=7
server.undo.logDeletePeriod=86400000
client.undo.logTable=undo_log
client.undo.compress.enable=true
client.undo.compress.type=zip
client.undo.compress.threshold=64k
#For TCC transaction mode
tcc.fence.logTableName=tcc_fence_log
tcc.fence.cleanPeriod=1h
#Log rule configuration, for client and server
log.exceptionRate=100
#Transaction storage configuration, only for the server. The file, db, and redis configuration values are optional.
store.mode=db
store.lock.mode=db
store.session.mode=db
#Used for password encryption
#store.publicKey=
#If `store.mode,store.lock.mode,store.session.mode` are not equal to `file`, you can remove the configuration block.
#store.file.dir=file_store/data
#store.file.maxBranchSessionSize=16384
#store.file.maxGlobalSessionSize=512
#store.file.fileWriteBufferCacheSize=16384
#store.file.flushDiskMode=async
#store.file.sessionReloadReadSize=100
#These configurations are required if the `store mode` is `db`. If `store.mode,store.lock.mode,store.session.mode` are not equal to `db`, you can remove the configuration block.
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.jdbc.Driver
store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true&rewriteBatchedStatements=true
store.db.user=root
store.db.password=root
store.db.minConn=5
store.db.maxConn=30
store.db.globalTable=global_table
store.db.branchTable=branch_table
store.db.distributedLockTable=distributed_lock
store.db.queryLimit=100
store.db.lockTable=lock_table
store.db.maxWait=5000
#These configurations are required if the `store mode` is `redis`. If `store.mode,store.lock.mode,store.session.mode` are not equal to `redis`, you can remove the configuration block.
#store.redis.mode=single
#store.redis.single.host=127.0.0.1
#store.redis.single.port=6379
#store.redis.sentinel.masterName=
#store.redis.sentinel.sentinelHosts=
#store.redis.maxConn=10
#store.redis.minConn=1
#store.redis.maxTotal=100
#store.redis.database=0
#store.redis.password=
#store.redis.queryLimit=100
#Transaction rule configuration, only for the server
server.recovery.committingRetryPeriod=1000
server.recovery.asynCommittingRetryPeriod=1000
server.recovery.rollbackingRetryPeriod=1000
server.recovery.timeoutRetryPeriod=1000
server.maxCommitRetryTimeout=-1
server.maxRollbackRetryTimeout=-1
server.rollbackRetryTimeoutUnlockEnable=false
server.distributedLockExpireTime=10000
server.xaerNotaRetryTimeout=60000
server.session.branchAsyncQueueSize=5000
server.session.enableBranchAsyncRemove=false
server.enableParallelRequestHandle=false
#Metrics configuration, only for the server
metrics.enabled=false
metrics.registryType=compact
metrics.exporterList=prometheus
metrics.exporterPrometheusPort=9898
- For the meaning of the above configuration parameter information, you can check the official website:
- Start Nacos and log in to the management page
- Create a new one in the configuration list: seataServer.properties. The configuration content is the config.txt file just modified. Note that the type is properties.
4) Start
First start Nacos port number 8848, and then start seata-server
- Location
- cmd, enter the command:
seata-server.bat -m db
, the default is file, so db must be specified. If it is not the local machine, you also need to specify the ip and port number.
- View the list of services:
20.2 domain entity class
- Different companies may have different names for entity classes.
- Entity class that encapsulates the database. Entity classes that interact with front-end pages.