续接上一篇gateway简单应用的基础上
1.添加actuator的依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2.yml文件设置:
#配置actuator 提供的端点的安全性 # 暴露端点,供web访问到配置的网关路由 management: endpoints: web: exposure: include: '*'
文件所有内容:
# gateway 网关路由的配置应用
spring:
application:
name: spring-cloud-gateway
cloud:
gateway:
routes:
# gateway实现负载均衡的配置方式
- id: gateway_route
# lb:服务头,实现负载均衡的时候都要这样写服务名,而不懈具体的IP端口,因为一个服务名下面可能有多个服务对应的端口
uri: lb://spring-cloud-user-provider
predicates:
- Path=/gateway/**
filters:
- StripPrefix=1
#多路由的配置
- id: request_ratelimiter_route
#网关映射到的路径
uri: http://localhost:8080/
#断言的设置,一种路由匹配规则,对请求的路径进行判断
predicates:
#映射路径 -> http://localhost:8088/gateway/user
- Path=/ratelimiter/**
# 路径参数的映射 http://localhost:8088/gateway/user?name=zhou
- Query=name,zhou
- Method=GET
filters:
# 路径过滤,去掉路径前缀参数个数 gateway:http://localhost:8088/gateway/test -> http://localhost:8088/test
- StripPrefix=1
- name: RequestRateLimiter #过滤器名字
args: #过滤的参数设置
keyResolver: '#{@ipAddressKeyResolver}' #配置引入定义的限流的keyResolver
redis-rate-limiter.replenishRate: 1 # 每秒生成的令牌桶的个数
redis-rate-limiter.burstCapacity: 2 #令牌桶的容量
#重试机制的过滤配置; id:路由的名称,多个路由区别名
- id: retry_route
predicates:
- Path=/retry/**
uri: http://localhost:8080/
filters:
- StripPrefix=1
- name: Retry
args:
retries: 3 #重试的次数
status: 503 #当服务端返回的状态码是503的时候才会触发重试
#自定义过滤器
- id: define_route
predicates:
- Path=/define/**
uri: http://localhost:8080/
filters:
- StripPrefix=1
- MyDefine=Zhou_Guanjun
#配置服务发现(实现负载均衡时开启)
discovery:
locator:
lower-case-service-id: true #大小写敏感
enabled: true # 开启服务地址的发现
# redis 主机地址的配置
redis:
host: 192.168.43.84
port: 6379
timeout: 5000
server:
port: 8088
#配置指定的服务注册中心,配置负载均衡的时候需要配置(从服务注册中心获取服务地址列表)
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
#配置actuator 提供的端点的安全性
# 暴露端点
management:
endpoints:
web:
exposure:
include: '*'
3.自定义实现类:使用了redis的缓存机制,实现存储动态路由网关,使用postman工具进行测试动态的网关路由的配置方式
package com.self.springcloud.springcloudgateways;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.ArrayList;
import java.util.List;
/**
* 自定义的动态路由的实现持久化操作;
* 实现接口RouteDefinitionRepository
*
*
*/
@Component
public class RedisRouteDefinitionRepository implements RouteDefinitionRepository {
//定义路由的名字
private final static String GATEWAY_ROTE_KEY="gateway_dynamic_route";
@Autowired
private RedisTemplate<String,String> redisTemplate;
/**
* 获取动态的路由
* @return
*/
@Override
public Flux<RouteDefinition> getRouteDefinitions() {
List<RouteDefinition> routeDefinitionList=new ArrayList<>();
redisTemplate.opsForHash().values(GATEWAY_ROTE_KEY).stream().forEach(route->{
routeDefinitionList.add(JSON.parseObject(route.toString(),RouteDefinition.class));
});
return Flux.fromIterable(routeDefinitionList);
}
/**
* 保存路由的方式
* @param route
* @return
*/
@Override
public Mono<Void> save(Mono<RouteDefinition> route) {
// 把routeDefinition对象转换为json字符串
return route.flatMap(routeDefinition -> {
redisTemplate.opsForHash().put(GATEWAY_ROTE_KEY,routeDefinition.getId(), JSON.toJSONString(routeDefinition));
return Mono.empty();
});
}
/**
* 删除ID
* @param routeId
* @return
*/
@Override
public Mono<Void> delete(Mono<String> routeId) {
return routeId.flatMap(id->{
if (redisTemplate.opsForHash().hasKey(GATEWAY_ROTE_KEY,id)){
redisTemplate.opsForHash().delete(GATEWAY_ROTE_KEY,id);
return Mono.empty();
}
return Mono.defer(()-> Mono.error(new Exception("routeDefinition not found:"+routeId)));
});
}
}
4.测试结果:
测试用例:该代码在postman内,为json格式
{
"uri": "https://www.baidu.com",
"predicates": [{
"name": "Path",
"args": {
"pattern": "/baidu/**"
}
}],
"filters": [{
"name": "StripPrefix",
"args": {
"_genkey_0":1
}
}]
}
发送配置的路由数据后,需要使用refresh刷新缓存才能生效
网关列表的显示:
这是可以访问路由跳转百度的链接:通过自己的URL路由到百度下面
同样路由存储到了redis里面: