Nacos
1.1 nacos-sever
1.1.1 下载安装
https://github.com/alibaba/nacos/releases
1.1.2 部署
解压后启动:
sh bin/startup.sh -m standalone
-m standalone
表示单机启动。
部署后访问
localhost:8848/nacos
可访问nacos控制台,然后以nacos/nacos(用户名/密码)登录。
停止nacos-server使用如下命令:
sh bin/shutdown.sh
1.1.3 数据持久化
nacos-sever默认使用的是derby数据库来保存数据的,derby是一个基于内存的数据库,所以在服务重新启动后,derby中保存的数据就会丢失。
在Nacos控制台
命名空间
菜单项中新建一个命名空间。然后重新启动,会发现新建的命名空间不见了。
- 本地数据库
准备本地数据库,在数据库中执行nacos-server中
./conf/nacos-mysql.sql
,准备表数据。
- 配置Mysql连接信息
修改nacos-server 项目中的
./conf/application.properties
数据库相关配置:
### If use MySQL as datasource:
spring.datasource.platform=mysql
### Count of DB:
db.num=1
### Connect URL of DB:
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user.0=root
db.password.0=1234
- 重启server
> sh ./bin/shutdown.sh
The nacosServer(52861) is running...
Send shutdown request to nacosServer(52861) OK
> ./bin/startup.sh -m standalone
在Nacos控制台
命名空间
菜单项中新建一个命名空间。然后重新启动,会发现新建的命名空间还在,说明持久化配置成功。
1.1.4 集群配置
- 环境准备
将nacos-server复制出来3个,修改这3个nacos-server中
conf/application.properties
中的端口号及数据库配置。这三个nacos-server的端口分别为8848,8849,8850。
- 集群配置
分别将naocs-server下的cluster.conf.example复制为cluster.conf,并在末尾修改或添加如下配置:
192.168.0.125:8848
192.168.0.125:8849
192.168.0.125:8850
- 启动
分别在三个nacos-server下执行下面的命令启动:
sh bin/startup.sh
三个nacos-server启动后,访问127.0.0.1:8848/nacos, 127.0.0.1:8849/nacos, 127.0.0.1:8850/nacos可以访问对应的nacos-server。
在nacos-server控制台的
集群管理->节点列表
中可以看到三个server服务节点。
1.2 nacos-client
1.2.1 注册中心
准备
在Nacos控制台中
命名空间
菜单添加一个一个新的命名空间
Test
(命名空间ID项要为Test,与后面演示一致)。
父工程依赖
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- Spring Boot -->
<parent>
<artifactId>spring-boot-starter-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.6.3</version>
</parent>
<groupId>org.example</groupId>
<artifactId>nacos</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>nacos-client01</module>
</modules>
<packaging>pom</packaging>
<!-- Spring Cloud 及 Spring cloud alibaba 依赖管理 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2021.0.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2021.0.1.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
本工程
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>nacos</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>nacos-client01</artifactId>
<dependencies>
<!-- Spring Cloud 项目加载 bootstrap.yml 文件 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<!-- Nacos discover client -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
启动类
NacosClientApp.java
@SpringBootApplication
@EnableDiscoveryClient
public class NacosClientApp {
public static void main(String[] args) {
SpringApplication.run(NacosClientApp.class, args);
}
}
配置
bootstrap.yml
server:
port: 9000
spring:
application:
name: nacos-client
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: Test # 默认为Public
group: TEST_GROUP # 默认为DEFAULT_GROUP
以上信息配置完成后,启动项目,观察nacos控制台
服务管理->服务列表->Test
中有当前服务。
服务名 | 分组名称 | 集群数目 | 实例数 | 健康实例数 | 触发保护阈值 | 操作 |
---|---|---|---|---|---|---|
nacos-client | TEST_GROUP | 1 | 1 | 1 | false | 详情\示例代码\订阅者\ 删除 |
添加接口
NacosProviderController.java
@RestController
@RequestMapping("/provider")
public class NacosProviderController {
@Value("${server.port}")
private Integer port;
@GetMapping("/port")
public Integer port() {
return port;
}
@GetMapping("/info")
public String info() {
return "Nacos provider info";
}
}
重启服务,使接口生效。
1.2.2 服务消费
添加新的服务,作为消费方消费上面
nacos-client
提供的服务。
添加依赖
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>nacos</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>nacos-consumer01</artifactId>
<dependencies>
<!-- 加载 bootstrap.yml -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<!-- Nacos Discovery -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- loadbalancer -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<!-- Web模块 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
配置
bootstrap.yml
server:
port: 9010
spring:
application:
name: nacos-client-consumer01
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: Test
group: TEST_GROUP
启动类
NacosConsumerApp.java
@SpringBootApplication
@EnableDiscoveryClient
// 开启Feign支持
@EnableFeignClients
public class NacosConsumerApp {
public static void main(String[] args) {
SpringApplication.run(NacosConsumerApp.class, args);
}
}
Feign Client
NacosProviderClient.java
@FeignClient("nacos-client")
public interface NacosProviderClient {
@GetMapping("/provider/port")
Integer port();
@GetMapping("/provider/info")
String info();
}
请求接口
NacosConsumerController.java
@RestController
@RequestMapping("/consumer")
public class NacosConsumerController {
@Resource
private NacosProviderClient nacosProviderClient;
@GetMapping("/provider/port")
public Integer providerPort() {
return nacosProviderClient.port();
}
@GetMapping("/provider/info")
public String providerInfo() {
return nacosProviderClient.info();
}
}
启动项目访问接口,可正常访问到
nacos-client
服务。
1.2.2 配置中心
注册中心采用父工程+子模块的方式演示,为了能理清晰的知道导入的依赖的作用,该项目为单模块项目演示。
添加依赖
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>spring-boot-starter-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.6.3</version>
<relativePath/>
</parent>
<groupId>org.example</groupId>
<artifactId>nacos-config-client</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2021.0.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2021.0.1.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
启动类
NacosConfigClientApp.java
@SpringBootApplication
public class NacosConfigClientApp {
public static void main(String[] args) {
SpringApplication.run(NacosConfigClientApp.class, args);
}
}
配置
bootstrap.yml
基本配置
server:
port: 9003
spring:
profiles:
active: dev
application:
name: nacos-config-client
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
# 命名空间
namespace: Test
# 分组
group: TEST_GROUP
# 文件后缀
file-extension: yml
对于以上配置,需要在Nacos控制台对应的namespace下新建一个配置文件,文件分组要为
TEST_GROUP
。
配置文件命名组成:
${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
进入Nacos控制台在
Test
命名空间下添加配置。 Data Id: nacos-config-client-dev.yml Group: TEST_GROUP 配置格式: yaml 配置内容:
server:
port: 10003
配置好后启动项目。 控制台可以看到类似如下日志输出:
Ignore the empty nacos configuration and get it based on dataId[nacos-config-client] & group[TEST_GROUP]
Ignore the empty nacos configuration and get it based on dataId[nacos-config-client.yml] & group[TEST_GROUP]
.......
listening config: dataId=nacos-config-client-dev.yml, group=TEST_GROUP
listening config: dataId=nacos-config-client.yml, group=TEST_GROUP
listening config: dataId=nacos-config-client, group=TEST_GROUP
项目最终在10003端口(Nacos中配置)启动。
如果项目启动不是10003端口,而是本地配置文件中的端口,检查Nacos中的配置文件是否配置正确,如命名空间、分组配置。
配置动态刷新
- 添加配置 修改Nacos中配置文件中的配置,并发布:
server:
port: 10003
info: Nacos config test
- 读取配置 编写AutoRefreshController.java读取配置:
@RefreshScope // 刷新配置
@RestController
@RequestMapping("/config")
public class AutoRefreshController {
@Value("${info}")
private String info;
@GetMapping("/info")
public String configInfo() {
return info;
}
}
启动项目,访问
/config/info
,可以看到接口返回配置文件中配置的内容。更改Nacos中的配置,再次访问接口查看响应数据也跟着发生变化。
@RefreshScope
多配置文件(扩展多个配置)
- 配置文件
通过
extension-configs
添加多个配置文件:
server:
port: 9003
spring:
profiles:
active: dev
application:
name: nacos-config-client
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
namespace: Test
group: TEST_GROUP
file-extension: yml
# 添加扩展配置
extension-configs:
- dataId: datasource.yml
group: DATASOURCE_GROUP
# 是否自动刷新
refresh: true
- dataId: redis.yml
group: CACHE_GROUP
refresh: false
- Nacos控制台添加配置
Data Id: datasource.yml
Group: DATASOURCE_GROUP
内容:
datasource:
platform: mysql
Data Id: redis.yml
Group: CACHE_GROUP
内容:
redis:
host: 127.0.0.1
- 新增接口访问配置
@RefreshScope
@RestController
@RequestMapping("/config")
public class ConfigController {
@Value("${datasource.platform}")
private String datasourcePlatform;
@Value("${redis.host}")
private String redisHost;
@GetMapping("/datasource/platform")
public String datasourcePlatform() {
return datasourcePlatform;
}
@GetMapping("/redis/host")
public String redisHost() {
return redisHost;
}
}
启动项目,访问新增的两个接口,接口将响应新增的配置文件中对应的内容。(如果项目启动报错@Value加载不到配置,需要检查配置文件是否正确)。
- 测试动态刷新
确保接口开启了自动刷新,
@RefreshScope
。由于配置文件datasource.yml开启了refresh,而redis.yml没有开启refresh,所以在nacos修改redis.yml的内容时,接口无法动态获取并刷新。
1.2.3 配置中心、服务发现及集群配置
依赖
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.3</version>
<relativePath/>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
<artifactId>nacos-client-cluster</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2021.0.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2021.0.1.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
启动类
NacosClientClusterApp.java
@SpringBootApplication
@EnableDiscoveryClient
public class NacosClientClusterApp {
public static void main(String[] args) {
SpringApplication.run(NacosClientClusterApp.class, args);
}
}
配置
bootstrap.yml
server:
port: 9004
spring:
application:
name: nacos-client-cluster
cloud:
nacos:
server-addr: 192.168.0.125:8848,192.168.0.125:8849,192.168.0.125:8850
discovery:
namespace: Test
group: TEST_GROUP
config:
namespace: Test
group: TEST_GROUP
file-extension: yml
Nacos-server中添加配置文件
Data ID: nacos-client-cluster.yml
Group: TEST_GROUP
配置格式: YAML
配置内容:
info: nacos client cluster info
添加接口
ClientInfoController.java
@RestController
public class ClientInfoController {
@Value("${info}")
private String info;
@Value("${server.port}")
private Integer port;
@GetMapping("/info")
public String info() {
return info;
}
@GetMapping("/port")
public Integer port() {
return port;
}
}
打成可执行jar包
要把项目打包成一个可执行jar包,在pom.xml添加如下配置:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
在项目根目录执行:
mvn package
执行完成后在 **项目根目录/target/**会生成nacos-client-cluster-1.0-SNAPSHOT.jar。
运行jar
执行下面命令运行jar包,使用多个服务构成集群
java -jar nacos-client-cluster-1.0-SNAPSHOT.jar --server.port=9004
java -jar nacos-client-cluster-1.0-SNAPSHOT.jar --server.port=9005
java -jar nacos-client-cluster-1.0-SNAPSHOT.jar --server.port=9006
分别启动项目后,在nacos控制台
服务管理->服务列表
能看到服务nacos-client-cluster有三个实例。
2 Sentinel
高并发大流量导致系统服务不可用。Sentinel应对这些场景常见策略有服务降级、熔断、限流。
2.1 常见的限流算法
2.1.1 计数器算法
设定某个时间内接口访问频次,如1s访问某接口100次,访问达到100次后限制访问,进入下一秒时,计数器清零。但是处在临界值时,访问次数会变成2倍。如在临界值前0.5秒到1.5秒分别有访问了100次,那么这一秒内就连续访问了200次。
2.1.2 滑动窗口算法
2.1.3 令牌桶算法
固定大小的令牌桶,以一定的速率生成令牌(如果令牌桶满,生成的令牌丢弃)。每次接口访问前从桶中获取令牌,拥有令牌的请求才能继续访问。如果访问速率大于令牌生成速率,令牌桶中的令牌很快就被取完了,一些请求拿不到令牌就会触发限流。
2.1.4 漏桶限流算法
有一个以恒定速率出水的漏桶,每次能漏出的水是恒定的,如果进水速率大于出水速率漏桶很快就被填满,然后触发限流。
2.2
2.2.1 sentinel-server
下载
https://github.com/alibaba/Sentinel/releases
安装
将下载的jar包运行,服务默认在8080端口启动。
java -jar sentinel-dashboard-1.8.4.jar
访问 127.0.0.1:8080 ,然后以 sentinel/sentinel(用户名/密码)登录。
2.2.2 sentinel-client
添加依赖
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>spring-boot-starter-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.6.3</version>
</parent>
<groupId>org.example</groupId>
<artifactId>sentinel</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2021.0.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2021.0.1.0</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
启动类
SentinelApp.java
@SpringBootApplication
public class SentinelApp {
public static void main(String[] args) {
SpringApplication.run(SentinelApp.class, args);
}
}
配置文件
server:
port: 9010
spring:
application:
name: sentinel-client
cloud:
sentinel:
transport:
# IP 访问
dashboard: 127.0.0.1:8080
添加接口
SentinelController.java
@RestController
public class SentinelController {
@Value("${server.port}")
private Integer port;
@GetMapping("/port")
public Integer getPort() {
return port;
}
}
完成上述步骤后,启动项目并访问
/port
接口,然后在sentinel控制台可以看到当前服务的实例。
在
实时监控
菜单中可以看到接口访问信息,如QPS、响应时间等。
在
簇点链路
菜单中可以看到请求路径,并且可以配置流控、熔断等限制。
2.2.3 限流
限流配置
在Sentinel的
触点链路
菜单中对接口
/port
选择
流控
设置,并将单机阈值选项改为3。然后访问该接口,如果每秒钟访问该接口的频次大于3次,触发限流。
Blocked by Sentinel (flow limiting)
自定义限流异常
@Service
public class CustomBlockException implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {
httpServletResponse.setContentType("application/json;charset=UTF-8");
httpServletResponse.getWriter().write("{\"message\": \"访问频繁\"}");
}
}