houyi平台-配置指南-网关配置

网关基本配置说明

TODO:
配置URL

zuul:
  routes:
    users:
      path: /baidu/**
      url: http://baidu.com

配置微服务

zuul:
  routes:
    users:
      path: /myusers/**
      serviceId: users_service

基于Nacos实现动态路由

参考文档
https://blog.csdn.net/rickiyeat/article/details/84595350
原理:
由于Nacos支持动态配置,因此可以通过Nacos配置Zuul的路由。

  1. 监听nacos配置变化
    public void registerNacosConfig(String dataId, String group) {
        try {
            Properties properties = new Properties();
            properties.put(PropertyKeyConst.SERVER_ADDR, GatewayConfig.getInstance().getNacosAddr());
            ConfigService configService = NacosFactory.createConfigService(properties);

            // 注册Nacos配置更新监听器,用于监听触发
            configService.addListener(dataId, group, new Listener() {
                @Override
                public void receiveConfigInfo(String configInfo) {
                    // 发送路由刷新事件
                    refreshRoute();
                }
                @Override
                public Executor getExecutor() {
                    return null;
                }
            });
        } catch (NacosException e) {
            e.printStackTrace();
        }
    }
    
    public void refreshRoute() {

        RoutesRefreshedEvent routesRefreshedEvent = new RoutesRefreshedEvent(routeLocator);
        SpringContextHolder.getApplicationContext().publishEvent(routesRefreshedEvent);

    }

2.注册Nacos配置源

@Configuration
public class NacosZuulConfig {

    @Autowired
    private ZuulProperties zuulProperties;

    @Autowired
    private ServerProperties serverProperties;

    @Bean
    public NacosZuulRouteLocator routeLocator() {
        NacosZuulRouteLocator routeLocator = new NacosZuulRouteLocator(
                this.serverProperties.getServlet().getServletPrefix(), this.zuulProperties);


        RefreshRouteManager.getManager().setRouteLocator(routeLocator);
    
        return routeLocator;
    }
}

3.实现Nacos自动刷新接口


public class NacosZuulRouteLocator extends SimpleRouteLocator implements RefreshableRouteLocator {

    @Autowired
    private ZuulProperties properties;

    @Autowired
    private DynamicNacosConfig propertiesAssemble;

    public NacosZuulRouteLocator(String servletPath, ZuulProperties properties) {
        super(servletPath, properties);
        this.properties = properties;
    }

    @Override
    public void refresh() {
        super.doRefresh();
    }

    @Override
    protected Map<String, ZuulRoute> locateRoutes() {
        LinkedHashMap<String, ZuulRoute> routesMap = new LinkedHashMap<String, ZuulRoute>();
        // 从application.properties中加载路由信息
        routesMap.putAll(super.locateRoutes());
        // 从Nacos中加载路由信息
        routesMap.putAll(propertiesAssemble.getProperties());
        // 优化一下配置
        LinkedHashMap<String, ZuulRoute> values = new LinkedHashMap<>();
        for (Map.Entry<String, ZuulRoute> entry : routesMap.entrySet()) {
            String path = entry.getKey();

            if(path==null){
                continue;
            }
            // 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());
        }
        System.out.println("Router : " + values.toString());
        
        return values;
    }
}

4.解析Nacos配置文件

@Component
public class DynamicNacosConfig {

    public Map<String, ZuulRoute> getProperties() {

        Map<String, ZuulRoute> routes = new LinkedHashMap<>();

        if (GatewayConfig.getInstance().getDataId() == null) {
            return routes;
        }

        List<ZuulRouteEntity> results = listenNacos(GatewayConfig.getInstance().getDataId(),
                GatewayConfig.getInstance().getGroup());

        for (ZuulRouteEntity result : results) {
            if (StringUtils.isBlank(result.getPath())) {
                continue;
            }
            ZuulRoute zuulRoute = new ZuulRoute(result.getId(), result.getPath(), result.getServiceId(),
                    result.getUrl(), result.isStripPrefix(), result.getRetryable(), null);

            routes.put(zuulRoute.getPath(), zuulRoute);

        }

        return routes;
    }

    private List<ZuulRouteEntity> listenNacos(String dataId, String group) {
        try {
            Properties properties = new Properties();
            properties.put(PropertyKeyConst.SERVER_ADDR, GatewayConfig.getInstance().getNacosAddr());
            ConfigService configService = NacosFactory.createConfigService(properties);
            String content = configService.getConfig(dataId, group, 5000);
            System.out.println("从Nacos返回的配置:" + content);
            if (content == null) {
                return new ArrayList<ZuulRouteEntity>();
            } else {
                return JSONObject.parseArray(content, ZuulRouteEntity.class);
            }

        } catch (NacosException e) {
            e.printStackTrace();
        }
        return new ArrayList<>();
    }

}

5.Nacos配置项解析Bean

public class ZuulRouteEntity {
    /**
     * The ID of the route (the same as its map key by default).
     */
    private String id;
    /**
     * The path (pattern) for the route, e.g. /foo/**.
     */
    private String path;
    /**
     * The service ID (if any) to map to this route. You can specify a physical
     * URL or a service, but not both.
     */
    private String serviceId;
    /**
     * A full physical URL to map to the route. An alternative is to use a
     * service ID and service discovery to find the physical address.
     */
    private String url;
    /**
     * Flag to determine whether the prefix for this route (the path, minus
     * pattern patcher) should be stripped before forwarding.
     */
    private boolean stripPrefix = true;
    /**
     * Flag to indicate that this route should be retryable (if supported).
     * Generally retry requires a service ID and ribbon.
     */
    private Boolean retryable;

    private String apiName;

    private Boolean enabled;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public String getServiceId() {
        return serviceId;
    }

    public void setServiceId(String serviceId) {
        this.serviceId = serviceId;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public boolean isStripPrefix() {
        return stripPrefix;
    }

    public void setStripPrefix(boolean stripPrefix) {
        this.stripPrefix = stripPrefix;
    }

    public Boolean getRetryable() {
        return retryable;
    }

    public void setRetryable(Boolean retryable) {
        this.retryable = retryable;
    }

    public String getApiName() {
        return apiName;
    }

    public void setApiName(String apiName) {
        this.apiName = apiName;
    }

    public Boolean getEnabled() {
        return enabled;
    }

    public void setEnabled(Boolean enabled) {
        this.enabled = enabled;
    }
}

Nacos配置样例

[
{"enabled":true,
"id":"test",
"path":"/test130/**",
"retryable":false,
"stripPrefix":true,
"service-id": "user-center"
}
]

授权使用说明

TODO:

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,755评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,305评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,138评论 0 355
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,791评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,794评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,631评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,362评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,264评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,724评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,900评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,040评论 1 350
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,742评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,364评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,944评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,060评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,247评论 3 371
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,979评论 2 355

推荐阅读更多精彩内容