溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Spring Cloud Zuul的動態(tài)路由以及集成Nacos實(shí)現(xiàn)的示例分析

發(fā)布時間:2021-12-18 14:48:40 來源:億速云 閱讀:530 作者:柒染 欄目:大數(shù)據(jù)

Spring Cloud Zuul的動態(tài)路由以及集成Nacos實(shí)現(xiàn)的示例分析,針對這個問題,這篇文章詳細(xì)介紹了相對應(yīng)的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

一、說明

網(wǎng)關(guān)的核心概念就是路由配置和路由規(guī)則,而作為所有請求流量的入口,在實(shí)際生產(chǎn)環(huán)境中為了保證高可靠和高可用,是盡量要避免重啟的,所以實(shí)現(xiàn)動態(tài)路由是非常有必要的;下面主要介紹實(shí)現(xiàn)的思路,并且以Nacos為數(shù)據(jù)源來講解

二、實(shí)現(xiàn)要點(diǎn)

要實(shí)現(xiàn)動態(tài)路由只需關(guān)注下面4個點(diǎn)

  1. 網(wǎng)關(guān)啟動時,動態(tài)路由的數(shù)據(jù)怎樣加載進(jìn)來

  2. 靜態(tài)路由動態(tài)路由以那個為準(zhǔn),ps:靜態(tài)路由指的是配置文件里寫死的路由配置

  3. 監(jiān)聽動態(tài)路由的數(shù)據(jù)源變化

  4. 數(shù)據(jù)有變化時怎樣通知zuul刷新路由

三、具體實(shí)現(xiàn)

3.1. 實(shí)現(xiàn)動態(tài)路由的數(shù)據(jù)加載

  • 重寫SimpleRouteLocator類的locateRoutes方法,此方法是加載路由配置的,父類中是獲取properties中的路由配置,可以通過擴(kuò)展此方法,達(dá)到動態(tài)獲取配置的目的

  • 這里采用靜態(tài)路由動態(tài)路由共存,相同路由id以動態(tài)路由優(yōu)先覆蓋的實(shí)現(xiàn)方式

AbstractDynRouteLocator抽象類

