订单同步工程标准化改造事记

提及来,也是一段比较有挑战有压力的经历。作完以后,有一种云淡风轻的感受,故记之。

html

缘起

周二下午,忽报:QA 环境下单以后,订单搜索不出来了。java

略排查,发现订单记录并未同步到 ES 索引里。进一步发现,订单同步工程 S 虽然进程还在,但已经再也不处理消息了。昨天由于一个项目的需求才测试过 QA 环境订单同步无问题,上午也没动静,怎么下午就忽然报问题了呢?mysql

很快联想到,前两日,框架层发了通告:再也不为使用了 3.2.x 如下 dubbo 版本的应用提供自动注册 dubbo 服务的能力。极可能是 S dubbo 版本太低,没法注册和访问 dubbo 服务,没法进行订单同步,进而影响订单搜索和详情,严重阻塞了项目的测试。订单是核心嘛~~react

因而我将 pom 里的 dubbo 版本改为了最新版本。可仍是不行。要找框架同窗一块儿排查下了。

git

旧世界

ClassVisitor

框架同窗东顺说,早上貌似改过 zan 版本,也许是这个致使的。因而,我请求降回到原来的版本,先解决问题再说。sadly,即便降回到原来的版本进行部署, S 的服务依然起不来。退路已断。面试

框架同窗子杰的第一个想法,是在本地启动调试。由于这样方便且高效。不过 S 应用已经好久没有在本地启动。并且 S 依赖比较多,在本地恐怕很难启动。sql

报 ClassVisitor should be a interface , not a class 。此类错误一般是 jar 冲突致使。所以,我在工程里搜索了下 ClassVisitor ,果真发现有两个,一个是接口,一个是类。 看来要排掉那个有类 ClassVisitor 的 jar 包。apache

<dependency>
            <groupId>com.youzan.platform</groupId>
            <artifactId>bootstrap</artifactId>
            <version>3.2.7.3-RELEASE</version>
            <exclusions>
                <exclusion>
                    <groupId>org.ow2.asm</groupId>
                    <artifactId>asm</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

排掉以后,就再也不报这个错了。 然而, S 依然不处理消息。json

一边是测试同窗在催促,一边是毫无头绪。内心有些急,可一时也想不到如何解决。子杰指望本地调试,可本地启动老是报奇怪的 groovy 不兼容错误。调了一夜,终于把这个问题解决了。 但 S 依然不处理消息。

bootstrap

补丁

周三早上,继续战斗。子杰发了一段配置,让放在 S 工程的 XML 配置里。说这段配置是用来注册 dubbo 服务的。 加入以后,报错: cause: Could not initialize class com.coreos.jetcd.api.KVGrpc, dubbo version: 1.0.1-SNAPSHOT, current host: x.x.x.x

子杰看了,开心地说,这个错误以前见过,可能 protobuf 版本冲突了。 离成功不远了。

<dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-server</artifactId>
            <version>1.2.6</version>
            <exclusions>
                <exclusion>
                    <groupId>com.google.protobuf</groupId>
                    <artifactId>protobuf-java</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

排除 protobuf-java 包以后,终于能够起来了。 验证了下,订单同步 OK 了。 松了一口气。

间歇性跪

才没轻松多久, 又跪了。又跪了。又跪了。又跪了。 测试同窗又来催了。

沟通

在这种情形下,发生一点小“纠纷”老是可能的。有一次,在吃饭的时候,S 跪了。 测试同窗群里喊:进度如何了,找到根本缘由了么? 内心有点恼火:做为开发,我确定要尽职尽责尽早排查和解决问题;但是你也不能只是催,在这样尴尬的时刻,能够支援一下嘛。 不过,你们都很通情达理,我提供了“临时启动服务”的方法,测试同窗就帮忙先启动服务了。

反思一下,测试同窗的作法也是合情合理的,由于他们要负责保障更大域范围的环境稳定,须要知道进度和缘由。解决棘手问题时,同步进度和缘由也是很重要的,内心应该装下更大的世界。此外,若我能及早同步“临时解决方案”,让测试同窗知道怎么解决,也不会有这样的“纠纷”。有话好好说,总能找到更柔和的方式来解决。

