The fourth day of spring cloud learning is the Silicon Valley version

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

Tags: Java Spring Cloud Microservices

Posted on Thu, 11 Nov 2021 04:06:12 -0500 by SpanKie