目录
下一篇:微服务三、SpringCloudAlibaba(2021版本) Seata分布式事务、RocketMQ分布式消息
上一篇:
微服务一、SpringCloudAlibaba(2021版本)+Nacos-从零开始、安装、配置、使用和父子项目搭建
本篇内容是接着上一篇的,本篇主要内容:
Sentinel 流量安全控制
、
OpenFeign 负载均衡
、
Gateway网关路由和动态路由
、
sentinel结合Nacos持久化配置、Nacos持久化
继续集成-Sentinel 流量安全控制
github spring-cloud-alibaba Sentinel文档
Alibaba Sentinel 是一款高性能且轻量级的流量控制、熔断降级解决方案。是面向分布式服务架构的高可用流量控制组件。分为两个部分:
- 核心库(Java 客户端)不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。
- 控制台(Dashboard)基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器。
接入Sentinel 控制台
从
release 页面
下载最新版本的控制台 jar 包。
启动命令如下,本文使用的是目前最新 1.8.1 版本:
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.1.jar
访问:
http://localhost:8080/
输入默认账号密码sentinel
两个子工程pom增加
<!-- spring cloud alibaba sentinel 依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
两个子工程yml增加
spring:
cloud:
sentinel:
transport:
port: 8719
dashboard: localhost:8080
# feign 开启 sentinel 支持
feign:
sentinel:
enabled: true
sentinel.transport.port 端口配置会在应用对应的机器上启动一个 Http Server,与 Sentinel 控制台做交互。比如 Sentinel 控制台添加了一个限流规则,会把规则数据 push 给这个 Http Server 接收,Http Server 再将规则注册到 Sentinel 中。确保客户端有访问量,Sentinel 会在客户端首次调用的时候进行初始化,开始向控制台发送心跳包。
即:访问一次客户端,Sentinel 即可完成客户端初始化操作
老规矩,启动项目,多访问几次:
http://localhost:8081/test
定义资源
资源 是 Sentinel 中的核心概念之一。可以是任何东西,服务,服务里的方法,甚至是一段代码。最常用的资源是我们代码中的 Java 方法。Sentinel 提供了 @SentinelResource 注解用于定义资源,并提供了 AspectJ 的扩展用于自动定义资源、处理 BlockException 等。
只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源。
注解(注解方式埋点不支持 private 方法)
文档
Sentinel 集成 openfeign遇到的问题
该版本的说明实在太少,最终也没在网上找到对应的问题和解决方法,倔强的我也不愿意自降版本,所以,断断续续的尝试了好一段时间,这里记录下我最终的解决方案
项目启动找不到
@FeignClient
注解标注的类
因为开启feign对sentinel的支持 feign.sentinel.enabled: true 项目启动报错,找不到
@FeignClient
注解标注的类,最后在启动类@EnableFeignClients注解加上扫描制定包@EnableFeignClients(basePackages = “com.demo.rpc.*”),启动成功但是又出现了下面得错误
远程调用不生效一直进入fallback
可能版本得原因吧最后删掉了上方配置和feign.sentinel.enabled: true,远程调用生效,但是这时又发现了以下问题
生产者关闭fallback不生效
最后查看feign的属性时发现了circuitbreaker,描述是:If true, an OpenFeign client will be wrapped with a Spring Cloud CircuitBreaker circuit breaker. (如果为true,OpenFeign客户端将被一个Spring云断路器包装。)加上后成功解决!
feign:
circuitbreaker:
enabled: true
后面继续。
重新贴下整理后的各文件配置
父pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.7</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.demo</groupId>
<artifactId>cloud-nacos-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>cloud-nacos-demo</name>
<description>Demo project for Spring Cloud Nacos</description>
<packaging>pom</packaging>
<modules>
<!--
<module>cloud-nacos-common-entity</module>
<module>cloud-nacos-common-redis</module>
<module>cloud-nacos-common-utils</module>
-->
<module>cloud-nacos-console-center</module>
<module>cloud-nacos-customer-center</module>
</modules>
<properties>
<java.version>1.8</java.version>
<spring-boot.version>2.4.7</spring-boot.version>
<spring-cloud.version>2020.0.0</spring-cloud.version>
<spring-cloud-alibaba.version>2021.1</spring-cloud-alibaba.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- spring boot 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- SpringCloud 微服务 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- SpringCloud Alibaba 微服务 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- bootstrap 启动器 使bootstrap配置文件生效 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
</dependencies>
</project>
子pom依赖
<!--lombok依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- SpringCloud Alibaba Nacos 注册中心 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringCloud Alibaba Nacos Config配置中心 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- 远程调用 SpringCloud Openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<!-- SpringCloud Alibaba Sentinel 熔断降级,外部降级 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
yml
删除了application.yml使用bootstrap.yml文件
# Tomcat
server:
port: 8081
# Spring
spring:
application:
name: customer-center
profiles:
active: dev
cloud:
nacos:
discovery:
server-addr: localhost:8848
group: DEV_GROUP
#namespace: xxx-xxx-xxx
#service: ${spring.application.name}
#register-enabled: true # 是否开启注册服务(默认true)
config:
# 配置中心地址
server-addr: localhost:8848
prefix: config # 默认为 spring.application.name 的值
# 配置文件格式
file-extension: yml
#namespace: xxx-xxx-xxx
#refresh-enabled: true # 是否开启动态刷新(默认true)
# 共享配置
# shared-configs:
# - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
sentinel:
# 取消控制台懒加载
eager: true
transport:
port: 8719 # 在应用对应的机器上启动一个 Http Server,与 Sentinel 控制台做交互
dashboard: localhost:8080 # 控制台地址
feign:
circuitbreaker:
# If true, an OpenFeign client will be wrapped with a Spring Cloud CircuitBreaker circuit breaker.
enabled: true
启动类
package com.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients // 开启feign远程调用
@EnableDiscoveryClient // 开启nacos
public class CloudNacosCustomerCenterApplication {
public static void main(String[] args) {
SpringApplication.run(CloudNacosCustomerCenterApplication.class, args);
}
}
Sentinel + openfeign熔断降级
console-center
TestController
package com.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@GetMapping("/test")
public String test() {
return "我是来自console-center得数据";
}
}
修改
customer-center
UserController
package com.demo.controller;
import com.demo.config.ConfigProperties;
import com.demo.rpc.ConsoleApiService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
public class UserController {
@Resource
ConfigProperties properties;
@Resource
private ConsoleApiService consoleApiService;
@GetMapping("/user")
public String getUser() {
return "customer-center发起请求,请求内容:" + consoleApiService.test();
}
}
ConsoleApiService
使用FallbackFactory 可以记录异常
package com.demo.rpc;
import com.demo.rpc.impl.ConsoleApiServiceFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
// value 代表要调用的服务
// 设置configuration属性为 feign的配置 比如日志记录
// fallback 消费端 降级方案
@FeignClient(value = "console-center", fallbackFactory = ConsoleApiServiceFallbackFactory.class)
public interface ConsoleApiService {
@GetMapping("/test")
String test();
}
ConsoleApiServiceFallbackFactory
服务熔断降级处理,可返回托底数据,
package com.demo.rpc.impl;
import com.demo.rpc.ConsoleApiService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class ConsoleApiServiceFallbackFactory implements FallbackFactory<ConsoleApiService> {
@Override
public ConsoleApiService create(Throwable cause) {
return new ConsoleApiService() {
@Override
public String test() {
log.error("test fail :remote call console-center test method fail, 原因:");
cause.printStackTrace();
return null;
}
};
}
}
目录
启动项目,多请求几次
http://localhost:8081/user
添加
流控
规则,(默认效果
快速失败
)定义资源访问的 QPS 为 1(每秒能处理查询数目)。
请求远程服务调用
http://localhost:8081/user
,对比单次和快速刷新效果
请求
http://localhost:8082/test
,对比单次和快速刷新效果
OpenFeign (服务调用与客户端负载均衡)
开发微服务,免不了需要服务间调用,服务间调用和调用失败的熔断降级在上文已经配置过了,这里实践下客户端的负载均衡
创建子工程
cloud-nacos-console-center2
(上文已有,此处略过)
将
cloud-nacos-console-center的内容复制到cloud-nacos-console-center2
修改TestController
(为了区分)
package com.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@GetMapping("/test")
public String test() {
// int a = 1 / 0;
return "我是来自console-center2得数据";
}
}
修改bootstrap.yml
文件
server.port: 8083
启动项目
测试负载
多次请求
http://localhost:8081/user
console-center2和console-center轮询调用,几率平均!
负载均衡策略
1、轮循
ReactiveLoadBalancer
默认使用的实现是
RoundRobinLoadBalancer
轮循,上文配置的测试的负载方式就是轮询
打开nacos管理后台,选择服务实例编辑权重,取值在0~1之间,值越大代表实例被调用的几率越大,权重改为0不会调用
console-center2的权重更改
实测发现除了改为0,其他的任何值都默认为轮询,查了下资料说是spring cloud-ribbon默认是没有权重的轮询算法的. 另外这个nacos的权重属性不一定在springcloud 有用到, 可以使用元信息配置的权重+自定义ribbon策略
2、随机负载
官方切换成
随机负载
均衡示例
package com.demo.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.loadbalancer.core.RandomLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;
@Slf4j
public class NacosWeightRule {
/**
* 切换为随机负载均衡(官方写法)
*/
@Bean
ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
LoadBalancerClientFactory loadBalancerClientFactory) {
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
return new RandomLoadBalancer(loadBalancerClientFactory
.getLazyProvider(name, ServiceInstanceListSupplier.class),
name);
}
}
作为@LoadBalancerClient或@LoadBalancerClient配置参数传递的类,不应使用@configuration进行注释,也不应在组件扫描范围之外,启动类添加
@LoadBalancerClients(defaultConfiguration = {NacosWeightRule.class})
再次测试,两个服务调用概率确实改为了随机
nacos控制台上下线失效
而上下线功能也是,虽然
nacos
实现了秒级的实例上下线,但是由于在
Spring Cloud
中,负载组件
rabbion
的实例信息更新是采用了定时任务的形式,有可能这个任务上一秒刚刚执行完,下一秒你就执行实例上下线操作,那么
rabbion
要感知这个变化,就必须要等待
refreshIntervalMs
秒后才可以感知到。
解决:
默认
ttl
设置为 35 秒, 可以设置spring.cloud.loadbalancer.cache.enabled: false禁用缓存或者更改
ttl
的值spring: application: name: customer-center profiles: active: dev cloud: loadbalancer: cache: # enabled: false ttl: 2s
Gateway(网关)
API网关的作用
- API网关可以把后端的多个服务进行整合,提供唯一的业务接口(请求转发),客户端只需要调用这个接口即可完成数据获取与展示。
- 针对所有的请求进行统一鉴权,限流,熔断,日志。
- 协议转化。针对后端不同的协议,在网关层统一处理后以http对外提供服务。
- 统一错误码处理
- 请求转发,并且可以基于网关实现内、外网隔离。
网关路由
创建子模块cloud-nacos-gateway
经历了一天的各种问题后终于尝试成功了(如何创建子模块可参考前面的创建父子项目)
pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.demo</groupId>
<artifactId>cloud-nacos-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.demo</groupId>
<artifactId>cloud-nacos-gateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>cloud-nacos-gateway</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- SpringCloud Alibaba Nacos 注册中心 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringCloud Alibaba Nacos Config配置中心 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- SpringCloud Alibaba Sentinel 熔断降级,外部降级 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- 远程调用 SpringCloud Openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<!-- SpringCloud Alibaba Sentinel Gateway 网关 和 Sentinel Starter 配合使用 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
<!-- SpringCloud Gateway -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- 单独使用 -->
<!-- sentinel gateway adapter 依赖 -->
<!--<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
</dependency>-->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
bootstrap.yml
# Tomcat
server:
port: 10000
# Spring
spring:
application:
name: gateway-center
profiles:
active: dev
cloud:
nacos:
discovery:
server-addr: localhost:8848
group: DEV_GROUP
config:
# 配置中心地址
server-addr: localhost:8848
prefix: config # 默认为 spring.application.name 的值
# 配置文件格式
file-extension: yml
# 网关配置
gateway:
discovery:
locator:
# 开启从注册中心动态创建路由的功能,利用微服务名进行路由
enabled: true
routes:
- id: customer-center # 路由 ID,唯一 没有固定规则,建议配合服务名
# 支持普通url和lb://注册中心服务名称
uri: lb://customer-center
predicates: # 路由条件,根据匹配结果进行路由
- Path=/customer/** # 路径相匹配的进行路由,会添加到uri后
#- After=2020-02-21T15:51:37.485+08:00[Asia/Shanghai]
#- Cookie=username,yys
#- Header=X-Request-Id, \d+ # 请求头要有X-Request-Id属性并且值为整数的正则表达式
filters:
# 自动去掉一节路径, 转发到uri后自动去掉customer, 1代表截取路径的个数
- StripPrefix=1
- id: console-center
uri: lb://console-center
predicates:
- Path=/console/**
filters:
- StripPrefix=1
启动类注解
@SpringBootApplication
@EnableDiscoveryClient
启动项目
如报错:Consider defining a bean of type ‘org.springframework.http.codec.ServerCodecConfigurer’ in your configuration.
要排除依赖spring-boot-starter-web,因为会与spring cloud gateway的webflux冲突。
网关路由测试
访问
http://localhost:10000/customer/user
访问
http://localhost:10000/console/test
动态路由
Spring Cloud Gateway本身不支持直接从Nacos动态加载路由配置表,需要自己编写监听器监听配置变化并刷新路由表。
项目修改
package com.demo.config;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
@Component
public class NacosDynamicRouteService implements ApplicationEventPublisherAware {
//设置路由配置的Nacos dataid
private String dataId = "gateway.properties";
//设置路由配置的nacos group
@Value("${spring.cloud.nacos.config.group:DEFAULT_GROUP}")
private String group;
//Nacos 配置中心地址
@Value("${spring.cloud.nacos.config.server-addr}")
private String serverAddr;
@Autowired
private RouteDefinitionWriter routeDefinitionWriter;
private ApplicationEventPublisher applicationEventPublisher;
private static final List<String> ROUTE_LIST = new ArrayList<>();
@PostConstruct //服务器加载Servlet的时候运行,并且只会被服务器执行一次
public void dynamicRouteByNacosListener() {
try {
//创建nacos服务
ConfigService configService = NacosFactory.createConfigService(serverAddr);
//根据条件获取nacos配置
configService.getConfig(dataId, group, 5000);
//为nacos配置添加监听
configService.addListener(dataId, group, new Listener() {
@Override
public void receiveConfigInfo(String configInfo) {
//清空路由信息
clearRoute();
try {
//路由信息JSON转为RouteDefinition对象
List<RouteDefinition> gatewayRouteDefinitions = JSONObject.parseArray(configInfo, RouteDefinition.class);
//添加路由信息
for (RouteDefinition routeDefinition : gatewayRouteDefinitions) {
addRoute(routeDefinition);
}
//推送路由信息
publish();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public Executor getExecutor() {
return null;
}
});
} catch (NacosException e) {
e.printStackTrace();
}
}
private void clearRoute() {
for(String id : ROUTE_LIST) {
this.routeDefinitionWriter.delete(Mono.just(id)).subscribe();
}
ROUTE_LIST.clear();
}
private void addRoute(RouteDefinition definition) {
try {
routeDefinitionWriter.save(Mono.just(definition)).subscribe();
ROUTE_LIST.add(definition.getId());
} catch (Exception e) {
e.printStackTrace();
}
}
private void publish() {
this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this.routeDefinitionWriter));
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
}
删除路由信息
# Tomcat
server:
port: 10000
# Spring
spring:
application:
name: gateway-center
profiles:
active: dev
cloud:
nacos:
discovery:
server-addr: localhost:8848
group: DEV_GROUP
config:
# 配置中心地址
server-addr: localhost:8848
prefix: config # 默认为 spring.application.name 的值
# 配置文件格式
file-extension: yml
# 网关配置
gateway:
discovery:
locator:
# 开启从注册中心动态创建路由的功能,利用微服务名进行路由
enabled: true
routes:
# - id: customer-center # 路由 ID,唯一 没有固定规则,建议配合服务名
# # 支持普通url和lb://注册中心服务名称
# uri: lb://customer-center
# predicates: # 路由条件,根据匹配结果进行路由
# - Path=/customer/** # 路径相匹配的进行路由,会添加到uri后
# #- After=2020-02-21T15:51:37.485+08:00[Asia/Shanghai]
# #- Cookie=username,yys
# #- Header=X-Request-Id, \d+ # 请求头要有X-Request-Id属性并且值为整数的正则表达式
# filters:
# # 自动去掉一节路径, 转发到uri后自动去掉customer
# - StripPrefix=1
# - id: console-center
# uri: lb://console-center
# predicates:
# - Path=/console/**
# filters:
# - StripPrefix=1
nacos控制台动态路由配置
[
{
"id":"customer-center",
"order": 0,
"uri":"lb://customer-center",
"predicates":[
{
"name":"Path",
"args":{
"pattern":"/customer/**"
}
}
],
"filters":[
{
"name":"StripPrefix",
"args": {
"parts": "1"
}
}
]
},
{
"id":"console-center",
"order": 0,
"uri":"lb://console-center",
"predicates":[
{
"name":"Path",
"args":{
"pattern":"/console/**"
}
}
],
"filters":[
{
"name":"StripPrefix",
"args": {
"parts": "1"
}
}
]
}
]
Filter
- StripPrefix Filter 请求路径截取的功能(截掉前面的)
- PrefixPath Filter 的作用和 StripPrefix 正相反,是在 URL 路径前面添加一部分的前缀
动态路由测试
nacos配置前访问不到,配置后访问正常
下一篇:微服务三、SpringCloudAlibaba(2021版本) Seata分布式事务、RocketMQ分布式消息
微服务三、SpringCloudAlibaba(2021版本) Seata分布式事务、RocketMQ分布式消息
还有分布式事务、分布式消息等,下一篇再撸吧
其他
相关文档
Sentinel持久化配置
一旦项目重启,Sentinel规则将消失,生产环境需要将配置规则进行持久化
pom
<!-- Sentinel Datasource Nacos 持久化-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
sentinel持久化支持的类型
com.alibaba.cloud.sentinel.datasource.config.DataSourcePropertiesConfiguration
- private FileDataSourceProperties
file
;- private NacosDataSourceProperties
nacos
;- private ZookeeperDataSourceProperties
zk
;- private ApolloDataSourceProperties
apollo
;- private RedisDataSourceProperties
redis
;- private ConsulDataSourceProperties
consul
;
sentinel结合Nacos持久化配置
修改cloud-nacos-customer-center bootstrap.yml,添加
spring:
cloud:
sentinel:
# 取消控制台懒加载
eager: true
transport:
port: 8719 # 在应用对应的机器上启动一个 Http Server,与 Sentinel 控制台做交互
dashboard: localhost:8080 # 控制台地址
filter:
# 关闭官方默认收敛所有context
# 若在网关流控控制台上看到了 URL 资源,就是此配置项没有置为 false
enabled: false
datasource:
# # 降级规则
ds1:
nacos:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
dataId: ${spring.application.name}-flow-rules
groupId: DEFAULT_GROUP
data-type: json
# authority(授权规则)、degrade(降级规则)、flow(流控规则)、param(热点规则)、system(系统规则)五种规则持久化到Nacos中。 另外还增加网关的两个(api分组,限流)
rule-type: flow
nacos添加配置
[
{
"resource": "console-center_test",
"limitApp": "default",
"grade": 1,
"count": 1,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}
]
- resource:资源名称
- limitApp:来源应用
- grade:阀值类型,0-线程数,1-qps
- count:单机阀值
- strategy:流控模式,0-直接,1-关联,2-链路
- controlBehavior:流控效果,0-快速失败,1-warm up,2-排队等待
- clusterMode:是否集群
Sentinel持久化配置如果自己写的话,可能会写错,可以用浏览器捕获数据
Sentinel上的流控规则删除,发布nacos上的配置,测试可达到一样的效果
Nacos持久化
默认情况下Nacos会将配置信息存储在内嵌存储器中,但通常我们希望在数据库中存储或管理这些配置信息,那么就需要进行持久化修改,目前Nacos仅支持MYSQL5.6以上数据库。
初始化数据库表
在/userpath/nacos/conf下找到文件nacos-mysql.sql,在数据库执行该文件内容,完成库表初始化工作。
修改Nacos配置
在/userpath/nacos/conf下找到文件application.properties,定位到 Config Module Related Configurations
将原本注释的部分放开并修改为自己的数据库连接信息。
### 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=123456