17 Introduction to springcloud Alibaba
What can you do?
Service current limit degradation: by default, it supports the access of Servlet, Feign, RestTemplate, Dubbo and RocketMQ current limit degradation functions. You can modify the current limit degradation rules in real time through the console during operation. It also supports viewing the current limit degradation Metrics monitoring.
Service registration and discovery: it adapts to the Spring Cloud service registration and discovery standard and integrates Ribbon support by default.
Distributed configuration management: supports external configuration in distributed system, and automatically refreshes when the configuration changes.
Message driven capability: build message driven capability 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. Support the storage and access of any type of data in any application, any time and any place.
Distributed task scheduling: provide second level, accurate, highly reliable and highly available timed (based on Cron expression) task scheduling services. At the same time, it provides a distributed task execution model, such as grid tasks. Grid tasks support the uniform distribution of tasks to all workers (schedulerx clients) for execution.
Where?
https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md
How do you play?
18 SpringCloud Alibaba Nacos service registration and configuration center
18.1 installation and operation of Nacos
First, Download Nacos 1.1.4 on the official website. 1.1.4 is used here
https://github.com/alibaba/nacos/releases/tag/1.1.4
18.2 demonstration of Nacos as a service registry
Official website document
https://spring-cloud-alibaba-group.github.io/github-pages/greenwich/spring-cloud-alibaba.html#_spring_cloud_alibaba_nacos_config
18.2.1 Nacos based service providers
Create new modules cloudalibaba provider payment9001 and 9002
9002 completely refers to 9001, but the port is different
Here, because we are a child project, we need to introduce the corresponding version management dependency in the parent project
<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>
Then the current pom
<dependencies> <!--SpringCloud ailibaba nacos --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!-- SpringBoot integration Web assembly --> <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> <!--Daily general jar Package configuration--> <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>
yaml
server: port: 9001 spring: application: name: nacos-payment-provider cloud: nacos: discovery: server-addr: localhost:8848 #Configure Nacos address management: endpoints: web: exposure: include: '*' #Exposure monitoring
Don't forget to add @ EnableDiscoveryClient annotation for main startup
@EnableDiscoveryClient @SpringBootApplication public class PaymentMain9001 { public static void main(String[] args) { SpringApplication.run(PaymentMain9001.class, args); } }
Simple business class
@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; } }
When we build both modules, we can see the corresponding information in the configuration center
18.2.2 Nacos based service consumers
Nacos automatically integrates load balancing
Create a new module cloudalibaba-consumer-nacos-order83
pom
<dependencies> <!--SpringCloud ailibaba nacos --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!-- Introduce self defined api General package, you can use Payment payment Entity --> <dependency> <groupId>com.atguigu.springcloud</groupId> <artifactId>cloud-api-commons</artifactId> <version>${project.version}</version> </dependency> <!-- SpringBoot integration Web assembly --> <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> <!--Daily general jar Package configuration--> <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>
yaml
server: port: 83 spring: application: name: nacos-order-consumer cloud: nacos: discovery: server-addr: localhost:8848 #Address of nasos #The name of the microservice that the consumer will access (the microservice provider successfully registered in nacos) service-url: nacos-user-service: http://Which microservice does the Nacos payment provider # access
Don't forget to add @ EnableDiscoveryClient annotation for main startup
@EnableDiscoveryClient @SpringBootApplication public class OrderNacosMain83 { public static void main(String[] args) { SpringApplication.run(OrderNacosMain83.class,args); } }
Because this is the RestTemplate instance to be used by the consumer, there is one more configuration class
Because of load balancing, don't forget to add the @ LoadBalanced annotation
@Configuration public class ApplicationContextBean{ @Bean @LoadBalanced public RestTemplate getRestTemplate() { return new RestTemplate(); } }
controller interface
@RestController public class OrderNacosController{ @Resource private RestTemplate restTemplate; @Value("${service-url.nacos-user-service}") private String serverURL; @GetMapping("/consumer/payment/nacos/{id}") public String paymentInfo(@PathVariable("id") Long id) { return restTemplate.getForObject(serverURL+"/payment/nacos/"+id,String.class); } }
Finally, the consumer will find two service ports to provide services in turn.
18.3 demonstration of Nacos as service configuration center
18.3.1 establishment of read configuration module
Create a new module cloudalibaba config Nacos client3377
pom
<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> <!--General basic configuration--> <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>
Two yaml
bootstrap.yaml
# nacos configuration server: port: 3377 spring: application: name: nacos-config-client cloud: nacos: discovery: server-addr: localhost:8848 #Nacos service registry address config: server-addr: localhost:8848 #Nacos as configuration center address file-extension: yaml #Specifies the configuration of yaml format # ${spring.application.name}-${spring.profile.active}.${spring.cloud.nacos.config.file-extension}
application.yaml
spring: profiles: active: dev # Represents the development environment
Main start
@EnableDiscoveryClient @SpringBootApplication public class NacosConfigClientMain3377 { public static void main(String[] args) { SpringApplication.run(NacosConfigClientMain3377.class, args); } }
controller interface
Because the nacos registry is used here, you need to add the @ RefreshScope annotation to refresh automatically
@RestController @RefreshScope //Add @ RefreshScope annotation to the controller class to make the configuration under the current class support the dynamic refresh function of Nacos. public class ConfigClientController { @Value("${config.info}") private String configInfo; @GetMapping("/config/info") public String getConfigInfo() { return configInfo; } }
18.3.2 establishment of Nacos configuration center file
How to build it
The naming of documents is also noted as follows
As shown in the figure below, we wrote the configuration in two files before
Question:
Question 1:
In actual development, a system is usually prepared
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?
Question 2:
A large distributed microservice system will have many microservice sub projects,
Each microservice project will have a corresponding development environment, test environment, advance environment, formal environment
How to manage these micro service configurations?
Namespace+Group+Data ID? Why is it so designed?
What is 1
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 two target objects.
2. Three aspects
Default:
Namespace=public,Group=DEFAULT_GROUP, the default Cluster is default
The default Namespace of Nacos is public, which is mainly used to realize isolation.
For example, we now have three environments: development, testing and production. We can create three namespaces. Different namespaces are isolated.
Group defaults to DEFAULT_GROUP and group can divide different micro services into the same group
Service is a micro service; A service can contain multiple clusters. The DEFAULT Cluster of Nacos is DEFAULT, and the Cluster is a virtual partition of the specified micro service.
For example, for disaster recovery, Service microservices are deployed in Hangzhou computer room and Guangzhou computer room respectively,
At this time, a cluster name (HZ) can be given to the Service micro Service in Hangzhou computer room,
Give a cluster name (GZ) to the Service microservices in the Guangzhou computer room, and try to make the microservices in the same computer room call each other to improve performance.
The last is Instance, which is the Instance of micro service.
18.3.2.1 configure according to id
Create a new file to make his name different from the previous one
One - dev, one - test
How to use it? Just modify active
18.3.2.2 Group differentiated documents
Create a new group
Add the group attribute to the corresponding configuration class, and then enter the corresponding group
18.3.2.3 Namespace scheme
Create a new namespace and configure it according to its
Configure the space id in the application
18.4 Nacos cluster and persistent configuration (important)
Currently, persistence only supports mysql
When persistence is not configured, derby database is used by default. How to switch?
18.4.1 persistence of windows
Configuration steps for switching from derby to mysql
Create Nacos in mysql database first_ Config database
Then execute the script
/******************************************/ /* Full database name = nacos_config */ /* Table name = config_info */ /******************************************/ CREATE TABLE `config_info` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `data_id` varchar(255) NOT NULL COMMENT 'data_id', `group_id` varchar(255) DEFAULT NULL, `content` longtext NOT NULL COMMENT 'content', `md5` varchar(32) DEFAULT NULL COMMENT 'md5', `gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT 'Creation time', `gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT 'Modification time', `src_user` text COMMENT 'source user', `src_ip` varchar(20) DEFAULT NULL COMMENT 'source ip', `app_name` varchar(128) DEFAULT NULL, `tenant_id` varchar(128) DEFAULT '' COMMENT 'Tenant field', `c_desc` varchar(256) DEFAULT NULL, `c_use` varchar(64) DEFAULT NULL, `effect` varchar(64) DEFAULT NULL, `type` varchar(64) DEFAULT NULL, `c_schema` text, PRIMARY KEY (`id`), UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info'; /******************************************/ /* Full database name = nacos_config */ /* Table name = config_info_aggr */ /******************************************/ CREATE TABLE `config_info_aggr` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `data_id` varchar(255) NOT NULL COMMENT 'data_id', `group_id` varchar(255) NOT NULL COMMENT 'group_id', `datum_id` varchar(255) NOT NULL COMMENT 'datum_id', `content` longtext NOT NULL COMMENT 'content', `gmt_modified` datetime NOT NULL COMMENT 'Modification time', `app_name` varchar(128) DEFAULT NULL, `tenant_id` varchar(128) DEFAULT '' COMMENT 'Tenant field', PRIMARY KEY (`id`), UNIQUE KEY `uk_configinfoaggr_datagrouptenantdatum` (`data_id`,`group_id`,`tenant_id`,`datum_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Add tenant field'; /******************************************/ /* Full database name = nacos_config */ /* Table name = config_info_beta */ /******************************************/ CREATE TABLE `config_info_beta` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `data_id` varchar(255) NOT NULL COMMENT 'data_id', `group_id` varchar(128) NOT NULL COMMENT 'group_id', `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name', `content` longtext NOT NULL COMMENT 'content', `beta_ips` varchar(1024) DEFAULT NULL COMMENT 'betaIps', `md5` varchar(32) DEFAULT NULL COMMENT 'md5', `gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT 'Creation time', `gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT 'Modification time', `src_user` text COMMENT 'source user', `src_ip` varchar(20) DEFAULT NULL COMMENT 'source ip', `tenant_id` varchar(128) DEFAULT '' COMMENT 'Tenant field', PRIMARY KEY (`id`), UNIQUE KEY `uk_configinfobeta_datagrouptenant` (`data_id`,`group_id`,`tenant_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_beta'; /******************************************/ /* Full database name = nacos_config */ /* Table name = config_info_tag */ /******************************************/ CREATE TABLE `config_info_tag` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `data_id` varchar(255) NOT NULL COMMENT 'data_id', `group_id` varchar(128) NOT NULL COMMENT 'group_id', `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id', `tag_id` varchar(128) NOT NULL COMMENT 'tag_id', `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name', `content` longtext NOT NULL COMMENT 'content', `md5` varchar(32) DEFAULT NULL COMMENT 'md5', `gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT 'Creation time', `gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT 'Modification time', `src_user` text COMMENT 'source user', `src_ip` varchar(20) DEFAULT NULL COMMENT 'source ip', PRIMARY KEY (`id`), UNIQUE KEY `uk_configinfotag_datagrouptenanttag` (`data_id`,`group_id`,`tenant_id`,`tag_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_tag'; /******************************************/ /* Full database name = nacos_config */ /* Table name = config_tags_relation */ /******************************************/ CREATE TABLE `config_tags_relation` ( `id` bigint(20) NOT NULL COMMENT 'id', `tag_name` varchar(128) NOT NULL COMMENT 'tag_name', `tag_type` varchar(64) DEFAULT NULL COMMENT 'tag_type', `data_id` varchar(255) NOT NULL COMMENT 'data_id', `group_id` varchar(128) NOT NULL COMMENT 'group_id', `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id', `nid` bigint(20) NOT NULL AUTO_INCREMENT, PRIMARY KEY (`nid`), UNIQUE KEY `uk_configtagrelation_configidtag` (`id`,`tag_name`,`tag_type`), KEY `idx_tenant_id` (`tenant_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_tag_relation'; /******************************************/ /* Full database name = nacos_config */ /* Table name = group_capacity */ /******************************************/ CREATE TABLE `group_capacity` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Primary key ID', `group_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Group ID,A null character indicates the entire cluster', `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Quota, 0 means the default value is used', `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Usage', `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'The maximum size of a single configuration, in bytes. 0 means the default value is used', `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Maximum number of aggregate sub configurations, 0 means the default value is used', `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'The upper limit of the sub configuration size of a single aggregate data, in bytes. 0 means the default value is used', `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Maximum change history quantity', `gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT 'Creation time', `gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT 'Modification time', PRIMARY KEY (`id`), UNIQUE KEY `uk_group_id` (`group_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Cluster, each Group Capacity information table'; /******************************************/ /* Full database name = nacos_config */ /* Table name = his_config_info */ /******************************************/ CREATE TABLE `his_config_info` ( `id` bigint(64) unsigned NOT NULL, `nid` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `data_id` varchar(255) NOT NULL, `group_id` varchar(128) NOT NULL, `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name', `content` longtext NOT NULL, `md5` varchar(32) DEFAULT NULL, `gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00', `gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00', `src_user` text, `src_ip` varchar(20) DEFAULT NULL, `op_type` char(10) DEFAULT NULL, `tenant_id` varchar(128) DEFAULT '' COMMENT 'Tenant field', PRIMARY KEY (`nid`), KEY `idx_gmt_create` (`gmt_create`), KEY `idx_gmt_modified` (`gmt_modified`), KEY `idx_did` (`data_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Multi tenant transformation'; /******************************************/ /* Full database name = nacos_config */ /* Table name = tenant_capacity */ /******************************************/ CREATE TABLE `tenant_capacity` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Primary key ID', `tenant_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Tenant ID', `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Quota, 0 means the default value is used', `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Usage', `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'The maximum size of a single configuration, in bytes. 0 means the default value is used', `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Maximum number of aggregate sub configurations', `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'The upper limit of the sub configuration size of a single aggregate data, in bytes. 0 means the default value is used', `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Maximum change history quantity', `gmt_create` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT 'Creation time', `gmt_modified` datetime NOT NULL DEFAULT '2010-05-05 00:00:00' COMMENT 'Modification time', PRIMARY KEY (`id`), UNIQUE KEY `uk_tenant_id` (`tenant_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Tenant capacity information table'; CREATE TABLE `tenant_info` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `kp` varchar(128) NOT NULL COMMENT 'kp', `tenant_id` varchar(128) default '' COMMENT 'tenant_id', `tenant_name` varchar(128) default '' COMMENT 'tenant_name', `tenant_desc` varchar(256) DEFAULT NULL COMMENT 'tenant_desc', `create_source` varchar(32) DEFAULT NULL COMMENT 'create_source', `gmt_create` bigint(20) NOT NULL COMMENT 'Creation time', `gmt_modified` bigint(20) NOT NULL COMMENT 'Modification time', PRIMARY KEY (`id`), UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`), KEY `idx_tenant_id` (`tenant_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='tenant_info'; CREATE TABLE users ( username varchar(50) NOT NULL PRIMARY KEY, password varchar(500) NOT NULL, enabled boolean NOT NULL ); CREATE TABLE roles ( username varchar(50) NOT NULL, role varchar(50) NOT NULL ); INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE); INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN');
Find application.properties in the directory of nacos-server-1.1.4\nacos\conf
It should be noted that the higher version of mysql may not match the lower version of nacos, and the corresponding version needs to be changed
spring.datasource.platform=mysql db.num=1 db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true db.user=root //Own database account db.password=123456 //Database password
Then restart the nacos command
startup.cmd -m standalone
Finally, we found that the changed configuration file can be stored in mysql
18.4.2 Nacos+MySQL production environment configuration for Linux
It is estimated that 1 Nginx+3 nacos registries + 1 mysql+jdk8
Download the linux version of nacos on the official website
https://github.com/alibaba/nacos/releases/tag/1.1.4
When configuring nacos, you need to ensure that the virtual machine has mysql version 5.6.5 or above
For mysql installation, please refer to the following articles
https://www.cnblogs.com/dingguofeng/p/13814645.html
Refer to the following article for jdk installation
https://blog.csdn.net/pdsu161530247/article/details/81582980
Create a mynacos folder in the root directory of linux and unzip the nacos files into this folder
Then open the mysql run sql script file
The file directory is as follows:
sql file directory
To prevent sql failure, you can add the following two sql sentences at the top of the sql file
create database `config_info`; use `config_info`;
Edit the / mynacos/nacos/conf/application.properties file
Add the following statement at the bottom
spring.datasource.platform=mysql db.num=1 db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true db.user=root db.password=123456
Build a nacos cluster
Enter the / mynacos/nacos/conf directory, create a cluster.conf file, and then add content
The content is that the previous ip is viewed with ip add on linux. The ip port number of ens33 network card is fixed
After completion
Edit the startup script startup.sh of Nacos so that it can accept different startup ports
/There is startup.sh in mynacos/nacos/bin directory. The modified contents are as follows:
After modification, start the nacoss cluster
./startup.sh -p 3333/4444/5555
If you encounter insufficient permissions, execute the following command
chmod +x /mynacos/nacos/bin/.
Then modify the configuration of nigex
Modify the nigex/config/nigex.config file
Amend as follows:
Start nigex
Then we test access to nacos through nginx on the machine
http://192.168.79.131:1111/nacos/#/login
Finally, register the service in the cluster
Modify yml configuration
19. Spring cloud Alibaba sentinel realizes fusing and current limiting
This component is somewhat similar to Hystrix
The download address here is version 1.7.0
https://github.com/alibaba/Sentinel/releases
Note that failure to start the package on the desktop will cause the service to fail
After installation and running, we can open the bin directory of nacos under the installation directory of nacos and execute it directly with cmd
19.1 realize service monitoring
Create module cloudalibaba-sentinel-service8401
pom
<dependencies> <!--SpringCloud ailibaba nacos --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!--SpringCloud ailibaba sentinel-datasource-nacos For subsequent persistence--> <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 integration Web assembly+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> <!--Daily general jar Package configuration--> <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>
yaml
server: port: 8401 spring: application: name: cloudalibaba-sentinel-service cloud: nacos: discovery: #Nacos service registry address server-addr: localhost:8848 sentinel: transport: #Configure Sentinel dashboard address dashboard: localhost:8080 #The default port is 8719. If it is occupied, it will automatically start + 1 scanning from 8719 until an unoccupied port is found port: 8719 management: endpoints: web: exposure: include: '*'
Main start
@EnableDiscoveryClient @SpringBootApplication public class MainApp8401 { public static void main(String[] args) { SpringApplication.run(MainApp8401.class, args); } }
controller
@RestController public class FlowLimitController { @GetMapping("/testA") public String testA() { return "------testA"; } @GetMapping("/testB") public String testB() { return "------testB"; } }
Then we start the microservice
However, it is found that sentinel does not have a lazy loading mechanism, so you need to visit it once to see it
19.2 realize flow control
The configuration options are shown below
19.2.1 the function configuration of flow control mode is described as follows:
19.2.1 the flow control effect is described as follows:
19.3 degradation rules
Official website
https://github.com/alibaba/Sentinel/wiki/%E7%86%94%E6%96%AD%E9%99%8D%E7%BA%A7
Sentinel will restrict the call of a resource in the call link when it is in an unstable state (for example, the call timeout or the abnormal proportion increases),
Make requests fail quickly to avoid cascading errors that affect other resources.
When a resource is downgraded, calls to the resource will be automatically fused within the next downgrade time window (the default behavior is to throw DegradeException).
Sentinel's circuit breaker is not half open
In the half open state, the system automatically detects whether the request is abnormal,
If there is no abnormality, close the circuit breaker and resume use,
If there is any abnormality, continue to open the circuit breaker and it is unavailable. Refer to Hystrix for details
19.3.1 RT degradation strategy
Downgrade according to the number of accesses. It should be noted that the condition for triggering the downgrade is that the number of threads > 5&& request time > 200ms will trigger the downgrade
19.3.2 abnormal proportion degradation
Refer to above
19.3.3 abnormal number degradation
19.4 current limiting
What are hot spots
What are hot spots
Hot spots are frequently accessed data. Many times, we want to count or limit the TopN data with the highest access frequency in a hot spot data, and limit its access or other operations
Official website description
https://github.com/alibaba/Sentinel/wiki/%E7%83%AD%E7%82%B9%E5%8F%82%E6%95%B0%E9%99%90%E6%B5%81
An annotation SentinelResource will be used
This annotation is similar to the annotation of HystrixCommand
It is mainly used to find out the details after a service error
Source code can refer to this class
com.alibaba.csp.sentinel.slots.block.BlockException
19.4.1 primary usage
How to conduct hot spot current limiting
It should be noted that we cannot limit the value attribute set in the SentinelResource annotation in the interface current limit
Then, when we access this point and bring the p1 parameter, if the current limit is exceeded, an error will be reported, and the method in the blockHandler attribute set in the SentinelResource annotation will be triggered. This method is the bottom method, but don't forget to add the parameter in this method
The parameter blockexception is not allowed, otherwise an error will be reported
19.4.1 advanced usage
What should we do when we want to not restrict the p1 parameter when it is a certain value?
19.5 system rules
Official website description
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
Simply put, there are system level restrictions
The main configurations are as follows:
19.6 @SentinelResource annotation
19.6.1 resource name limit
Introduce a package written before yourself on 8401
<dependencies> <!--SpringCloud ailibaba nacos --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency><!-- Introduce self defined api General package, you can use Payment payment Entity --> <groupId>com.atguigu.springcloud</groupId> <artifactId>cloud-api-commons</artifactId> </dependency> <!--SpringCloud ailibaba sentinel-datasource-nacos For subsequent persistence--> <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 integration Web assembly+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> <!--Daily general jar Package configuration--> <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>
Rewrite a controller class
@RestController public class RateLimitController { @GetMapping("/byResource") @SentinelResource(value = "byResource",blockHandler = "handleException") public CommonResult byResource() { return new CommonResult(200,"Current limit test by resource name OK",new Payment(2020L,"serial001")); } public CommonResult handleException(BlockException exception) { return new CommonResult(444,exception.getClass().getCanonicalName()+"\t Service Unavailable"); } }
Then start the service
We control the flow according to the resource name
The above configuration indicates that if the number of queries is greater than 1 in 1 second, it will run to our custom flow and limit the flow
The corresponding information is as follows:
But what's wrong with this usage
1. The system is default and does not reflect our own business requirements.
2 according to the existing conditions, our customized processing method is coupled with the business code, which is not intuitive.
3 each business method adds a bottom-up, which aggravates the code inflation.
4. The global unified processing method is not reflected.
19.6.2 customer defined current limiting processing logic
Create the com.atguigu.springcloud.myhandler.CustomerBlockHandler class to customize the flow limiting processing logic
public class CustomerBlockHandler{ //The return parameters should be consistent with the return parameters of the method being exposed, and there should be a BlockException class public static CommonResult handleException(BlockException exception){ return new CommonResult(2020,"Customized current limiting processing information......CustomerBlockHandler1"); } //The return parameters should be consistent with the return parameters of the method being exposed, and there should be a BlockException class public static CommonResult handleException1(BlockException exception){ return new CommonResult(2020,"Customized current limiting processing information......CustomerBlockHandler2"); } }
Then add notes on the methods that need to be explained
@GetMapping("/rateLimit/customerBlockHandler") //The value attribute represents an id represented on sentinel // blockHandlerClass represents the class with the bottom // blockHandler represents the method name of which method in the class @SentinelResource(value = "customerBlockHandler", blockHandlerClass = CustomerBlockHandler.class, blockHandler = "handleException1") public CommonResult customerBlockHandler() { return new CommonResult(200,"Custom current limiting processing logic by customer"); }
After limiting the current, if the operation such as degradation is triggered, it will be explained by the method we set ourselves
Further description of the configuration
19.6.3 more annotation attribute descriptions
The three pictures are the same
19.7 service fuse function
19.7.1 ribbon based
sentinel integration ribbon+openFeign+fallback
Create two new service providers cloudalibaba provider payment9003 / 9004. Do the same
pom
<dependencies> <!--SpringCloud ailibaba nacos --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency><!-- Introduce self defined api General package, you can use Payment payment Entity --> <groupId>com.atguigu.springcloud</groupId> <artifactId>cloud-api-commons</artifactId> <version>${project.version}</version> </dependency> <!-- SpringBoot integration Web assembly --> <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> <!--Daily general jar Package configuration--> <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>
yaml
server: port: 9004 spring: application: name: nacos-payment-provider cloud: nacos: discovery: server-addr: localhost:8848 #Configure Nacos address management: endpoints: web: exposure: include: '*'
The @ EnableDiscoveryClient annotation is required for main startup
@SpringBootApplication @EnableDiscoveryClient public class PaymentMain9004 { public static void main(String[] args) { SpringApplication.run(PaymentMain9004.class, args); } }
Simple business class
@RestController public class PaymentController{ @Value("${server.port}") private String serverPort; public static HashMap<Long,Payment> 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<Payment> paymentSQL(@PathVariable("id") Long id) { Payment payment = hashMap.get(id); CommonResult<Payment> result = new CommonResult(200,"from mysql,serverPort: "+serverPort,payment); return result; } }
Finally, we start this class to test the test address http://localhost:9004/paymentSQL/1
Then create a consumer cloudalibaba-consumer-nacos-order84
pom
<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> <!-- Introduce self defined api General package, you can use Payment payment Entity --> <dependency> <groupId>com.atguigu.springcloud</groupId> <artifactId>cloud-api-commons</artifactId> <version>${project.version}</version> </dependency> <!-- SpringBoot integration Web assembly --> <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> <!--Daily general jar Package configuration--> <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>
yaml
server: port: 84 spring: application: name: nacos-order-consumer cloud: nacos: discovery: server-addr: localhost:8848 sentinel: transport: #Configure Sentinel dashboard address dashboard: localhost:8080 #The default port is 8719. If it is occupied, it will automatically start + 1 scanning from 8719 until an unoccupied port is found port: 8719 #The name of the microservice that the consumer will access (the microservice provider successfully registered in nacos) service-url: nacos-user-service: http://nacos-payment-provider
Main start
@EnableDiscoveryClient @SpringBootApplication public class OrderNacosMain84 { public static void main(String[] args) { SpringApplication.run(OrderNacosMain84.class, args); } }
Business class
@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", fallback = "handlerFallback", //Method with runtime exception blockHandler = "blockHandler") //Method of service degradation or fusing 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 ("Illegal parameter exception...."); }else if (result.getData() == null) { throw new NullPointerException ("NullPointerException,Should ID No corresponding record"); } return result; } public CommonResult handlerFallback(@PathVariable Long id,Throwable e) { Payment payment = new Payment(id,"null"); return new CommonResult<>(444,"fallback,No such flow,exception "+e.getMessage(),payment); } public CommonResult blockHandler(@PathVariable Long id, BlockException blockException) { Payment payment = new Payment(id,"null"); return new CommonResult<>(445,"blockHandler-sentinel Current limiting,No such flow: blockException "+blockException.getMessage(),payment); } }
robbin is used here, so the RestTemplate instance is used
@Configuration public class ApplicationContextConfig{ @Bean @LoadBalanced public RestTemplate getRestTemplate() { return new RestTemplate(); } }
The policy of fusing mainly depends on the SentinelResource annotation on the main startup class
@SentinelResource(value = "fallback", fallback = "handlerFallback", //Method with runtime exception blockHandler = "blockHandler") //Method of service degradation or fusing
19.7.1 based on feign
Modify the cloudalibaba consumer Nacos order84 module
Add feign's file
<!--SpringCloud openfeign --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
Set exposure monitoring in yaml and open sentinel support for feign
management: endpoints: web: exposure: include: '*' # Activate Sentinel support for Feign feign: sentinel: enabled: true
Write an interface to call feign
@FeignClient(value = "nacos-payment-provider",fallback = PaymentFallbackService.class)//Close 9003 service provider in call public interface PaymentService { @GetMapping(value = "/paymentSQL/{id}") public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id); }
His method:
@Component public class PaymentFallbackService implements PaymentService { @Override public CommonResult<Payment> paymentSQL(Long id) { return new CommonResult<>(444,"Service degradation return,There is no such flow information",new Payment(id, "errorSerial......")); } }
Add a piece of code to the controller
//==================OpenFeign @Resource private PaymentService paymentService; @GetMapping(value = "/consumer/openfeign/{id}") public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id) { if(id == 4) { throw new RuntimeException("No this id"); } return paymentService.paymentSQL(id); }
Finally, don't forget to add the @ EnableFeignClients annotation on the main startup class to enable feign support
Call service through controller
Test address: http://localhost:84/consumer/paymentSQL/1
If we deliberately make feign make an error in the call, he will return the method with the bottom
19.8 rule persistence
We persist the rules to nacos
Persist the flow restriction configuration rules into Nacos and save them. Just refresh 8401 a rest address and the sentinel console
You can see that as long as the configuration in Nacos is not deleted, the flow control rules on sentinel on 8401 remain valid
First, add the dependency that supports persistence to the pom file on the module that needs persistence
<!--SpringCloud ailibaba sentinel-datasource-nacos --> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> </dependency>
Then add the configuration in yaml
spring: cloud: sentinel: datasource: ds1: nacos: server-addr: localhost:8848 #Address of nacos dataId: ${spring.application.name} #Own service name groupId: DEFAULT_GROUP #Which group does it belong to data-type: json #Saved format rule-type: flow
Finally, you need to create a new configuration file in nacos, so that you can go back and read it every time sentinel starts
It should be noted that the file name and grouping must comply with the rules configured in yaml
So what does this json file mean? Refer to the following picture
When we shut down and restart the service, this rule will still exist in sentinel