50天10万行代码,一号专车系统重构细节回顾

2013年底,我关闭当时的创业项目,无所事事之时,打电话向快的CEO Dexter请教,当时快的和大黄蜂刚刚合并,他建议我可以先和大黄蜂CEO李祖闽(Joe)聊聊。

和Joe第一次见面是在虹桥火车站的一家肯德基里碰头,当时我看不太懂打车这个项目。那次碰面,我们聊的却不是出租车,聊的全是专车。两年多前的那时候,做这一块的不多,真正意识到这是个大机遇的且投入资源的创业公司比较少。Joe跟我讲了许多他对未来专车的构想,一下子就挑起我非常大的兴趣,简单说就是High了:)。

Joe也跟我讲了现在公司在技术上碰到的一些瓶颈,限制了业务的开展,比较痛苦,我们原定半个小时的碰面,结果一聊聊了4个多小时后,两人意犹未尽,又一起打车回市区聊了一路,下车的时候我和他约好第二天就去大黄蜂报到。

故事就这样展开了。。。

定时炸弹

2013年12月26日,刚入职的第一天,我看到了打车大战满地销烟的惨状,快的、滴滴、大黄蜂等多家打车公司刚刚在上海打过几波大战,当时大黄蜂打车在上海市场出租车市场的占有率可以排进前三。快的大黄蜂合并后,虽然明确大黄蜂未来的战略方向转做专车业务,同时也上线了第一版本的专车系统,并将部分出租车请求转发给快的打车。但出于种种因素考虑,还是把一大部分的工作重心依然留在出租车上面,并没有完全放弃出租车业务。

我初进大黄蜂,又恰逢临近春节,专车系统刚刚上线不久,我们想要在上海做一次“春节50/100元专车接送机场(虹桥、浦东两个机场)”的活动,但原来的产品及部分开发人员出现了一些波动,正在陆续办理离职手续,留下的开发人员状态也不太稳定,好在专车系统的即将离职的同学还比较靠谱,被我拉着讲了一个周末的数据库表结构及代码,于是我就是在边看代码边熟悉系统的基础上,进行业务开发,技术总监写代码不算什么,其实后面重构上线前期我还做过一整周的测试

2014年春节很快过去,快的和滴滴在全国掀起一波补贴大战,大黄蜂的出租车业务在上海市场协同快的也侧面参与了一些,但大部分精力已经开始转向专车业务,我对原来的系统也已经比较了解,当时的系统情况大致是这样:

50天10万行代码,一号专车系统重构细节回顾

CNUTCon2016容器实践经验谈专场,2016年9月9日即将开启,北京喜来登长城饭店芙蓉厅,点击了解详情!

当时出租车主要开了两个城市,上海和广州,各部署一套系统,数据库、缓存、Web服务、API、定时任务都在两地部署,由中心库负责定时同步主要的数据,比如用户信息等,但因为两地市场开拓的时候,运营策略不同,比如各项优惠、加急令、司机补贴等政策在两地各有不同,于是就维护了两套PHP代码,大致逻辑相似,细节又各有不同。

而专车系统是后来开发,以Java为主要开发语言,基础数据(用户、优惠券、订单等)依然依赖于出租车数据库,但主要数据库和代码部署在上海,因为专车只开了上海市场,所以暂时没有什么影响。这样的系统架构限制了当时的业务发展,也给未来留下了许多定时炸弹,下面我们会展开讨论。

但在这里需要申明一点:看到这样的系统结构,确实存在许多不合理性,单纯一张九十几个字段订单表就能干掉一大票观众,但我要为其辩护,在当时打车大战初期,业务的发展是野蛮式的,每天各种补贴政策、活动的调整,开发人手严重不足,技术完全是被业务拖着跑,相信经历过创业这个阶段的人都会有深刻感触。

很显然,这样的系统架构已经不能满足当前的业务需求,越往后拖,隐患越大,定时炸弹越多,我评估下来,主要存在这么几类大的问题:

1、多地保存数据,多地多份代码不可维护。

  • 多地逻辑代码冗余:代码无法维护和管理,添加一个业务逻辑要同时改两份码,或者只改一份,但下一次增加新业务逻辑时,因为两个地区的代码逻辑差异越来越大,需要非常小心,坑越挖越深;

  • 数据同步问题:上海的乘客到广州不能下单、优惠券不见了,反之亦然,上海的乘客出差去外地后,也不能下上海的机场、车站的预约订单,甚至不能登陆;

  • 并发冲突:两套数据的维护,一不小心就出现数据不一致的问题,无法合并,也留下被攻击的隐患;

2、无法快速开城,每开一个城市都要部署一套存储和代码,准备硬件、进机房、部署、调试,效率太低,还要做好数据的同步,及当地的新政策的业务开发,开一个城市需要一个月左右的开发周期。

3、数据库表结构和代码许多地方都是堆出来的,不可维护,比如一张订单表有九十几个字段;PS: 你没有看错,就是九十几个字段。

4、手机端通过轮询接口调用API,为了快速获取成单、通知、补贴政策调整等信息。但毫无疑问,这个对于手机的资源消耗(流量、电量)很大,也增加服务器的开销。

5、公共服务和业务代码耦合太紧,比如优惠券、支付等模块;

6、专车司机公里数计算不准确,出租车司机带有打表器,专车司机主要靠手机GPS,手机会有信号不准,接受不到GPS(跳点、断点、隧道、高架)等情况;

7、系统压力大,活动一上来,慢查层出不穷,各个状况出现;

8、API接口没有加密机制,容易被刷,用户身份容易被窃取;

9、无法适应专车灵活多变的业务场景,每做一个活动,都需要2,3周的开发;

还有许多细节,比如轮询接口直接访问数据库、GPS坐标系混乱、司乘价格绑定、重复上报GPS、电子围栏不可维护、支付、定位、保险、第三方接口接入等,已不能满足业务发展,这里就不再一一列举。在这样的前提下,内部反复多轮沟通后,我们启动了重构计划。

和时间赛跑的重构马拉松

2014年4月9日,我们正式启动了重构,重构目标就是在解决这些问题的基础上,完成整个系统的第一阶段的服务化工作,大致目标包括有:

  • 设计一套灵活的专车系统,以应对专车复杂的业务场景;

  • 整个系统,包括存储及服务集中部署,便于管理维护;

  • 需要支持出租车、专车两项业务的迅速开城;

  • 手机端和服务器的实时消息(包括接单、抢单、成单、通知、计费等)推送采用长连接;

  • 接口定义一套的新的数据协议,请求加密,防token窃取,请求防篡改;

  • 采用多级缓存方案,数据库、Redis、MongoDB、分布式本地缓存;

  • 引入分布式日志系统(重构后期来不及加入,只做了一部分,但后期为此吃足苦头,快的的兄弟们给了我们很大的帮助);

  • 公共服务及业务服务的抽象及服务化;

  • 南、北向接口分离,南向接口主要对接外部供应商,北向接口仅指出租车部分,主要面向第三方渠道、比如携程、去哪儿等。

  • 数据库分库、分表、读写分离;

  • 优化寻找周边司机,道路距离计算等算法;

  • 上阿里云;

第一阶段的服务化设计后的架构图,大致如下:

50天10万行代码,一号专车系统重构细节回顾

在将以上所有这些灵活配置的内容之上,又定义了大小产品的概念,把这些灵活多变的配置参数抽象成一个个产品,每个产品维护这些配置的参数或规则,从而达到运营策略和运行系统的隔离,实现了一套灵活的专车业务系统。

这些产品对应给乘客看到的其实是一个个车型,但看起来同样是经济型的车,在后台根据不同的条件已经被抽象配置成不同的定义规则,如机场订单的经济型和非机场的经济型就完全是不同的业务规则,无论从预估的价格、发单、抢单、撮合、通知等都完全不同。

这样的设计在重构上线后,业务系统大框架在两年时间基本没有动过,最多是增加为一些新的指标或者函数进行开发,但不会影响主流程,业务系统的架构非常稳定。

市场部门或是业务部门要上线一个新的运营策略,比如一号专车在2015年和Uber打战的时候,上线一号快车,在研发部门实际只用了两天就已经配置测试完毕,为了配合运营的工作,才拖了一周才上线。

限于篇幅因素,技术细节这里就不再多说,给大家看一个最小片段的机场单的产品命中规则

( 单v城市 ==1 ) && ( 函v电子围栏 (单v目的地,上海浦东机场) ) && ( 单v渠道 ==0 || 单v渠道 ==1 || 单v渠道 ==201 ) && ( 单v类型 ==2 )&&( 单v入口 == 0 )&& !((单v用车时长>=1)&&(客v版本号>=4))&&(单v回调码==0)

题外话:在一次偶然的机会,和行业内的各家专车系统对标时,发现一号专车这种系统设计和Uber的设计思路非常类似,所以Uber才可以让各城市经理在不同城市开通不同车型做各种各样的活动,Uber系统应该是经历了数年演化,而一号系统重构头尾只花了2个多月,实际上一号的指标维度非常多,有些甚至用自定义函数来组合使用一个指标,因为国内的运营策略变化实在太快太多了。殊途同归吧。

最后再说到时间、时间….时间啊!上面提的许多技术问题,如果从时间的维度上考虑,根本就不是问题,什么GPS距离计算算法不准、去噪及道路拟合算法不够优、流控还没有做、长连接服务质量不好、SQL慢查优化,给我们时间,统统都不是问题。重构计划是4月9号开始, 我们在阅读旧有代码、梳理业务、设计新的数据库结构、搭建团队、搭API接口层框架、搭分布式服务架构(Thrift + ZK + DHF SRV Framework + Chukwa[实际没用起来])的过程中,很快就到了5月1号。

劳动节后,第一波炸弹来袭,听说其他几家打车应用也在做专车,天下武功,唯快不破,我们必须最先上线,于是计划调整改到7.15上线,下了死命令,好吧,干吧,需求不能变,时间变了! 临近5月中旬,新的需求来了,要求我们直接和快的打车端对接,至少要在重构上线后两周内也上,没有办法,在打车领域竞争的激烈程度超出所有的想象,业务发展的速度都是按天算的。

于是我们把上线时间又提前到6.15,并计划6.30上线快的APP端的一号专车,时间,还是时间,需要提前梳理对接流程、接口定义及开发,人呢间呢吧,继续干吧!没有抱怨,也不谈梦想、更没有什么改造世界的想法,仅仅是一份信任、一个承诺,整个重构团队日夜加班,从4月9号计划启动,到6月18号上线,连续70天没有休息一天,前后端的重构团队都是全公司来得最早走得最晚的人,终于还是让系统上了线。PS:苦过笑过,留下的都是许多欢乐回忆,当值得书写留念。

上线前一天

上线前一天,虽然已经预演过两次,但大家心里都没有底,因为专车业务量刚刚起来,系统如果真的出问题,将会给对手们一个绝佳的机会。内部在讨论的时候,问的最多的一个问题是如果系统挂了,我们有什么预案,做了两套,一套是切回老系统,但会出现新旧数据不一致的问题,后续补数据非常麻烦;再一套是需要运营的兄弟们支持,系统只记录下单信息,然后出后台报表,由运营同学手工派单,再打电话通知乘客和司机接送,回到原始社会,这就是现实。

来源:林中轩

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2016年7月28日
下一篇 2016年7月28日

相关推荐