因而我在群里回复:他们的担忧和考虑是合理的,且已经快接近成功了。稍安。其实我也不知道距离成功还有多远。

蛛丝马迹

排查问题,只能从错误日志里寻找一切蛛丝马迹。子杰找了一段 JVMExitHook 的代码,加在启动的时候,这样方便在进程退出的时候,打印一些线索。 不过,这招没起效果,打印出的信息彷佛没有派上用场。

同时,我也在仔细观察日志里出现的各类细微错误。不能放过一个嫌疑份子。确认了有四种可能的影响因素:1. 应用 M 跪; 2. Hbase 读写失败; 3. 脏数据; 4. 底层 jar 不兼容,致使某种隐藏的问题。

M跪

又跪了。发现 S 有个任务访问 M 服务报错,登陆机器,发现 M 服务跪了。重启 M 。 过了一段时间,S 又跪了,M 服务也跪了。会不会受了这个服务的影响呢 ? 将 M 服务所涉及的任务暂时禁用了。将 M 禁用后,S 彷佛就没有跪过了。

M 报错的缘由,是由于零售同窗将一个接口迁移到了新的工程,也就是说,原来的接口下线了。 S 去注册这个接口的服务的时候找不到。

HBase

发现有一些 HBase 写入失败。咨询 HBase 同窗,是由于 QA 集群运行了一些离线任务,有时资源比较紧张。 虽然有疑点,但不太可能致使 S 跪。

脏数据

在排查过程当中,也发现有些脏数据,致使 NSQ 消息处理失败。脏数据可能把一个任务搞跪,不过 S 里有不少任务,要把 S 跪掉,还须要一些“道行” 吧。

隐藏的坑

只是猜想,但确实是比较大的嫌疑。 由于前三者都是局部的影响,不太可能将 S 整个搞跪掉,但这个多是全局的影响。好比说,某个 jar 版本的组件,与另外一个组件交互,可能产生 bug , 吃内存,致使内存 OOM 。只是猜想。

暂时维稳

子杰有了新的发现。从 dmsg 日志里看到,S 独占内存过多,Linux 内核将 S 的 java 进程 kill 掉了。调整了堆内存从 6.5G 到 4G,而后运行了一成天都没有跪。

java invoked oom-killer: gfp_mask=0x201da, order=0, oom_adj=0, oom_score_adj=0
java cpuset=/ mems_allowed=0
Pid: 4288, comm: java Not tainted 2.6.32-754.9.1.el6.x86_64 #1
[ 4286] 602 4286 3321904 1898888 2 0 0 java
Out of memory: Kill process 4286 (java) score 929 or sacrifice child
Killed process 4286, UID 602, (java) total-vm:13287616kB, anon-rss:7595528kB, file-rss:24kB


新工程

QA 环境终于能够暂时安静一会了。 但是,生产环境如何解决呢?

S 承载着公司亿级订单的同步,显然不能容忍用打补丁的方式来解决(况且这个补丁很恶心,会埋很大的坑),并且也没法接入 aladdin ,自动升级 jar 版本。 所以, QA 的作法,只能暂时维稳,不能用做生产环境的解决方案。

咨询子杰 ,是否有办法能够以最小成原本改造 S 应用 ? 回答:使用 youzan-boot 标准化工程。但是要改形成 youzan-boot 工程,势必改动很大,整个工程结构都变了,部署方式也变了,上线风险是很大的。对于 S 这样的应用,稍有不慎,就是 P1 或 P0 故障。

进退两难。

由于本身不太熟悉应用打包和部署的方式,有点畏难。但想了想,本质上就是把应用里的任务想办法启动起来。绝大部分代码都是能够复用的,只须要在新的工程结构中,将原来的启动代码嵌入进去。想到这里,有了一些信心,决定采用新工程的方式来解决这个问题。