public abstract class AbstractDynRouteLocator extends SimpleRouteLocator implements RefreshableRouteLocator {    private ZuulProperties properties;    public AbstractDynRouteLocator(String servletPath, ZuulProperties properties) {        super(servletPath, properties);        this.properties = properties;    }    @Override    public void refresh() {        doRefresh();    }    @Override    protected Map<String, ZuulRoute> locateRoutes() {        LinkedHashMap<String, ZuulRoute> routesMap = new LinkedHashMap<>();        // 從application.properties中加載靜態(tài)路由信息        routesMap.putAll(super.locateRoutes());        // 從數(shù)據(jù)源中加載動態(tài)路由信息        routesMap.putAll(loadDynamicRoute());        // 優(yōu)化一下配置        LinkedHashMap<String, ZuulRoute> values = new LinkedHashMap<>();        for (Map.Entry<String, ZuulRoute> entry : routesMap.entrySet()) {            String path = entry.getKey();            // Prepend with slash if not already present.            if (!path.startsWith("/")) {                path = "/" + path;            }            if (StringUtils.hasText(this.properties.getPrefix())) {                path = this.properties.getPrefix() + path;                if (!path.startsWith("/")) {                    path = "/" + path;                }            }            values.put(path, entry.getValue());        }        return values;    }    /**     * 加載路由配置,由子類去實(shí)現(xiàn)     */    public abstract Map<String, ZuulRoute> loadDynamicRoute();}

由于動態(tài)路由的數(shù)據(jù)可以有很多種途徑,如:Nacos、Redis、Zookeeper、DB等,所以這里定義一個抽象類,由具體的實(shí)現(xiàn)類去定義loadDynamicRoute方法

3.2. Nacos路由實(shí)現(xiàn)類

NacosDynRouteLocator類

3.2.1. 實(shí)現(xiàn)loadDynamicRoute方法獲取動態(tài)數(shù)據(jù)

@Overridepublic Map<String, ZuulProperties.ZuulRoute> loadDynamicRoute() {    Map<String, ZuulRoute> routes = new LinkedHashMap<>();    if (zuulRouteEntities == null) {        zuulRouteEntities = getNacosConfig();    }    for (ZuulRouteEntity result : zuulRouteEntities) {        if (StrUtil.isBlank(result.getPath()) || !result.isEnabled()) {            continue;        }        ZuulRoute zuulRoute = new ZuulRoute();        BeanUtil.copyProperties(result, zuulRoute);        routes.put(zuulRoute.getPath(), zuulRoute);    }    return routes;}private List<ZuulRouteEntity> getNacosConfig() {    try {        String content = nacosConfigProperties.configServiceInstance().getConfig(ZUUL_DATA_ID, ZUUL_GROUP_ID,5000);        return getListByStr(content);    } catch (NacosException e) {        log.error("listenerNacos-error", e);    }    return new ArrayList<>(0);}

3.2.2. 增加NacosListener監(jiān)聽路由數(shù)據(jù)變化

private void addListener() {    try {        nacosConfigProperties.configServiceInstance().addListener(ZUUL_DATA_ID, ZUUL_GROUP_ID, new Listener() {            @Override            public Executor getExecutor() {                return null;            }            @Override            public void receiveConfigInfo(String configInfo) {                //賦值路由信息                locator.setZuulRouteEntities(getListByStr(configInfo));                RoutesRefreshedEvent routesRefreshedEvent = new RoutesRefreshedEvent(locator);                publisher.publishEvent(routesRefreshedEvent);            }        });    } catch (NacosException e) {        log.error("nacos-addListener-error", e);    }}

注意路由數(shù)據(jù)變化后不需要自己手動刷新路由,只需要給zuul發(fā)送一個RoutesRefreshedEvent事件即可,zuul自己有個ZuulRefreshListener類會監(jiān)聽事件幫我們刷新路由

該類完整的代碼實(shí)現(xiàn)可查看:

https://gitee.com/zlt2000/microservices-platform/blob/master/zlt-gateway/zuul-gateway/src/main/java/com/central/gateway/route/nacos/NacosDynRouteLocator.java

3.3. 配置類創(chuàng)建NacosDynRouteLocator的Bean

DynamicZuulRouteConfig類

@Configuration@ConditionalOnProperty(prefix = "zlt.gateway.dynamicRoute", name = "enabled", havingValue = "true")public class DynamicZuulRouteConfig {    @Autowired    private ZuulProperties zuulProperties;    @Autowired    private DispatcherServletPath dispatcherServletPath;    /**     * Nacos實(shí)現(xiàn)方式     */    @Configuration    @ConditionalOnProperty(prefix = "zlt.gateway.dynamicRoute", name = "dataType", havingValue = "nacos", matchIfMissing = true)    public class NacosZuulRoute {        @Autowired        private NacosConfigProperties nacosConfigProperties;        @Autowired        private ApplicationEventPublisher publisher;        @Bean        public NacosDynRouteLocator nacosDynRouteLocator() {            return new NacosDynRouteLocator(nacosConfigProperties, publisher, dispatcherServletPath.getPrefix(), zuulProperties);        }    }}

這里通過自定義配置來控制是否開啟動態(tài)路由功能

3.4. 添加Nacos路由配置

Spring Cloud Zuul的動態(tài)路由以及集成Nacos實(shí)現(xiàn)的示例分析
新增配置項:

  • Data Id:zuul-routes

  • Group:ZUUL_GATEWAY

  • 配置內(nèi)容:

[  {      "enabled":true,      "id":"csdn",      "path":"/csdn/**",      "retryable":false,      "stripPrefix":true,      "url":"https://www.csdn.net/"  }, {      "enabled":true,      "id":"github",      "path":"/github/**",      "retryable":false,      "stripPrefix":true,      "url":"http://github.com/"  }]

添加兩條路由數(shù)據(jù)

四、測試

  • 啟動網(wǎng)關(guān)通過/actuator/routes端點(diǎn)查看網(wǎng)關(guān)所有路由信息
    Spring Cloud Zuul的動態(tài)路由以及集成Nacos實(shí)現(xiàn)的示例分析

    可以看到靜態(tài)路由和Nacos里配置的兩條路由信息并存顯示

  • 修改Nacos配置,關(guān)閉csdn路由
    Spring Cloud Zuul的動態(tài)路由以及集成Nacos實(shí)現(xiàn)的示例分析

  • 刷新查看網(wǎng)關(guān)的路由信息
    Spring Cloud Zuul的動態(tài)路由以及集成Nacos實(shí)現(xiàn)的示例分析

    csdn的路由已經(jīng)看不到了,實(shí)現(xiàn)了動態(tài)改變路由配置

關(guān)于Spring Cloud Zuul的動態(tài)路由以及集成Nacos實(shí)現(xiàn)的示例分析問題的解答就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI