Spring cloud gateway nacos實現動態路由

Spring cloud gateway的三個核心概念

route 路由

能夠理解爲一條轉發規則,包含:css

  • id
  • 目標url
  • 斷言(predicate)
  • 過濾器(filter)
    若斷言爲true,則請求將經由 filter 被路由到目標 url。

predicate 斷言

能夠理解爲一個條件判斷,對當前的http請求進行指定規則的匹配,當匹配上規則時,斷言才爲true,此時請求會被路由到目標地址,服務或者過濾器html

filter 過濾器

對請求進行處理的邏輯部分。當請求的斷言爲true 時,會被路由到設置好的過濾器, 以對請求進行處理。例如,能夠爲請求添加一個請求頭,或添加一個請求參數,或對請求URI 進行修改等。mysql

Nacos做爲路由規則的配置中心

nacos的配置和運行以下git

  • MySQL配置運行
  • 運行MySQLgithub

    docker run -p 3306:3306 --name mysql \
    -v /Users/wangbin/dockerall/mysql/log:/var/log/mysql \
    -v /Users/wangbin/dockerall/mysql/data:/var/lib/mysql \
    -v /Users/wangbin/dockerall/mysql/conf:/etc/mysql \
    -e MYSQL_ROOT_PASSWORD=root \
    -d mysql:5.7
    
    docker exec -it mysql bash
    
    mysql -proot
    
    create database nacos_config;
    
    use nacos_config;
  • 執行SQL
    SQL內容
  • 新建/xxxxx/nacos_docker/init.d/目錄並生成custom.properties文件。文件內容以下web

    management.endpoints.web.exposure.include=*
    server.contextPath=/nacos
    server.servlet.contextPath=/nacos
    server.port=8848
    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=root
    nacos.cmdb.dumpTaskInterval=3600
    nacos.cmdb.eventTaskInterval=10
    nacos.cmdb.labelTaskInterval=300
    nacos.cmdb.loadDataAtStart=false
    management.metrics.export.elastic.enabled=false
    management.metrics.export.influx.enabled=false
    server.tomcat.accesslog.enabled=true
    server.tomcat.accesslog.pattern=%h %l %u %t "%r" %s %b %D %{User-Agent}i
    nacos.security.ignore.urls=/,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/v1/auth/login,/v1/console/health/**,/v1/cs/**,/v1/ns/**,/v1/cmdb/**,/actuator/**,/v1/console/server/**
    nacos.naming.distro.taskDispatchThreadCount=1
    nacos.naming.distro.taskDispatchPeriod=200
    nacos.naming.distro.batchSyncKeyCount=1000
    nacos.naming.distro.initDataRatio=0.9
    nacos.naming.distro.syncRetryDelay=5000
    nacos.naming.data.warmup=true
    nacos.naming.expireInstance=true
  • 新建logs目錄
  • 運行Nacosspring

    docker run
    --name nacos -d
    -p 8848:8848
    --privileged=true
    --restart=always
    -e JVM_XMS=256m
    -e JVM_XMX=256m
    -e MODE=standalone
    -e PREFER_HOST_MODE=hostname
    -v /xxxxx/nacos_docker/init.d/custom.properties:/home/nacos/init.d/custom.properties
    -v /xxxxx/nacos_docker/logs:/home/nacos/logs
    nacos/nacos-server
  • 訪問 http://localhost:8848
  • 輸入 nacos/nacos登錄

新建配置內容sql

image

內容以下docker

[{
    "id":"user-router",
    "predicates":[
      {
        "args":{
          "pattern": "/usr/**"
        },
        "name": "Path"
      }
    ],
    "filters": [
      {
        "name": "StripPrefix",
        "args": {
          "parts": "1"
        }
      }
    ],
    "uri": "lb://user-service"
}]

對應的yml內容如route部分bootstrap

spring:
  application:
    name: dynamicgateway
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #配置Nacos地址
      config:
        server-addr: localhost:8848
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
        - id: user-router
          uri: lb://user-service
          predicates:
            - Path=/usr/**
      filters:
        - StripPrefix=1 # 表示在轉發時去掉usr

新建項目
由於使用了Spring cloud,Spring Cloud Alibaba,Nacos之間的版本依賴關係以下
版本依賴關係

新建DynamicGatewayRouteConfig

@Component
public class DynamicGatewayRouteConfig implements ApplicationEventPublisherAware {

    private String dataId = "gateway-router";

    private String group = "DEFAULT_GROUP";

    @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<String>();

    @PostConstruct
    public void dynamicRouteByNacosListener() {
        try {
            ConfigService configService = NacosFactory.createConfigService(serverAddr);
            configService.getConfig(dataId, group, 5000);
            configService.addListener(dataId, group, new Listener() {

                public void receiveConfigInfo(String configInfo) {
                    clearRoute();
                    try {
                        List<RouteDefinition> gatewayRouteDefinitions = JSONObject.parseArray(configInfo, RouteDefinition.class);
                        for (RouteDefinition routeDefinition : gatewayRouteDefinitions) {
                            addRoute(routeDefinition);
                        }
                        publish();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

                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));
    }

    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }
}

在nacos的route內容發生變化時會自動調用更新

bootstrap.yml內容以下

spring:
  application:
    name: dynamicgateway
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #配置Nacos地址
 config:
        server-addr: localhost:8848
    gateway:
      discovery:
        locator:
          enabled: true
management:
  endpoints:
    web:
      exposure:
        include: '*'
 endpoint:
    health:
      show-details: always

具體代碼
代碼

相關文章
相關標籤/搜索