{"id":2160,"date":"2023-04-02T13:34:26","date_gmt":"2023-04-02T05:34:26","guid":{"rendered":"https:\/\/www.appblog.cn\/?p=2160"},"modified":"2023-04-05T19:44:54","modified_gmt":"2023-04-05T11:44:54","slug":"spring-cloud-zuul-routing-automatic-refresh-principle","status":"publish","type":"post","link":"https:\/\/www.appblog.cn\/index.php\/2023\/04\/02\/spring-cloud-zuul-routing-automatic-refresh-principle\/","title":{"rendered":"Spring Cloud Zuul \u8def\u7531\u81ea\u52a8\u5237\u65b0\u539f\u7406"},"content":{"rendered":"<h2>\u73b0\u8c61<\/h2>\n<p>\u53d1\u5e03\u65b0\u670d\u52a1\uff0c\u7136\u540e\u5728\u6570\u636e\u5e93\u914d\u7f6e\u4e86\u8def\u7531\uff0c\u4f7f\u7528\u670d\u52a1\u8def\u5f84\u8bbf\u95ee404\u3002\u7136\u540e\u91cd\u65b0\u53d1\u5e03\u65b0\u7684\u670d\u52a1\uff0c\u5c31\u53ef\u4ee5\u7ee7\u7eed\u8bbf\u95ee\u5f97\u5230<\/p>\n<p>\uff081\uff09\u914d\u7f6e\u4e86\u8def\u7531\u7b2c\u4e00\u6b21\u8bbf\u95ee<\/p>\n<p><!-- more --><\/p>\n<p><img decoding=\"async\" src=\"http:\/\/www.yezhou.me\/AppBlog\/images\/Java\/\u52a8\u6001\u8def\u7531-\u5e94\u7528\u91cd\u542f\u524d.png\" alt=\"\u52a8\u6001\u8def\u7531-\u5e94\u7528\u91cd\u542f\u524d\" \/><\/p>\n<p>\uff082\uff09\u91cd\u65b0\u53d1\u5e03\u540e\u8bbf\u95ee<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/www.yezhou.me\/AppBlog\/images\/Java\/\u52a8\u6001\u8def\u7531-\u5e94\u7528\u91cd\u542f\u540e.png\" alt=\"\u52a8\u6001\u8def\u7531-\u5e94\u7528\u91cd\u542f\u540e\" \/><\/p>\n<h2>\u5206\u6790<\/h2>\n<p>\uff081\uff09\u67e5\u627e<code>RefreshableRouteLocator.refresh<\/code>\u65b9\u6cd5<\/p>\n<pre><code class=\"language-java\">@Component\npublic class NacosRouteLocator extends SimpleRouteLocator implements RefreshableRouteLocator {\n\n    public NacosRouteLocator(ServerProperties serverProperties, ZuulProperties properties) {\n        super(serverProperties.getServlet().getContextPath(), properties);\n    }\n\n    @Override\n    public void refresh() {\n        doRefresh();\n    }\n\n    @Override\n    protected Map&lt;String, ZuulProperties.ZuulRoute&gt; locateRoutes() {\n\n        \/\/\u9ed8\u8ba4\u4ece\u914d\u7f6e\u6587\u4ef6\u4e2d\u52a0\u8f7d\u8def\u7531\u4fe1\u606f\n        \/\/return super.locateRoutes());\n\n        \/\/\u5b9a\u5236\u8def\u7531, \u53ef\u4ee5\u4f7f\u7528db\u7684\u914d\u7f6e\u7ba1\u7406\u8fdb\u884c\u8def\u7531\n        Map&lt;String, ZuulProperties.ZuulRoute&gt; routesMap = DbUtils.loadRoutes();\n\n        return routesMap;\n    }\n}<\/code><\/pre>\n<p>\uff082\uff09<code>ZuulHandlerMapping.setDirty<\/code>\u65b9\u6cd5<\/p>\n<pre><code class=\"language-java\">public class ZuulHandlerMapping extends AbstractUrlHandlerMapping {\n\n    public void setDirty(boolean dirty) {\n        this.dirty = dirty;\n        if (this.routeLocator instanceof RefreshableRouteLocator) {\n            ((RefreshableRouteLocator) this.routeLocator).refresh();\n        }\n    }\n}<\/code><\/pre>\n<p>\uff083\uff09<code>ZuulRefreshListener.reset<\/code>\u65b9\u6cd5<\/p>\n<pre><code class=\"language-java\">private static class ZuulRefreshListener\n        implements ApplicationListener&lt;ApplicationEvent&gt; {\n\n    @Autowired\n    private ZuulHandlerMapping zuulHandlerMapping;\n\n    private HeartbeatMonitor heartbeatMonitor = new HeartbeatMonitor();\n\n    @Override\n    public void onApplicationEvent(ApplicationEvent event) {\n        if (event instanceof ContextRefreshedEvent\n                || event instanceof RefreshScopeRefreshedEvent\n                || event instanceof RoutesRefreshedEvent\n                || event instanceof InstanceRegisteredEvent) {\n            reset();\n        }\n        else if (event instanceof ParentHeartbeatEvent) {\n            ParentHeartbeatEvent e = (ParentHeartbeatEvent) event;\n            resetIfNeeded(e.getValue());\n        }\n        else if (event instanceof HeartbeatEvent) {\n            HeartbeatEvent e = (HeartbeatEvent) event;\n            resetIfNeeded(e.getValue());\n        }\n    }\n\n    private void resetIfNeeded(Object value) {\n        if (this.heartbeatMonitor.update(value)) {\n            reset();\n        }\n    }\n\n    private void reset() {\n        this.zuulHandlerMapping.setDirty(true);\n    }\n}<\/code><\/pre>\n<p>\uff084\uff09\u53d1\u73b0<code>ApplicationEvent<\/code><\/p>\n<pre><code class=\"language-java\">@Override\npublic void onApplicationEvent(ApplicationEvent event) {\n    if (event instanceof ContextRefreshedEvent\n            || event instanceof RefreshScopeRefreshedEvent\n            || event instanceof RoutesRefreshedEvent\n            || event instanceof InstanceRegisteredEvent) {\n        reset();\n    }\n    else if (event instanceof ParentHeartbeatEvent) {\n        ParentHeartbeatEvent e = (ParentHeartbeatEvent) event;\n        resetIfNeeded(e.getValue());\n    }\n    else if (event instanceof HeartbeatEvent) {\n        HeartbeatEvent e = (HeartbeatEvent) event;\n        resetIfNeeded(e.getValue());\n    }\n}<\/code><\/pre>\n<p>\u53ef\u4ee5\u770b\u5230\uff0c\u5176\u4e2d\u7684\u5b9e\u4f8b\u6ce8\u518c\u4e8b\u4ef6<code>RoutesRefreshedEvent<\/code>\u548c<code>InstanceRegisteredEvent<\/code>\u5747\u4f1a\u89e6\u53d1\u5237\u65b0\u8def\u7531\u3002<\/p>\n<p>\uff085\uff09Eureka\u89e6\u53d1\u8def\u7531\u66f4\u65b0<\/p>\n<pre><code class=\"language-java\">\/\/ org.springframework.cloud.netflix.eureka.CloudEurekaClient#onCacheRefreshed\n@Override\nprotected void onCacheRefreshed() {\n    super.onCacheRefreshed();\n\n    if (this.cacheRefreshedCount != null) { \/\/ might be called during construction and\n        \/\/ will be null\n        long newCount = this.cacheRefreshedCount.incrementAndGet();\n        log.trace(&quot;onCacheRefreshed called with count: &quot; + newCount);\n        this.publisher.publishEvent(new HeartbeatEvent(this, newCount));\n    }\n}<\/code><\/pre>\n<pre><code class=\"language-java\">@Override\n\/\/ org.springframework.cloud.netflix.eureka.serviceregistry.EurekaAutoServiceRegistration#start\npublic void start() {\n    \/\/ only set the port if the nonSecurePort or securePort is 0 and this.port != 0\n    if (this.port.get() != 0) {\n        if (this.registration.getNonSecurePort() == 0) {\n            this.registration.setNonSecurePort(this.port.get());\n        }\n\n        if (this.registration.getSecurePort() == 0 &amp;&amp; this.registration.isSecure()) {\n            this.registration.setSecurePort(this.port.get());\n        }\n    }\n\n    \/\/ only initialize if nonSecurePort is greater than 0 and it isn&#039;t already running\n    \/\/ because of containerPortInitializer below\n    if (!this.running.get() &amp;&amp; this.registration.getNonSecurePort() &gt; 0) {\n\n        this.serviceRegistry.register(this.registration);\n\n        this.context.publishEvent(new InstanceRegisteredEvent&lt;&gt;(this,\n                this.registration.getInstanceConfig()));\n        this.running.set(true);\n    }\n}<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\u73b0\u8c61 \u53d1\u5e03\u65b0\u670d\u52a1\uff0c\u7136\u540e\u5728\u6570\u636e\u5e93\u914d\u7f6e\u4e86\u8def\u7531\uff0c\u4f7f\u7528\u670d\u52a1\u8def\u5f84\u8bbf\u95ee404\u3002\u7136\u540e\u91cd\u65b0\u53d1\u5e03\u65b0\u7684\u670d\u52a1\uff0c\u5c31\u53ef\u4ee5\u7ee7\u7eed\u8bbf\u95ee\u5f97\u5230 \uff08 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[42],"tags":[250],"class_list":["post-2160","post","type-post","status-publish","format-standard","hentry","category-spring-cloud","tag-zuul"],"_links":{"self":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts\/2160","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/comments?post=2160"}],"version-history":[{"count":0,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts\/2160\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/media?parent=2160"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/categories?post=2160"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/tags?post=2160"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}