一次Apollo Client升级导致的生产404 Not Found问题排查记录

概述

本文记录一次升级Apollo Client组件到1.7.0后遇到的重大生产事故。只想看结论的,可直接快进到文末。实际上,第一句话就是一个结论。

另,本文行文思路事后看起来可行略显思路清晰,实际上排查生产问题时如无头苍蝇,各种猜想各种否定猜想,各种排除各种验证。

另另,回滚服务有时候是一个法宝。

此时已经0点54分,明天醒来再好好整理一下。

事故

某次生产上线一次性发布6个微服务。应用发布后,并没有第一时间收到Prometheus (ERROR类型日志)告警,以为一切正常。

随后在打开某个小程序时,发现小程序打不开。第一时间把问题抛到技术群,随后去生产查看ELK ERROR(再次提到)日志,看到如下日志:

- status 500 reading RemoteOAuthService#smsCodeLogin(SmsCodeLoginDto)
feign.FeignException: status 500 reading RemoteOAuthService#smsCodeLogin(SmsCodeLoginDto)
at feign.FeignException.errorStatus(FeignException.java:78)
at feign.codec.ErrorDecoder$Default.decode(ErrorDecoder.java:93)
at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:149)
at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:78)
at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:103)
at com.aba.enduser.service.impl.UserLoginServiceImpl.smsCodeLogin(UserLoginServiceImpl.java:181)
at org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstMethodsInter.intercept(InstMethodsInter.java:86)
at com.aba.enduser.controller.LoginController.smsCodeLogin(LoginController.java)

事实上后来的排查证明与上面的报错无关。

与此同时,技术群前端同学排查到如下截图 404 NOT_FOUND异常:
在这里插入图片描述
看接口,以及上面报错日志,第一时间怀疑是OAuth服务(在此次发布清单6个服务中)有问题,于是回滚此服务。

但是,在回滚此服务后,小程序依旧有问题,404 NOT_FOUND异常依旧存在。

继续排查剩余5个发布应用清单,将其余4个服务排除后,回滚gateway-open服务。小程序打开正常。

反思

通过GitLab提供的Repository-Compare功能,即代码对比,本次发布版本Tag和发布前线上运行的版本Tag,并没有什么显著性问题(因为此次发布有2个问题,事后结论)看这个版本对比,也看不出啥问题。

在这里插入图片描述

排查

在这里插入图片描述

在这里插入图片描述

为何某些服务需要额外引入apollo-openapi?
因为如下代码:

@SpringBootApplication
@EnableApolloConfig(value = {"commons"})
public class OpenGatewayApplication {
    @Value("${apollo.portalUrl:http://172.111.222.33:8070}")
    private String portalUrl;
    @Value("${apollo.portal.token:717376485f69df0d}")
    private String token;

    @Bean
    public ApolloOpenApiClient apolloOpenApiClient() {
        return ApolloOpenApiClient.newBuilder()
                .withPortalUrl(portalUrl)
                .withToken(token)
                .build();
    }
}

在这里插入图片描述
为什么apollo-core版本有区别,得看pom文件里先引入apollo-client还是先引入apollo-openapi

c.ctrip.framework.apollo.internals.AbstractConfigRepository | trySync | 29 | - Sync config failed, will retry. Repository class com.ctrip.framework.apollo.internals.RemoteConfigRepository, reason: 'java.lang.String com.ctrip.framework.foundation.spi.provider.ApplicationProvider.getAccessKeySecret()'
Schedule long polling refresh failed [Cause: com.ctrip.framework.foundation.spi.provider.ApplicationProvider.getAccessKeySecret()Ljava/lang/String;]
Sync config from upstream repository class com.ctrip.framework.apollo.internals.RemoteConfigRepository failed, reason: com.ctrip.framework.foundation.spi.provider.ApplicationProvider.getAccessKeySecret()Ljava/lang/String;
Init Apollo Local Config failed - namespace: commons, reason: Load config from local config failed! [Cause: Cannot read from local cache file /opt/data/App/config-cache/App+default+commons.properties].
Could not load config for namespace commons from Apollo, please check whether the configs are released in Apollo! Return default value now!

借助于开源组件KubernetesFileBrowser,我们可以拿到kubernetes环境下pod里的文件。

有问题的版本Tag:
在这里插入图片描述
没有问题的版本Tag:
在这里插入图片描述

@EnableApolloConfig

