开发者社区 > 云原生 > 正文

请问有没有nacos+gateway 服务优雅下线的示例呀?找了好多个方案,感觉效果都不明显。

请问有没有nacos+gateway 服务优雅下线的示例呀?找了好多个方案,感觉效果都不明显,nacos server 2.0.4 nacos-client 1.4.2 。我们使用的kubernetes preStop hook ,已经提前通知服务器下线了,且gateway上也收到了nacos的event事件,但是感觉gateway并没有及时更新它的路由。

展开
收起
十一0204 2023-07-05 20:53:34 251 0
3 条回答
写回答
取消 提交回答
  • 在 Nacos 和 Spring Cloud Gateway 集成中,实现服务优雅下线需要考虑多个方面的因素。下面是一个可能的解决方案:

    1. 在 Nacos Server 的配置文件 application.properties 中,开启 nacos.discovery.server-protect-mode.enabled 属性,以防止服务下线后被其他服务误用。

    nacos.discovery.server-protect-mode.enabled=true
    

    2. 在 Nacos 客户端的配置文件中,设置 nacos.client.failover-switch 和 nacos.client.updateThreadNum 属性,以保证客户端能够及时地感知到服务下线事件。

    nacos.client.failover-switch=true
    nacos.client.updateThreadNum=20
    

    3. 在 Spring Cloud Gateway 的配置文件中,开启 spring.cloud.gateway.discovery.locator.enabled 属性,使 Gateway 能够使用 Nacos 的服务发现功能。同时,配置 spring.cloud.gateway.discovery.locator.route-idiom 属性,指定使用哪种方式生成路由。

    spring.cloud.gateway.discovery.locator.enabled=true
    spring.cloud.gateway.discovery.locator.route-idiom=org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator
    

    4. 在服务下线时,你可以使用 Kubernetes 的 preStop hook,向 Nacos Server 发送下线事件。例如,在 Pod 的配置中添加以下字段:

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    spec:
      containers:
        - name: my-container
          image: my-image
      terminationGracePeriodSeconds: 30
      lifecycle:
        preStop:
          exec:
            command: ["/bin/sh", "-c", "curl -X PUT 'http://nacos-server:8848/nacos/v1/ns/instance?serviceName=my-service&ip=${POD_IP}&port=${SERVER_PORT}&clusterName=DEFAULT&healthy=false'"]
    

    在 preStop hook 中,使用 curl 命令将下线事件发送给 Nacos Server。

    5. 手动触发路由刷新,以使 Spring Cloud Gateway 更新路由信息。你可以创建一个 RefreshController 类,在其中定义一个 POST 请求接口用于触发路由刷新。例如:

    @RestController
    public class RefreshController {
        private final RefreshRoutes refreshRoutes;
    
        public RefreshController(RefreshRoutes refreshRoutes) {
            this.refreshRoutes = refreshRoutes;
        }
    
        @PostMapping("/actuator/gateway/refresh")
        public Mono<Void> refresh() {
            return this.refreshRoutes.refresh();
        }
    }
    

    通过访问 /actuator/gateway/refresh 接口手动触发路由刷新。你可以将该接口暴露给外部,以便在服务下线时手动触发路由刷新。

    2023-07-30 14:36:29
    赞同 展开评论 打赏
  • 北京阿里云ACE会长

    在 Nacos 和 Spring Cloud Gateway 集成中,服务下线并不是一个简单的过程,需要考虑多个方面的因素,包括 Nacos Server 和客户端的配置,以及 Spring Cloud Gateway 的路由刷新机制等。下面给出一个可能的解决方案,供你参考:

    Nacos Server 配置
    在 Nacos Server 的配置文件 application.properties 中,需要开启 nacos.discovery.server-protect-mode.enabled 属性,以防止服务下线后被其他服务误用。例如:

    Copy
    nacos.discovery.server-protect-mode.enabled=true
    Nacos 客户端配置
    在 Nacos 客户端的配置文件中,需要设置 nacos.client.failover-switch 和 nacos.client.updateThreadNum 属性,以保证客户端能够及时地感知到服务下线事件。例如:

    Copy
    nacos.client.failover-switch=true
    nacos.client.updateThreadNum=20
    Spring Cloud Gateway 配置
    在 Spring Cloud Gateway 的配置文件中,需要开启 spring.cloud.gateway.discovery.locator.enabled 属性,以使 Gateway 能够使用 Nacos 的服务发现功能。例如:

    Copy
    spring.cloud.gateway.discovery.locator.enabled=true
    此外,你还需要配置 spring.cloud.gateway.discovery.locator.route-idiom 属性,以指定使用哪种方式生成路由。例如:

    Copy
    spring.cloud.gateway.discovery.locator.route-idiom=org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator
    下线处理
    在服务下线时,你可以使用 Kubernetes 的 preStop hook,将下线事件发送给 Nacos Server。例如:

    dts
    Copy
    apiVersion: v1
    kind: Pod
    metadata:
    name: my-pod
    spec:
    containers:

    - name: my-container
      image: my-image
    

    terminationGracePeriodSeconds: 30

    preStop hook

    lifecycle:
    preStop:
    exec:
    command: ["/bin/sh", "-c", "curl -X PUT 'http://nacos-server:8848/nacos/v1/ns/instance?serviceName=my-service&ip=${POD_IP}&port=${SERVER_PORT}&clusterName=DEFAULT&healthy=false'"]
    在 preStop hook 中,你可以使用 curl 命令将下线事件发送给 Nacos Server。

    路由刷新
    在 Spring Cloud Gateway 中,路由刷新通常由 DiscoveryClientRouteDefinitionLocator 类实现。当服务实例发生变化时,DiscoveryClientRouteDefinitionLocator 会自动更新路由信息。但是,这个更新过程可能会有一定的延迟,因此你可以手动触发路由刷新,以达到更及时的效果。例如:

    angelscript
    Copy
    @RestController
    public class RefreshController {
    private final RefreshRoutes refreshRoutes;

    public RefreshController(RefreshRoutes refreshRoutes) {
    this.refreshRoutes = refreshRoutes;
    }

    @PostMapping("/actuator/gateway/refresh")
    public Mono refresh() {
    return this.refreshRoutes.refresh();
    }
    }
    在这个例子中,我们创建了一个 RefreshController 类,通过 POST 请求触发路由刷新。你可以将该接口暴露给外部,以便在服务下线时手动触发路由刷新。

    2023-07-30 13:13:23
    赞同 展开评论 打赏
  • 意中人就是我呀!

    分析一下gateway的处理逻辑详细日志。此回答整理自钉群“Nacos社区群2”

    2023-07-05 21:41:08
    赞同 展开评论 打赏

阿里云拥有国内全面的云原生产品技术以及大规模的云原生应用实践,通过全面容器化、核心技术互联网化、应用 Serverless 化三大范式,助力制造业企业高效上云,实现系统稳定、应用敏捷智能。拥抱云原生,让创新无处不在。

相关电子书

更多
Nacos架构&原理 立即下载
workshop专场-微服务专场-开发者动手实践营-微服务-使用Nacos进行服务的动态发现和流量调度 立即下载
Nacos 启航,发布第一个版本, 云原生时代助力用户微服务平台建设 立即下载