问题产生背景

使用 Nacos 作为注册中心,gateway 作为网关,网关通过lb的方式进行服务路由,在网关报503服务不可用Service Unavailable。

现象版本

SpringCloud2020.0.3
Nacos 1.4.1

深入问题

是因为 ReactiveLoadBalancerClientFilter 全局过滤器没有加载。官方对其的解释是:

The ReactiveLoadBalancerClientFilter looks for a URI in the exchange attribute named ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR. If the URL has a lb scheme (such as lb://myservice), it uses the Spring Cloud ReactorLoadBalancer to resolve the name (myservice in this example) to an actual host and port and replaces the URI in the same attribute. The unmodified original URL is appended to the list in the ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR attribute. The filter also looks in the ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR attribute to see if it equals lb. If so, the same rules apply.

大概意思是 将请求过来的 URL 是 LB 方式的通过从服务注册中心获取到服务配置,并将原来未修改的 URL 中的 IP 和 端口解析为目标服务的。截取部分 ReactiveLoadBalancerClientFilter 过滤器代码:

URI url = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR);String schemePrefix = exchange.getAttribute(GATEWAY_SCHEME_PREFIX_ATTR);if (url == null || (!"lb".equals(url.getScheme()) && !"lb".equals(schemePrefix))) {// 不是 lb 的方式直接出去return chain.filter(exchange);}// preserve the original urladdOriginalRequestUrl(exchange, url);if (log.isTraceEnabled()) {log.trace(ReactiveLoadBalancerClientFilter.class.getSimpleName() + " url before: " + url);}URI requestUri = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR);String serviceId = requestUri.getHost();Set<LoadBalancerLifecycle> supportedLifecycleProcessors = LoadBalancerLifecycleValidator.getSupportedLifecycleProcessors(clientFactory.getInstances(serviceId, LoadBalancerLifecycle.class),RequestDataContext.class, ResponseData.class, ServiceInstance.class);// 构造 lb 的请求               DefaultRequest<RequestDataContext> lbRequest = new DefaultRequest<>(new RequestDataContext(new RequestData(exchange.getRequest()), getHint(serviceId, loadBalancerProperties.getHint())));// 获取服务中心配置并解析真正的地址return choose(lbRequest, serviceId, supportedLifecycleProcessors).doOnNext(response -> {if (!response.hasServer()) {supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onComplete(new CompletionContext<>(CompletionContext.Status.DISCARD, lbRequest, response)));throw NotFoundException.create(properties.isUse404(), "Unable to find instance for " + url.getHost());}ServiceInstance retrievedInstance = response.getServer();URI uri = exchange.getRequest().getURI();// if the `lb:<scheme>` mechanism was used, use `<scheme>` as the default,// if the loadbalancer doesn't provide one.String overrideScheme = retrievedInstance.isSecure() ? "https" : "http";if (schemePrefix != null) {overrideScheme = url.getScheme();}DelegatingServiceInstance serviceInstance = new DelegatingServiceInstance(retrievedInstance,overrideScheme);URI requestUrl = reconstructURI(serviceInstance, uri);if (log.isTraceEnabled()) {log.trace("LoadBalancerClientFilter url chosen: " + requestUrl);}exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl);exchange.getAttributes().put(GATEWAY_LOADBALANCER_RESPONSE_ATTR, response);supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onStartRequest(lbRequest, response));}).then(chain.filter(exchange)).doOnError(throwable -> supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onComplete(new CompletionContext<ResponseData, ServiceInstance, RequestDataContext>(CompletionContext.Status.FAILED, throwable, lbRequest,exchange.getAttribute(GATEWAY_LOADBALANCER_RESPONSE_ATTR))))).doOnSuccess(aVoid -> supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onComplete(new CompletionContext<ResponseData, ServiceInstance, RequestDataContext>(CompletionContext.Status.SUCCESS, lbRequest,exchange.getAttribute(GATEWAY_LOADBALANCER_RESPONSE_ATTR),new ResponseData(exchange.getResponse(), new RequestData(exchange.getRequest()))))));

其次,取决于是否加载 ReactiveLoadBalancerClientFilter 的是类 GatewayReactiveLoadBalancerClientAutoConfiguration 中关键代码:

@Bean@ConditionalOnBean(LoadBalancerClientFactory.class)@ConditionalOnMissingBean(ReactiveLoadBalancerClientFilter.class)@ConditionalOnEnabledGlobalFilterpublic ReactiveLoadBalancerClientFilter gatewayLoadBalancerClientFilter(LoadBalancerClientFactory clientFactory,GatewayLoadBalancerProperties properties, LoadBalancerProperties loadBalancerProperties) {return new ReactiveLoadBalancerClientFilter(clientFactory, properties, loadBalancerProperties);}

上述源代码中类 LoadBalancerClientFactory 是包 spring-cloud-loadbalancer 的,所以如果缺少则不会注入过滤器 ReactiveLoadBalancerClientFilter

如此简单的解决方案

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>

nacos+gateway服务发现lb路由报503 Service Unavailable相关推荐

  1. 解决gateway使用nacos重启报503 Service Unavailable问题

    问题描述 项目使用spring cloud gateway作为网关,nacos作为微服务注册中心,项目搭建好后正常访问都没问题,但是有个很烦人的小瑕疵: 当某个微服务重启后,通过网关调用这个服务时有时 ...

  2. 网页报503 service unavailable错误怎么解决

    有时候访问某些互联网网页时会出现"503 service unavailable"的错误提示,造成503 error的原因并不止一个,针对不同的情况有不同的解决办法.下面介绍一下面 ...

  3. 《Nacos(2) - 服务发现》

    <Nacos(2) - 服务发现> 提示: 本材料只做个人学习参考,不作为系统的学习流程,请注意识别!!! <Nacos-服务发现> <Nacos(2) - 服务发现&g ...

  4. nacos的服务发现详解

    Nacos源码系列整体栏目 [一]nacos服务注册底层源码详解 [二]nacos服务发现底层源码详解 [三]nacos的心跳机制底层源码详解 [四]nacos配置中心的底层源码详解 nacos的服务 ...

  5. VCSA 上的 vmware-vpxd 服务失败,Web端提示503 服务不可用 (503 Service Unavailable)

    昨晚VCSA碰到一个很诡异的问题: 使用 vSphere Web Client 连接到 vCenter Server Appliance时失败,提示: 503 服务不可用 (503 Service U ...

  6. VCSA访问web报错 503 Service Unavailable

    问题描述: 运行好好的VCSA突然无法访问,web页面报错: 503 Service Unavailable (Failed to connect to endpoint: [[N7Vmacore4H ...

  7. 转)VCSA 6.5重启无法访问,报错“503 Service Unavailable”的解决方法

    转)VCSA 6.5重启无法访问,报错"503 Service Unavailable"的解决方法 1. 问题 重启vcenter,登陆vsphere client,提示 &quo ...

  8. ESXi 6.7 的https服务挂掉处理方法 503 Service Unavailable (Failed to connect to endpoint: [N7Vmacore4Http16Loc

    ESXi 6.7 的https服务挂掉处理方法 503 Service Unavailable (Failed to connect to endpoint: [N7Vmacore4Http16Loc ...

  9. apache php 503,宝塔linux面板 apache网站访问报错503 Service Unavailable解决

    宝塔linux面板 apache网站访问报错: 503 Service Unavailable Service Unavailable The server is temporarily unable ...

最新文章

  1. docker安装kafka消息队列
  2. kset_create_and_add
  3. 老生常谈--GetROProperty,GetTOProperty,SetTOProperty的区别
  4. C#生成CHM文件(应用篇)之代码库编辑器(5)【总结、程序、源代码】
  5. Hystrix配置参数查找方式
  6. mysql数据库密码错误_MySQL数据库经典错误六 数据库密码忘记的问题
  7. 最好浏览器_Windows最好的浏览器!只有你想不到,没有它做不到
  8. 【翻译】IdentityServer4:基于资源的配置
  9. IJCAI 2019 融合角色信息的多样性对话生成
  10. 经典算法归纳(c语言)
  11. Pygame实战之外星人入侵NO.12——点击按钮开始游戏
  12. 柏诚股份冲刺上交所:年营收27.4亿 拟募资4.7亿
  13. python实现王者荣耀游戏框架
  14. html + layui 打开word文档
  15. 川信计算机组装维护,凉山州中学生技能大赛信息技术类竞赛总结
  16. 3、需求调研 - 产品管理系列文章
  17. 又是一年总结时-2007年总结及2008年计划
  18. 奥斯汀大学计算机专业怎么样,美国计算机专业大学排名是怎样的?
  19. MyDockFinder Steam版的新增功能和下载
  20. 浮点数陷阱——小数计算时与主观感觉不相符的异常

热门文章

  1. 测试Python软件是否安装成功
  2. 数据分析 | Pandas 200道练习题,每日10道题,学完必成大神(3)
  3. 你有多享受孤独,你就配有多自由
  4. 找到不偏科的学生(提取学生的所有课程都大于各个课程平均分的学生)
  5. 2022年全球市场外科手术引流设备总体规模、主要生产商、主要地区、产品和应用细分研究报告
  6. 1119-期货要见好就收
  7. php大会2018,2018 INFORMS国际大会
  8. phpstorm重复试用
  9. 【附源码】计算机毕业设计SSM校内考研吧
  10. 延续辉煌:苹果CEO蒂姆·库克,《蒂姆·库克传》书评