这个看一下EnableApolloConfig.java源码就明白:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({ApolloConfigRegistrar.class})
public @interface EnableApolloConfig {
    String[] value() default {"application"};
    int order() default Integer.MAX_VALUE;
}

也就意味着,除了在本地配置文件里指定需要引用的namespace,我还可以在@注解里指定namespace,像这样:

@EnableApolloConfig(value = {"commons", "gateway-open"})

配置文件:

#apollo
app:
  id: App
apollo:
  meta: http://apollo.aaabbbccc.com:8080
  bootstrap:
    enabled: true
    namespaces: commons,gateway-open

升级Apollo Client背景

后端微服务架构体系里将近30个微服务,所有的请求流量转发都是由gateway服务来承载。另外,考虑到我们的产品有不同的用户体系,比如C端用户,三方对接平台或商户等。基于这两点,我们有2个gateway网关服务,一个是gateway-c服务,用于服务C端用户的绝大多数请求。另一个是gateway-open服务,用于服务三方等渠道或商户的请求。

另外,作为一个背景知识,gateway网关服务里面的配置几乎都是路由转发规则配置,类似于:

spring.cloud.gateway.routes[22].id = enduser-provider
spring.cloud.gateway.routes[22].uri = lb://enduser-provider
spring.cloud.gateway.routes[22].predicates[0] = Path=/api/open/user/**
spring.cloud.gateway.routes[22].filters[0] = StripPrefix=1
spring.cloud.gateway.routes[22].filters[1] = RequestLogFilter
spring.cloud.gateway.routes[22].filters[2] = BlockListFilter
spring.cloud.gateway.routes[22].filters[3] = TokenFilter
spring.cloud.gateway.routes[22].filters[4] = SignVerifyFilter
spring.cloud.gateway.routes[22].filters[5] = HeaderCheckNullFilter

当业务场景变得越来越复杂,微服务数量越来越多,或随着一个个接口的上线或下线,或者某个符合predicates断言规则接口前端(含H5、小程序、iOS、Android等,即所谓大前端概念),适配增加各种不同场景的Filter,等等原因,导致gateway网关服务的路由转发规则变得臃肿复杂难以理解。

此为背景。

某次在优化gateway-c服务的配置后,从Sublime Text复制配置到Apollo,准备发布更改时,才发现不对劲,这次调整怎么有这么多啊。立马发现,好家伙,手残点错namespace。把本来应该变更到gateway-c的配置复制到gateway-open。

ok。我要回滚,我当然不可能点发布。但是,当我点击回滚时,弹窗提示的版本号明显不对,一个是目前生产的版本,一个是上一次的版本,类似于下图(非事发时截图):
在这里插入图片描述
仔细分析,我想要的其实并不是【回滚】功能,因为我的配置变更还未提交(发布)。再想了想,模模糊糊有了点头绪(虽然此处行文可能看起来显得思路清晰得一逼),此处Apollo版本发布概念实际上就是Git的版本控制概念。

配置有变更,等价于Git里的modified;
配置发布,相当于Git里的commit;
配置回滚,可类比于Git里的revert;
配置撤销,可类比于Git里的restore。
在这里插入图片描述
带着Apollo、回滚、撤销等关键词找到官方GitHub issue,看到:
在这里插入图片描述
点击Apollo-PR-2952,发现对应着Milestone 1.7.0。

因为之前了解过我们使用的生产环境Apollo UI(配置可视化管理端)版本号为:1.4.0,测试环境Apollo UI版本号为:1.7.0。

版本号正好匹配,于是打开测试环境Apollo UI,发现确实有这个【撤销配置】的入口:
在这里插入图片描述
作为对比,放一张生产环境的截图:
在这里插入图片描述
另外我们在pom文件里使用的apollo-client版本号为1.5.0,这个当然不区分测试和生产环境。

也就是说,apollo-client-1.5.0版本与apollo server(UI)1.7.0版本可以兼容,即测试环境就是这种情况,没有(发现)问题。

于是:升级生产Apollo Server版本到1.7.0!

PS:Apollo Server端成功升级后,我们应用侧,apollo-client还是1.5.0,两者完美兼容运行一段时间后。

结论

应用pom.xml文件先引入apollo-openapi-1.5.0,后引入apollo-client-1.7.0。先删除本地缓存下来的Apollo配置properties文件,应用启动时会有很多WARN日志,即上面提到的5类WARN日志,不影响应用启动成功。

<dependency>
	<groupId>com.ctrip.framework.apollo</groupId>
    <artifactId>apollo-openapi</artifactId>
    <version>1.5.0</version>
</dependency>
<dependency>
    <groupId>com.ctrip.framework.apollo</groupId>
    <artifactId>apollo-client</artifactId>
    <version>1.7.0</version>
</dependency>

事实上,请求http://localhost:8848/health/check
在这里插入图片描述
正好对应着健康健康endpoint端点:

@GetMapping({"/health/check"})
public String heathCheck() {
    return "OK";
}

但是,后面还是会持续打印WARN日志。

并且!
本地并没有缓存此应用需要的几个Apollo配置文件!!
后面如果要通过此服务做请求转发,拿不到配置路由规则,更谈何URL路径规则转发呢!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/202232.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用STM32微控制器实现烟雾传感器的接口和数据处理

烟雾传感器是常见的安全检测装置&#xff0c;通过检测空气中的烟雾浓度来提醒用户有潜在的火灾风险。本文将介绍如何使用STM32微控制器来实现烟雾传感器的接口和数据处理。包括硬件连接、采集模拟信号、数字信号处理和报警策略等方面。同时&#xff0c;给出相应的代码示例。 一…

【Android知识笔记】架构专题(一)

什么是 MVC 其实我们日常开发中的Activity,Fragment和XML界面就相当于是一个MVC的架构模式,但往往Activity中需要处理绑定UI,用户交互,以及数据处理。 这种开发方式的缺点就是业务量复杂的时候一个Activity过于臃肿。但是页面结构不复杂的情况下使用这种方式就会显得很简…

基于Java SSM框架实现KTV点歌系统项目【项目源码+论文说明】

基于java的SSM框架实现KTV点歌系统演示 摘要 本论文主要论述了如何使用JAVA语言开发一个KTV点歌系统&#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述KTV点歌系…

Linux基础项目开发1:量产工具——输入系统(三)

前言&#xff1a; 前面我们已经实现了显示系统&#xff0c;现在我们来实现输入系统&#xff0c;与显示系统类似&#xff0c;下面让我们一起来对输入系统进行学习搭建吧 目录 一、数据结构抽象 1. 数据本身 2. 设备本身&#xff1a; 3. input_manager.h 二、触摸屏编程 to…

云时空社会化商业 ERP 系统 gpy 文件上传漏洞复现

0x01 产品简介 时空云社会化商业ERP&#xff08;简称时空云ERP&#xff09; &#xff0c;该产品采用JAVA语言和Oracle数据库&#xff0c; 融合用友软件的先进管理理念&#xff0c;汇集各医药企业特色管理需求&#xff0c;通过规范各个流通环节从而提高企业竞争力、降低人员成本…

VSCODE 在新窗口中打开

使用VS习惯了&#xff0c;经常在新窗口中打开查看 但是VSCODE&#xff0c;无法拖动标签到一个新窗口中&#xff0c;一直以为没这个功能 后来发现 使用快捷健 ctlk,o 可以将标签页在新窗口中打开&#xff0c;虽然不如vsstudio方便&#xff0c;不过也可实现在新窗口打开的功能…

【动态规划】LeetCode2552:优化了6版的1324模式

本文涉及的基础知识点 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 动态规划 本题其它解法 C前缀和算法的应用&#xff1a;统计上升四元组 类似题解法 包括题目及代码C二分查找算法&#xff1a;132 模式解法一枚举3C二分查找算法&am…

CSAPP bomb_lab:phase_5

phase_5的汇编代码 0x0000000000401062 <0>: push %rbx0x0000000000401063 <1>: sub $0x20,%rsp0x0000000000401067 <5>: mov %rdi,%rbx0x000000000040106a <8>: mov %fs:0x28,%rax0x0000000000401073 <17>: mov …

hql面试题之字符串使用split分割,并选择其中的一部分字段的问题

版本&#xff1a;20231109 1.题目&#xff1a; 有两张表,a表有id和abstringr两个字段&#xff0c;b表也有id和bstr两个字段&#xff0c;具体如下 A表&#xff1a; 1abc,bcd,cdf2123,456,789 B表: 1acddef2123456 在a表的abstring字段中用‘,’分割&#xff0c;并取出前两…

sqli-labs靶场详解(less32-less37)

宽字节注入 原理在下方 目录 less-32 less-33 less-34 less-35 less-36 less-37 less-32 正常页面 ?id1 下面有提示 获取到了Hint: The Query String you input is escaped as : 1\ ?id1 看来是把参数中的非法字符就加上了转义 从而在数据库中只能把单引号当成普通的字…

Go 从编译到执行

一、Go运行编译简介 Go语言&#xff08;也称为Golang&#xff09;自从2009年由Google发布以来&#xff0c;已成为现代软件开发中不可或缺的一部分。设计者Rob Pike, Ken Thompson和Robert Griesemer致力于解决多核处理器、网络系统和大型代码库所引发的现实世界编程问题。我们…

TA-Lib学习研究笔记——Overlap Studies(二)上

TA-Lib学习研究笔记——Overlap Studies&#xff08;二&#xff09; 1. Overlap Studies 指标 [BBANDS, DEMA, EMA, HT_TRENDLINE, KAMA, MA, MAMA, MAVP, MIDPOINT, MIDPRICE, SAR, SAREXT, SMA, T3, TEMA, TRIMA, WMA]2.数据准备 get_data函数参数&#xff08;代码&#x…

msyql迁移到mongodb

关系型数据库迁移到mongodb的理由 高并发需求&#xff0c;关系型数据库不容易扩展 快速迭代 灵活的json模式 大数据量需求 应用迁移难度&#xff1a; 关系型到关系 oracle-》mysql oracle -》 postgresql 关系到文档- oracle -》 mongodb 需要考虑&#xff1a; 总体架构&#…

阿里云Windows server2016 安装Docker

阿里云Windows server2016 安装Docker 1 软件环境介绍2 下载更新2.1 windowsR 输入sconfig2.2 下载最新版的安装包&#xff0c;安装并重启2.3 下载并安装更新2.4 以管理员方式运行powershell2.5 将Tls修改成二级2.6 安装NuGet服务2.7 安装docker模块2.7 安装 docker包 32.8 查看…

Ajax的使用方法

1,什么是Ajax&#xff1f; Ajax&#xff08;异步Javascript和XML&#xff09;&#xff0c;是指一种创建交互式网页应用的网页开发技术。 2&#xff0c;Ajax的作用 Ajax可以使网页实现异步更新----即在不更新整个页面的情况下实现对某一部分进行更新。 简单来说Ajax就是用于连接…

顶级大厂Quora如何优化数据库性能?

Quora 的流量涉及大量阅读而非写入&#xff0c;一直致力于优化读和数据量而非写。 0 数据库负载的主要部分 读取数据量写入 1 优化读取 1.1 不同类型的读需要不同优化 ① 复杂查询&#xff0c;如连接、聚合等 在查询计数已成为问题的情况下&#xff0c;它们在另一个表中构…

HT for Web (Hightopo) 使用心得(5)- 动画的实现

其实&#xff0c;在 HT for Web 中&#xff0c;有多种手段可以用来实现动画。我们这里仍然用直升机为例&#xff0c;只是更换了场景。增加了巡游过程。 使用 HT 开发的一个简单网页直升机巡逻动画&#xff08;Hightopo 使用心得&#xff08;5&#xff09;&#xff09; 这里主…

纯js实现录屏并保存视频到本地的尝试

前言&#xff1a;先了解下&#xff1a;navigator.mediaDevices&#xff0c;mediaDevices 是 Navigator 只读属性&#xff0c;返回一个 MediaDevices 对象&#xff0c;该对象可提供对相机和麦克风等媒体输入设备的连接访问&#xff0c;也包括屏幕共享。 const media navigator…

【brew】Mac上安装vue3

先安装node。 这里我从其他博客找的方案&#xff0c;原始脚本下载太慢了。 cnpm的安装&#xff1a; 让npm更快一点。 npm install -g cnpm --registryhttps://registry.npm.taobao.org安装vue脚手架 2.0版本&#xff1a;sudo npm install -g vue-cli 3.0版本&#xff1a; sud…

2023.11.26使用opencv调节图片亮度

2023.11.26使用opencv调节图片亮度 测试一些opencv对图片的处理效果&#xff0c;方法比较简单&#xff0c;找出所有像素点&#xff0c;然后将RGB三色的亮度分别进行调节即可&#xff0c;同类可以进行像素级的处理。测试结果和项目代码如下&#xff1a; 使用OpenCV调节图拍亮…