new出了null

根据子杰提供的文档及界面,很快创建了新的标准化脚手架工程。接着,将原工程的代码拷贝到新的工程里,并在启动的入口,将原来启动任务的类的方法添加进去。

我是一个不解决主要问题寝食难安的人。深夜,继续。部署后,初始化任务出错。只好加日志,看看哪里抛异常了。不加没关系,一加he一跳。
`Task task = new Task(); logger.info("task:{}", task) , 居然打出了个 null !

new 出了个 null ? 百思不得其解。想着,恐怕又没进展了, 打算睡觉了。正准备睡觉的时候,忽然灵光一闪,去查看了下 toString 方法,是打印 task 实例中的 taskConfig 的,而此时 taskConfig 做为入参尚未设置到 task 中,所以打印为 null 。真是脑经急转弯啊。 遇到的每一个问题,都是一道面试题。):

看来,在程序的世界里,一切奇怪的事情,总有一个合理的原因。 联想到前不久的 “奇怪之事总有原因:订单状态对比不一致问题排查” ,有所领会。

环境变量引用改造

继续排查为何 task 没有正确初始化。对比原工程,发现 task 是一个声明为 prototype 的类,所引用的组件,也是 prototype 的。新老工程没有差别。

从日志里能够看到,环境变量读取到应用里,依然是占位符,并无正确地被替换。 原工程为了灵活,使用了 yaml 文件来配置环境变量,并在代码里作了遍历,这样,若是须要增长新的环境变量,只须要在 yaml 增长一项便可。

<bean id="mysqlDataSource" class="com.youzan.trade.sync.v2.EnvConfigLoader" init-method="init">
     <constructor-arg value="config/config.yaml"/>
</bean>

@Slf4j
public class EnvConfigLoader {

    private final String dir;

    public EnvConfigLoader(String dir) {
        this.dir = dir;
    }

    public void init() {
        try {
            String content =
                    StreamUtils.copyToString((InputStream) this.getClass().getClassLoader().getResource(dir).getContent(), Charset.forName("utf-8"));
            YamlReader reader = new YamlReader(content);

            Object object = reader.read();
            JSONObject config = JSONObject.parseObject(JSONObject.toJSONString(object));
            for (String key : config.keySet()) {
                Constants.urlMap.put(key, config.getString(key));
            }
        } catch (Exception e) {
            throw new RuntimeException("load config failed:" +dir, e);
        }
        log.info("load config success ,config is :{}", JsonUtils.toJson(Constants.urlMap));
    }
}

config/config.yaml 文件里的配置, 好比:
zk: ${hbase.zookeeper.address}

改形成新工程以后,因为 yaml 文件里的引用变量好比 ${hbase.zookeeper.address} 已经没法读取,所以,须要改形成新的方式读取环境变量。

考虑到 S 的任务所使用到的环境依赖基本已经齐全,很小几率会再添加一项。所以,打算改形成不那么灵活但足够清晰的方式。直接将 zk 做为 EnvConfigLoader 的实例变量注入,省去了读 yaml 文件的步骤。

@Slf4j
public class EnvConfigLoader {

    @Setter
    private String zk;

    public void init() {
        Constants.urlMap.put("zk", zk);
        log.info("load config success , config is :{}", JsonUtils.toJson(Constants.urlMap));
    }
}

折腾到凌晨一点,终于可以看到,任务在正确消费消息了。阶段性的重大进展! 奇怪的是,消息消费的任务日志没有打出来 。先睡觉吧。

日志

次日一大早,就去找东顺排查日志为何没找到。东顺在一个 home_IS_UNDEFINED 的目录下找到了消息消费的日志文件。 日志路径的配置有问题。 按照他的指点,导入了标准的 XML 日志配置,在指望的目录打印了任务处理日志。略开怀。

可错误日志没打出来。这也是要命的事情。在发布线上的过程当中,若没有错误日志的提醒,那是冒着枪林弹雨的冲锋,是容易中弹身亡的。

想起东顺以前提到:能够把原来的日志配置文件直接拷贝到新工程的配置文件里。错误日志终于打出来了! 开心 !~~ 又前进了一步,more closed to success。

打印日志到本地磁盘以后,还要上报到公司内部的日志平台上,方便查看多台服务器的日志。照葫芦画瓢,折腾了下,搞定了。喜。

简化

至此,新工程的总体和主要部分没问题了。还须要作一些简化,好比去掉一些无用的模块和文件,优化 pom 里的 jar 引用等,保持工程的简洁与干净,没有赘余。

需求支持

在新工程发布以前,有两个项目已经快接近尾声,须要在 trade-sync 作一个改动支持。一个改动很小,一个改动略大。若是等 trade-sync 改造上线以后再上线,恐怕这两个项目都要被延误。怎么办呢 ?

决定: 先在老的系统上改,随老的系统先发布; 而后再迁移到新的工程里,这些改动所涉及的任务从新再回归一遍。有个担忧,若是把这些改动复制到新的工程里,恐怕容易有遗漏。所幸,使用 git merge 命令,能够很方便地将改动从老的上面挪到新的工程上。


发布准备

接下来就要考虑发布了。

CR

工程改动太多了,有点失控的感受。 在发布以前,找几位有经验的同窗帮忙一块儿 check 下是明智的选择,也是必经的流程。一位是一直帮我排查 QA 同步问题的子杰同窗, 一位是见识比较广能力不错的王立同窗,由于他做为后端同窗解决了react 容器部署的问题,让 S 的新界面又从新问世啦!靠谱,厉害!还有一位是个人有伴水王,也是很踏实的。


业务回归

CR 的同时,也要验证这个工程是否能保证原有的任务都能正常进行。

前面谈到, 订单同步使得搜索和详情的任务都是 OK 的,也就是最重要的任务没问题;

有些任务是与第三方交互的,在 QA 是没法验证的。 好在:这个工程里绝大部分都是访问 DB, ES, HBase 的组件,绝大多数的业务逻辑都在配置的任务里。能够说是“将基础技术设施与业务逻辑相分离而实现配置化“的典范作法。所以,从基本层面看,只要验证部分任务, 覆盖到全部的组件类别, 就能够看做是验证了全部任务。

既能够把这种作法当作一种巧妙的方式,也能够看做是某种取巧和偷懒。这种方式仍是会有漏网之鱼。

虚惊一场

使用新工程部署以后,一直在观察中,没有跪过。 有点安心了。 在发布前晚,忽然发现: 跪掉了。 天 ! 难道还有什么细坑 ?又得继续观察和排查细坑了 ! 恐怕要延期发布了。

幸亏,当天早上, 有伴告诉我,他重启过一次,运维同窗也重启过一次,可是没启动成功。 我当即想到,可能他们是用老的 zan 版本启动的, 由于不兼容致使失败。我用 zan 的新版本启动是 OK 的。

很快确认了这一点, 虚惊一场。

庙算几何

孙子曰:“夫未战而庙算胜者,得算多也,未战而庙算不胜者,得算少也;多算胜,少算不胜,而况于无算呼?”

距离计划发布时间只有几个小时了。 这个工程的发布胜算在 92% 以上, 有 8% 的不肯定性。胜算以下:

  1. 最主要的订单同步任务是没有问题的;
  2. 十几个的任务及子路径,我验证了大部分是能够正确输出的;
  3. 组件代码无改动,只是工程结构变了;
  4. 在 QA 和 预发环境运行稳定。

不肯定性以下:

  1. 有一个任务是外部交互的,没法验证; 四个任务是边缘业务,不太好构造测试用例; 但这些任务所使用的组件,都在其余被验证过的任务中使用过了,所以,理论上也应该是间接被验证了;实际上是有点懒,结果是受了惩罚。
  2. 引入了 youzan-boot 的包,还有之前工程里的 jar 包,可能存在一些细微的不兼容的坑,未被发现。

无论怎样, 胜算仍是很大的。在发布的时候,再细心一些, 应该不会出什么问题。

决战时刻

预发的启示

在预发部署的时候,发现新的进程并无正常起来,必须先手动 kill 掉原来的进程,再部署新的工程,才能让新进程正常启动和运行服务。 这一点尤其重要, 不然很容易出问题。

若是能对预发出现的问题敏锐地感知,有时预发的问题真的是神明的指示。 前不久作过的一个项目中,须要作一些交易配置的变动。在预发验证拼团订单的时候,订单状态没有正常流转,经排查日志发现:预发的请求居然发到线上去了! 联系营销同窗得知,订单的后续通知,取决于接收最后一个参团订单的请求的机器所处的环境。好比说吧,拼团发起者的下单请求在 T1 机器, 拼团参团者的下单请求在 T2 机器上。 机器 T1 切换到了新的配置, T2 尚未。 此时, T2 将向营销发送消息,营销处理消息完成后,向交易机器 T3 发送回送消息。若是 T3 尚未切新配置,就可能致使走不下去。 发现这个问题后, 仔细思考了下,发如今 下午正常发布窗口发布是有风险的。由于若是正好在那个时间段有不少拼团活动,势必会致使不少拼团订单的状态流转有问题,不只会对商家的交易有影响,还要应对后续复杂麻烦的数据修复。 想一想,仍是辛苦一点,凌晨发布好了, 此时拼团活动极少, 且有更多时间来验证项目改动和回归业务。

通过沟通,决定在凌晨发布。安全上线。

发布文档

因为要赶在新进程起来以前手动 kill 老进程,这个时机得把握好, 为了不误操做,临阵手忙脚乱,所以,必要写个发布文档, 写清楚每个步骤要执行的命令, 在真正发布的时候,只要简单的复制粘贴就能够了。

原本想把这些命令写成一个脚本,但是 kill 老进程的执行要切换用户,一时间没有太多时间调试这个,且要执行的批量命令也很少, 所以,仍是直接复制粘贴了。好在发布的时候,机器的编号是逐渐递增的,能够预测每批次发哪几台机器, 这就容易多了:只要在每批次发布以前,先 kill 掉将要发布的机器的老进程便可。

会影响线上服务么? 因为还有其余服务器在处理消息,且凌晨的消息量极少,所以 kill 几台机器的进程不会对线上服务有影响。

单测

写好发布文档以后,已经 十一点半了。 该提发布申请了。

在提发布申请以前,得先运行并单测所有经过。到单测平台上运行了下,发现报错: groovy 与 spock-core 的版本不兼容。

郁闷了。在本地运行是 OK 的,为啥在这个节骨眼报错了。 看了下工程的配置,仍是比较老的版本。想一想能够升级到较新的版本,对任务运行应该没有影响。因而从核心工程拷贝了更新的版本号,并修复了一个单测文件。

为了简单,根据报错只把 groovy 的版本升到了 2.0.1 , —— 给本身买了个坑。在程序的世界里,因果命中注定。

小插曲

忽然想到, 除了 S ,还有一个附属应用 s, 代码与 S 相同 ,但只运行对比任务。嗯, 这个应用也要发布, 也在预发验证下。

我在 QA 也部署了应用 s ,可启动日志显示:访问交易配置表报错了:用户名被拒绝。这是怎么回事呢? 在发布以前,有一些配置变动我提交了。我想到应该是运维同窗更新过,不会有问题。 QA 无法验证, 只好上预发验证了。

因而,我在预发也部署了 s 应用。启动日志没报错,可也没消费日志。想了想,也许以前就没有吧。 应该是 OK 的,就作发布前的准备去了。

忽然被拉到一个群里,是预发交易配置库访问出错排查。因为我集中精力在准备发布,所以对这个并未投以太多关注。但群里好像说是比较严重的事情,坚持要查明白,彷佛说我故意配错了用户名和密码,以至于访问到错误的地方,险些形成安全事故,还连累了不少同窗耗费时间来查问题。可我只是提交了被别人改动的配置(而且我相信是运维同窗改动且应该是正确的),并没作出格的事情。难道,我一不留神就犯下了错误 ?

事情原委是:DBA 同窗杨大侠监控到交易配置库有大量访问错误,并且还来自于不一样的机房,认为这是很大的不合理。初步排查到,访问出错来自于预发的 s 应用。这有什么关联呢? 我一时也有点懵逼,仿佛处于云山雾绕。

####&amp;####

我提交了发布申请,开始发布 s 应用。未料,线上也报错了。这可奇怪了,我对比了下 S 与 s 的 交易配置表的用户名和密码,彻底同样的啊 ! 在 跳板机上用 mysql 链接了下,也是通的; S 在预发部署也没报错,这可奇怪了。

杨大侠提醒: DB 链接的 jdbcURL中有 &amp; 这样的字符。 我忽然想到了, 在 QA 遇到过这个问题,由于高版本的 mysql 不支持这个老的语法,须要将这个变成 & 自己。

哪里还藏有 &amp; 这个字符呢 ? 从新再check 了下 s 应用的配置。 发现,交易配置表的配置有两处,其中一处是彻底同样的,但还有一处。 重复出现的 DB 配置,真坑啊!

修改以后,就没有报错了。DBA 监控也没有报错了。 排查这个错误耗费了将近三个小时。发布完 s 应用后,已经三点了。

Bean没有找到

S 应用的发布彷佛顺利一些。发了几台,没有报 DB 访问错误,或者其余奇怪的错误。

四点半了, 刚发了几台机器,发现有错误: RefundBizNsqInput 的 bean 找不到,任务启动报错。这个任务是消费退款消息,写入退款数据,供订单导出来计算退款状态及金额的。若是这个数据有误,可能会影响订单状态的展现,误导商家发货。

心里有点崩溃。 这可怎么办呢? 继续发布完成 ? 这样会致使这个任务大量报错, 退款消息没法消费, 引发上述问题, 形成故障; 若是暂停发布,等待下午发布,一则如今新老混布有较大风险,二则下午发布风险更大; 从新发布,已经快到 5 点的发布截止窗口了,稍有延迟,就要走紧急发布了。

思前想后,仍是趁这会清净,赶忙发完吧。因而,我紧急看了下代码,发现 RefundBizNsqInput 不在组件自动 scan 的包路径下。 因而将这个任务涉及的组件类都移到了能够被自动扫描组件的路径下,修复了下单测。此刻,若是要再验证 OK 再发布的话,恐怕会耗时太长。 因而,我作了个大胆的决定,不验证就直接发布。由于只是经过 IDE 的重构功能挪了下包路径,理论上是不会有问题的。 其实内心仍是有点虚的。有时,直觉很重要,虽然它来自于大量经验的积累;当机立断也很重要。

想定,取消了以前的发布单,联系运维同窗,帮忙从新开了个紧急发布的绿灯, 从新开始发布。幸运的是,此次没有再报错误日志。因而,我按照写好的发布文档,一我的在这静静的天亮时分,循序渐进地开始发布, 一直发了两个小时,到七点半多才发完,一如 08 年踏雪归来的感受。

反思: 若是在 QA 有验证那个退款消息的任务, 就不会出现这个尴尬的局面了。由于这个任务的消息处理,须要加载一个自定义的 消息接收器,而这个没有被覆盖到。 这是一条漏网之鱼。


尾声

电子发票同步

正要鸣金收兵,忽现新军情:电子发票索引同步的一队小骑兵,趁我困倦之时,偷袭过来,想来个以逸待劳。任务里的一段 groovy 脚本没法执行。有几条消息就出错几条。得赶忙解决,否则线上又要报问题了。

排查这个错误,有点尴尬。 错误日志只打印了: failed to execute 。。。 啥信息也没有。 我总不可能添加一行日志, 再发布一次吧。近乎崩溃。怎么办怎么办 ? 扫了一眼脚本,有个奇怪的格式化日期的变量彷佛没定义。想用另外一种先替换看看。没效果。试来试去,没效果。

此刻,意识有点模糊,有点扛不住了。但是又不能就此睡去。 怎么办 ? 思来想去,只好打扰一下团队同窗了。 叫醒了三位懂些 groovy 的同窗,帮忙一块儿排查下。

孔鹏同窗提醒说,在本地运行下这个脚本。 我立刻想到了,能够把消息和脚本放到本地工程里运行下,看看哪里报错。那个被怀疑的变量也找到了定义的地方。在本地运行是经过的。 这可以让人有点摸不着头脑了。 天已经亮了,八点多了。

有同窗建议说,回滚吧。但是,回滚的代价太大了。 花了一整晚,终于将老的工程迁移到新的工程, 难道要由于一个小的问题,再滚回到原来的 ? 且新的工程回滚到老的,也是有比较大的风险的,发布也要通过一系列比较繁琐的操做,容易出错。 我宁肯背一个 P4 故障,也要把这个问题解决掉。已经没有退路了。

忽然灵光一闪,能够在预发起相同的任务,而后加调试日志,在预发看看是什么缘故 。 燃起了新的但愿。

用最后的精力折腾了一下, 发现报 unable to solve groovy.json.JsonSlurper 。 我觉得是没有 import ,所以加了一行 import 。但是仍是报错。 孔鹏同窗突然在群里说, JsonSlurper 这个类没有找到啊,且最好把 groovy-all 也引用进去吧。关键的一击啊 ! 我立刻去工程里看了下,groovy 2.0.8 才支持 JsonSlurper ,而我以前为了单测经过,只用了 groovy 2.0.1 。 细心的读者应该注意到,前面跑单测的时候,我把 groovy 的版本改为了 2.0.1 。 因果的命中注定 ,是说,在你写下这行代码或配置的时候,命运已经注定了,只待前来认领。要慎重啊!

当即修改,部署到预发, 解决了。 耶 !!

线上消费出错怎么办呢 ? 先用预发的任务消费线上的消息吧,确保后续的数据都写入 OK , 待明天作个优化后,再切回到线上的任务消费。原来预发能够做为线上的 “备胎” 啊!

反思: 不用说,这个任务也没回归到,由于很边缘。 然而,这个任务引用了一个类,依赖更高版本的 groovy ,是个局部细节问题,没有覆盖到。 看来, 凡是有疏忽,必受惩罚。 老天爷的惩罚仍是比较轻的: 照这样算下来,胜算大抵只有 80% 左右。

终于能够碎觉了。 emm.... 别打扰我。

监控统计

下午来到公司, 王爷 跟我说, S 的监控统计不对劲, 曲线值很低,跟业务量彻底不匹配。我想,多是日志平台又出问题了 ? 以前间歇性也会这样。但王爷坚持要查一下。因而,我开完一个会以后,就找日志平台的同窗苏苏一块儿去查了。

苏苏显然更相信本身抓包看到的数据,说,这个业务量可能就是这样。但我深知,业务量确定不是这样,更多是改造工程的过程当中,某个配置有问题,但暂时不知道是哪里有问题。

不过苏苏查底层问题仍是颇有章法的,脾气也不错,提及批评人的话来也是很温和。在通过我承认后,在机器上安装工具,抓包,看监控图表,发现 在 S 发布点以后,写监控统计就一直报错了。查来查去,发现 S 引用了一个自研轻量级 R 的包,来写入监控数据, R 则会读取 S 的一个配置文件,而这个文件的 NSQ 配置是错误的。至此,真相大白。

想到以前还没仔细看过监控统计的代码,领悟: 每个不清楚的想要暂时跳过的地方, 老天爷都会恩赐一个问题, 逼着你最终弄清楚。


小结

像是走过了一段较长的路。 面对大流量下的大改动的发布,曾经感受到比较大的压力。发布完成以后,感受彷佛没那么可怕了。 一切都过去了。

流量似山海,心内亦平川。 日常心就好。

相关文章
相关标签/搜索