1. 将 actuator 端点暴露出来
-
management:
-
endpoints:
-
web:
-
exposure:
-
include: "*"
2. redis 配置
https://www.cnblogs.com/idea360/p/12632801.html
3. 将原内存路由持久化到 redis
-
@Component
-
public class RedisRouteDefinitionRepository implements RouteDefinitionRepository {
-
/**
-
* hash存储的key
-
*/
-
public static final String GATEWAY_ROUTES = "gateway_dynamic_route";
-
@Resource
-
private StringRedisTemplate redisTemplate;
-
/**
-
* 获取路由信息
-
* @return
-
*/
-
@Override
-
public Flux<RouteDefinition> getRouteDefinitions() {
-
List<RouteDefinition> routeDefinitions = new ArrayList<>();
-
redisTemplate.opsForHash().values(GATEWAY_ROUTES).stream()
-
.forEach(routeDefinition -> routeDefinitions.add(JSON.parseObject(routeDefinition.toString(), RouteDefinition.class)));
-
return Flux.fromIterable(routeDefinitions);
-
}
-
@Override
-
public Mono<Void> save(Mono<RouteDefinition> route) {
-
return route.flatMap(routeDefinition -> {
-
redisTemplate.opsForHash().put(GATEWAY_ROUTES, routeDefinition.getId(), JSONObject.toJSONString(routeDefinition));
-
return Mono.empty();
-
});
-
}
-
@Override
-
public Mono<Void> delete(Mono<String> routeId) {
-
return routeId.flatMap(id -> {
-
if (redisTemplate.opsForHash().hasKey(GATEWAY_ROUTES, id)) {
-
redisTemplate.opsForHash().delete(GATEWAY_ROUTES, id);
-
return Mono.empty();
-
}
-
return Mono.defer(() -> Mono.error(new NotFoundException("route definition is not found, routeId:" + routeId)));
-
});
-
}
-
}
4. 重写动态路由服务
-
@Service
-
public class GatewayDynamicRouteService implements ApplicationEventPublisherAware {
-
@Resource
-
private RedisRouteDefinitionRepository redisRouteDefinitionRepository;
-
private ApplicationEventPublisher applicationEventPublisher;
-
/**
-
* 增加路由
-
* @param routeDefinition
-
* @return
-
*/
-
public int add(RouteDefinition routeDefinition) {
-
redisRouteDefinitionRepository.save(Mono.just(routeDefinition)).subscribe();
-
applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
-
return 1;
-
}
-
/**
-
* 更新
-
* @param routeDefinition
-
* @return
-
*/
-
public int update(RouteDefinition routeDefinition) {
-
redisRouteDefinitionRepository.delete(Mono.just(routeDefinition.getId()));
-
redisRouteDefinitionRepository.save(Mono.just(routeDefinition)).subscribe();
-
applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
-
return 1;
-
}
-
/**
-
* 删除
-
* @param id
-
* @return
-
*/
-
public Mono<ResponseEntity<Object>> delete(String id) {
-
return redisRouteDefinitionRepository.delete(Mono.just(id)).then(Mono.defer(() -> Mono.just(ResponseEntity.ok().build())))
-
.onErrorResume(t -> t instanceof NotFoundException, t -> Mono.just(ResponseEntity.notFound().build()));
-
}
-
@Override
-
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
-
this.applicationEventPublisher = applicationEventPublisher;
-
}
-
}
5. 对外暴露接口
-
@RestController
-
@RequestMapping("/gateway")
-
public class GatewayDynamicRouteController {
-
@Resource
-
private GatewayDynamicRouteService gatewayDynamicRouteService;
-
@PostMapping("/add")
-
public String create(@RequestBody RouteDefinition entity) {
-
int result = gatewayDynamicRouteService.add(entity);
-
return String.valueOf(result);
-
}
-
@PostMapping("/update")
-
public String update(@RequestBody RouteDefinition entity) {
-
int result = gatewayDynamicRouteService.update(entity);
-
return String.valueOf(result);
-
}
-
@DeleteMapping("/delete/{id}")
-
public Mono<ResponseEntity<Object>> delete(@PathVariable String id) {
-
return gatewayDynamicRouteService.delete(id);
-
}
-
}
测试
测试前删除我们配置的静态路由,因为静态路由和 redis 动态路由同时存在时取并集。
- 访问 http://localhost:2000/actuator/gateway/routes , 可以看到只有默认路由。
-
[
-
{
-
"route_id": "CompositeDiscoveryClient_consul",
-
"route_definition": {
-
"id": "CompositeDiscoveryClient_consul",
-
"predicates": [
-
{
-
"name": "Path",
-
"args": {
-
"pattern": "/consul/**"
-
}
-
}
-
],
-
"filters": [
-
{
-
"name": "RewritePath",
-
"args": {
-
"regexp": "/consul/(?<remaining>.*)",
-
"replacement": "/${remaining}"
-
}
-
}
-
],
-
"uri": "lb://consul",
-
"order": 0
-
},
-
"order": 0
-
},
-
{
-
"route_id": "CompositeDiscoveryClient_idc-gateway",
-
"route_definition": {
-
"id": "CompositeDiscoveryClient_idc-gateway",
-
"predicates": [
-
{
-
"name": "Path",
-
"args": {
-
"pattern": "/idc-gateway/**"
-
}
-
}
-
],
-
"filters": [
-
{
-
"name": "RewritePath",
-
"args": {
-
"regexp": "/idc-gateway/(?<remaining>.*)",
-
"replacement": "/${remaining}"
-
}
-
}
-
],
-
"uri": "lb://idc-gateway",
-
"order": 0
-
},
-
"order": 0
-
},
-
{
-
"route_id": "CompositeDiscoveryClient_idc-provider1",
-
"route_definition": {
-
"id": "CompositeDiscoveryClient_idc-provider1",
-
"predicates": [
-
{
-
"name": "Path",
-
"args": {
-
"pattern": "/idc-provider1/**"
-
}
-
}
-
],
-
"filters": [
-
{
-
"name": "RewritePath",
-
"args": {
-
"regexp": "/idc-provider1/(?<remaining>.*)",
-
"replacement": "/${remaining}"
-
}
-
}
-
],
-
"uri": "lb://idc-provider1",
-
"order": 0
-
},
-
"order": 0
-
},
-
{
-
"route_id": "CompositeDiscoveryClient_idc-provider2",
-
"route_definition": {
-
"id": "CompositeDiscoveryClient_idc-provider2",
-
"predicates": [
-
{
-
"name": "Path",
-
"args": {
-
"pattern": "/idc-provider2/**"
-
}
-
}
-
],
-
"filters": [
-
{
-
"name": "RewritePath",
-
"args": {
-
"regexp": "/idc-provider2/(?<remaining>.*)",
-
"replacement": "/${remaining}"
-
}
-
}
-
],
-
"uri": "lb://idc-provider2",
-
"order": 0
-
},
-
"order": 0
-
}
-
]
这个时候访问 http://192.168.124.5:2000/idc-provider1/provider1/1 根据结果可以推测能正确路由到 provider1
, 测试结果一致。
- 创建
provider1
路由,将路径设置为/p1/**
,测试是否生效。
POST
请求 http://localhost:2000/gateway/add
-
{
-
"id":"provider1",
-
"predicates":[
-
{
-
"name":"Path",
-
"args":{
-
"_genkey_0":"/p1/**"
-
}
-
},
-
{
-
"name":"RemoteAddr",
-
"args":{
-
"_genkey_0":"192.168.124.5/16"
-
}
-
}
-
],
-
"filters":[
-
{
-
"name":"StripPrefix",
-
"args":{
-
"_genkey_0":"1"
-
}
-
}
-
],
-
"uri":"lb://idc-provider1",
-
"order":0
-
}
查看 redis
存储,或者请求 http://localhost:2000/actuator/gateway/routes , 都可以看到配置成功。