2019 年度总结
第一次写年度总结,简要回顾一下 2019 年工作中发生的事。
从 18 年 10 月份开始调查微服务,主要是调查基于 Spring Cloud 搭建微服务环节,使用到了 Eureka、Feign 等组件,代码主要还是 .NET Core,毕竟之前的 3.0 版系统是 ASP.NET 的,而且功能比较多,迁移起来比较方便。不过 .NET Core 对比 Spring Cloud 原生组件来说还是差距比较大的,比如重试、熔断等在我们的 .NET Core 微服务中都还没有实现。暂时也没有这方面的必要,所以也就没有继续调查。日志方面之前记录在 MongoDB 中的,现迁移到了 ELK。配置使用了携程开源的 Apollo, Java 的支持比较好,.NET Core 差了点,不过使用起来倒也没啥问题。定时任务使用的是 Quartz.NET,之前是通过自建的 WinForm 程序单机运行的。当任务越来越多时对服务器的压力比较大,单机也越来越无法支撑, Quartz 支持集群,可扩展性提高了很多。另外这些都是基于 .NET Core 框架的,为之后运维通过 Kubernetes(k8s) 管理和发布各种环境打下了基础。
当然,由于 .NET Core 毕竟也算是新鲜事物,很多相关的组件也不是很完善。Redis 客户端使用的 CSRedis 就出过一些问题;SkyWalking 后来由于影响服务器性能,只能关停了。不过总的来说,系统到现在也已经上线将近一年了,运行也算是很平稳的,运维在使用了 k8s 后发布的工作量也是减少了很多(毕竟公司的发布频率还是相当高的,平均下来估计每周都有一次)。
说起来,这也是我进公司以来第二次系统的升级了。刚进公司的时候正好赶上公司架构的改造,不过改动并不算大,更多的是一些写法上的统一。这次改动就比较大了,整个就是一个新的代码框架。比较可惜的是,由于时间、人员(正好赶上公司裁员)等因素,很多东西都是从之前的代码复制过来的,也就导致之前的一些问题仍然还在。比如,我们的 BLL 层其实就是具体的 Service 层,应该是可以使用依赖注入和单例来简化开发和提高效率的, Redis 的访问、更新、删除操作也还有很大的优化空间。另外,将 3.0 中的主要模块功能迁移到新系统是为了之后 DB 服务器的拆分做准备的,但由于年前裁员导致的影响,之后已经完全没有人手来做这些事情了。这间事情也就不了了之了。
微服务系统大概是 18 年 10 月开始调查,11 月开始搭建,12 月到 19 年 2 月是代码迁移(这段就比较枯燥了,基本上可算是重复劳动)。
3 月份迁移的是定时任务到 Quartz ,还算是比较顺利的。
之后到 4 月底基本上是在做慢事务的调查和优化。提到优化,感慨还是蛮多的。最大的感受就是开发没有规范,开发对性能的意识比较单薄。实际上我还是在之前的 SVN 上看到看到过一份开发规范的,但貌似是很久之前的了,而且也没人来 Review 代码是否符合开发规范。
很多性能问题是可以通过严格执行开发规范来避免的。比如循环体中应尽量避免查询数据库,避免循环的获取重复的数据,即使是从缓存(Redis)中获取(根据监控曾发现一个请求可能会访问上千次缓存服务器)。再比如应禁止使用模糊匹配来删除缓存 Key 等。
数据库使用的是读写分离,但是读库的查询仍然很慢的情况下,一般采用的对策是加索引,但随之而来的插入和更新缓慢问题从没人考虑,导致现在某些索引比较多的表偶尔会发生单条记录新增或更新会被阻塞数秒甚至十几二十秒的情况。根据运维所说,现在生产 400G 的数据,其中 250G 左右是索引。现在索引多了想要删除也是很麻烦的事情,一旦删除之后导致查询变慢,可能会导致整个数据库变慢,所以单靠运维已经很难解决这个问题了。如果最开始规约上有规定何时能加、何时不能加索引,有效的控制索引的创建,就不会有这些问题了。至于慢查询,有时候确实很难优化,最好是在需求时期就开始考虑,一旦功能完成了再想优化,难度会增加很多。若需要修改数据结构,那旧数据如何处理?若需要修改业务,那些已经习惯了的用户怎么办?
还有一个原因就是开发工期了,按理来说自己公司产品的维护,工期上应该比较好估算,也应该比较宽松才是,但往往是在需求讨论结束开始编码时会给出一个比较紧的发布日期,有一种需求已经确定了,产品最好第二天就能上线一样的感觉。这么紧的发布日期,自然也就导致开发完全没有心思去考虑性能的问题,功能能按期实现就行了。虽说不是每次都是如此,但十次中少说也有六七次是这样。就说之后 4 月份开始的小程序,说是 6 月初上线,6 月初的时候实际开发也大都完成了,但由于一些关联系统等的问题,最终好像是在 8 月份才正式上线。中间有那么长的时间可以利用,为什么一定等到后期慢的不行了才想起来优化呢?
6 月份的时候另一件事就是引入了 Git 来管理项目代码,并且制定了 Git 开发流程 ,其中包含了如何并行的开发,如何合并、发布等?之后陆续的把大部分系统都迁到了 GitLab 上。 Git 再加上之前就引入的 Jenkins 使我们的测试和发布方便了很多。最初是从 2018 年使用 Jenkins 编译 3.0 项目开始的(使用 Jenkins 自动编译 C# 项目),现在大部分的系统都已经可以通过 Jenkins 发布了。
小程序结束到 8 月底仍然继续在做代码的优化,期间整理了常见的一些导致慢事务的原因及如何优化,在部门内发表过。
9 月份让我们小组调查一下行为分析系统,期间调查了 Apache Storm、Hadoop、Flink、Flume。但由于并没有具体的需求,最后只在 10 月中旬发布了使用 Flink 收集小程序部分访问信息的功能,其数据持久化到一台 MySQL 服务器。不过这些数据到现在仍然没有被使用过,暂时只是收集着。
10 月下旬让我们组做了统计客服即时消息(我们公司使用的是融云)内容的功能,最后采用的是使用定时任务获取历史消息的 zip 文件地址,然后通过消息队列下载文件、解压、读取文件的方案。期间自己简单的了解了下 Python 语言,不过暂时还没有机会使用到项目中。
11 - 12 月份除了优化之外,主要做了两件事情:1. MongoDB 日志的优化;2. 供应商店铺功能的开发。
第一个问题其实也算是历史遗留问题,最初设计时这些数据是保存在 SqlServer 的日志表中的,但由于其不仅包含操作日志,还包含一些 Info、Warning 和 Error 日志(这些数据本应保存在日志文件或类似的地方),导致该表数据量非常庞大,但是又不允许删除历史数据(这点我是非常不理解的),最终庞大到 DB 撑不住的时候将其迁移到了一台单独的 MongoDB 服务器。我们这次之所以优化 MongoDB 也是由于这些历史原因导致的, SqlServer 是关系型数据库,日志表有一张关联表,很简单的通过 Join
就可以关联了,但 MongoDB 是文档型数据库,无法实现 Join
操作,开发的人没考虑性能,获取了大量的关联表数据在代码中做关联,导致整个 MongoDB 都很慢。由于不允许删历史数据,导致数据越来越多,查询也越来越慢,后来有增加了一台归档服务器,报错所有日志,原来那台仅保存 3 个月内的日志数据。但不巧的是这张关联表没有创建日期字段,没法按照日期进行归档,所以也就有了此次优化。优化方案也比较简答,将两张表合并成一张表就行了,主要是历史数据处理起来比较麻烦,只能慢慢的一点点处理。
第二个就是前几天在忙的新功能,仍然是工期太紧导致的。本来说是 12/30 发布(我估算的是 1/8),但到现在仍有不少问题需要修改,可以想象的是发布后随之而来的问题肯定不会少。
总的来说,2019 年给我的感觉就是一个字 快 ,非常的快,没想到一年就这么快过去了。人说忙起来时间就过得快,但也没感觉自己有多忙啊!