首先,这里通篇讲的是故事没有太多技术性的东西,更泛干货。
2013年阿里作出了一个重大决策,要求集团 All In 无线,作为互联网的一枚新兵我们并没有什么想法。只知道今天无线看上去重要了,至于为什么要怎么做完全是无感的。2013年得老板 @winter 赏识有幸加入了这样一个重要的团队。那年随着无线的高速发展,手机淘宝也开始进入飞速增长期。我们不断的面对越来越多的需求、我们总是在不断的赶着一个又一个重要的里程碑。当然那时我仍然是一个迷茫的页面仔。阿里是一家非常重运营的公司,自然在手机淘宝上这不会是例外。我们做了一个又一个营销活动页面,多到我已无法数清。
随着业务的不断膨胀,我们需要面对的需求也越来越多。但此时包括我在内的一些同事开始迷茫,我不知道在这样的一样团队前端意味着什么。难道仅仅是每次营销活中开发前端页面的那个页面仔而已?我们的未来在哪里?我们做了一个又一个类似的活动,我们在这个过程中得到了什么?我带着这种不安与迷茫找到 @winter ,告诉他我不知道自己该做什么!@winter 和 CC 告诉我说其实方向很多,比如我遇到的营销活动的问题。今天虽然我们做了,但都是拿人肉堆出来的。前端在这件事上跟本谈不上成长,让我不妨可以去尝试一下。我说好吧,既然没有方向那我就随便选一个你认为重要的方向。从此,我走上了营销支持这条不归路。
当我尝试的去全心思考该如何去做营销支持这样一件事后,我很悲剧的发现运营在填充数据的时候很容易出错。比如我们在做一个与时间相关的页面时要求运营按时间线把素材填入到后台时,运营可以给我各种我想不到的输入,比如2014/05/06
、2014-05-06
、20140506
、2015年5月6日
等等各种我想不到的输入。这该怎么玩?我总不能为每一次运营活动都做一个后台吧?这要疯掉啊。而我们每天都得面对这种输入,靠教育肯定也是行不通的。于是在 @winter 的指导下我们做了一大胆的开始。我们要做一个方便运营输入的数据控制后台!说做就做,我们从提出想法到把这后后台拿给运营花了两天的时间,在我们未完成订餐功能的团队平台上开辟了一个运营配置的功能。
很多时候我们想的总是美好的,但事情却总不会朝着我们预设的方向发展!我们在做运营配置这个功能的时候想的更多的是如何让运营能够以很能够理解的方式把数据填对,经历了几版的更新我们逐渐把运营填充这事做的开始有些顺顺畅了。然后这还不够,因为配置这块是单发的,这意味着前端需要独立引用一个JS去看运营的配置便正确的展示出页面信息。与此同时我们仍然无法解决前端总是在不停的制作各种各样的页面的情况,虽然有些时候只是一些细微的差别。为了改善这个问题我们又开发了模板功能,这样前端可以把这些细微的差异通过与数据配置关联以便做到尽可能的复用。为了更正式的做这件事,我们把数据配制功能和模板功能放在一起从团队平台中抽出并命名为MT平台,然后就向不归路越走越远了。
MT平台的出现并不是一个偶然。在这样一个环境下,前端不得不思考如何用有限的人力解决尽可能多的需求。仅凭人去堆,那瓶颈将永远在前端上。我们常常的玩笑今天这样一件事做是历史的必然,偶然的是这件事我们用这种方式做了。
我们将页面定义为由模板+数据生成的方式,即:模板 + 数据配置 = 页面 。前端维护模板,运营维护数据互相不干涉。模板和数据模板都有自己的版本控制,这样即便前端正在编辑源代码也不会影响运营的输出,这样就可以避免运营意外把前端代码发布出去的悲剧。运营在选择一个模板时,那么当前页面所对应的模板版本就确定了。如果需要更新前面的页面只需将版本更新到所需版本。为了更好的让运营能够关注本身的工作,我们甚至把数据统计相关的参数全成的自动化。
- 前端需要定义模板的HTML代码及与其关联的数据配置结构。
- 通过
<script data-mt-variable="pageData"></script>
语法引用运营配置数据 - 保存源代码并发布(产生一个可用的版本)
模板解决了前端与运离分离的事,这种页面级的复用虽然减少了前端的工作量,但对于营销过程中一些常用的组件我们总是得在每个模板中重复的写。为了解决这个问题我们又引入了插件机制。前端无需关心插件是如何放进页面。
每个插件跟模板一样由源码和数据配置两部分组成,同样做了数据与源码版本的分离。通过插件运营同学可以随时给一张页面插入一个分享按钮,或是唤起手机淘宝的功能。
- 进入MT平台选择一个他需要的模板,并基于该模板创建页面
- 在页面编辑后台中配置页面数据。
- 发布至线上
- 系统在发布时会找到
HEAD
中的打点统计参数data-spm
并替换成正确的值。 - 将
<script data-mt-variable="pageData"></script>
替换成<script>pageData={/**运营配置数据生成的JSON*/}</script>
。 - 在
HEAD
尾行插件相关插件配置及JS代码。
今天手淘中大量的营销活动页面中商品都是通过招商或算法给出的,我们不能总指望运营在这里从A系统中导出现导入到B系统中。于是我们开始将页面中所需的数据中整理出标准模型(比如商品)。然后通过与招商、算法以及选品平台打通实现让运营能够快速的将商品数据导入到页面中来。
面对个性化内容,我们这种方式肯定是不够的。我们需要相关的API支持才能让页面真正的做到与浏览用户相关。因此我们又提供了几套API模板,这些API不理解数据是什么,而是会去看数据配置中有没有一些特定的字段,并跟据这些字段生成对应的参数调用到对应的服务,然后将真实的数据内容返回给前端。
有了API模板运营就可以将特定的玩法固化下来,并有自己的空间去处理数据源来的细节。
目前MT平台每天都会有大量页面在前端不介入的情况下发布上线,即使今天手淘前端集体休假运营也不会受多大影响。但事总有意外,今年(2015年)双11就差点出大问题。
双11预热的第一天,由于担心系统状态我们执了一夜的班。所幸当晚什么事也都没发生,但是第二天我们正准备回去休息的时候手机突然手到报警说集群负载过高。于是们立马冲出会议室开始排查问题,得益于阿里完善的监控机制我们很快的发现原来在上午的活动页面中引用了一个404
的资源。导致CDN回源压力过大,单机qps到了1500左右。很快我们找到这个页面将404的引用问题修复了。但对于一个集群来讲这样修复只能算是暂时避免了故障的产生,其实并没有解决问题。同时单机qps 1500这个值也略低了点……但这个时间点我们已不能够对集群作太多的变更,每一步操作都可以会引起更大的问题。终于当晚21点左右集群再次被流量打死,集群开始出现不断的可用与不可用之间抖动。结果排查发现我们在CDN端的配置出错了,于是又立马通知CDN修正配置才恢复了服务。搞定这个问题的同时我们开始担心,双11当天会不会还会挂掉。于是和几位同事连续三天的奋斗把系统中所有可能存的故障点都排查了一圈,也确实发现了不少问题。经过了一系统不再愚蠢的优化之后,最终我们将单机qps稳定在了2400左右,这样整体服务的可靠性就大大提升了。
营销业务是一个看起来杂乱但又有线可寻的业务,因此需要做这块业务的同学不断的总结从中找到业务的价值的规律。我们尝试在这个过程中不断挖掘业务的潜在条理,并从前到后的解决问题。手淘前端团队在这个过程中自然的走向了全栈之路,所不同的是我们在后端没有选择Node.js的方案,而是采用了传统的Java。说到这里可能会有人会问,难道Node对前端来说不是更容易上手么?我们选择Java主要是因为以下几点因素:
今天的手淘是阿里业务的重要一个组成部分,手淘的发展离开不阿里固有资源和服务的支持。我们在建设营销业务相关平台和服务的时候难免的会用到一些大团队甚至集团内提供的服务,这时候如果选择一个与集团技术体系相违背的新东西落地成本实在太高。阿里的服务端技术还是Java的天下,相关服务的提供也是以Java为主。如果我们想跟上手淘的发展节奏,我们就必需快速进入整体的技术体系而非以我们以为最方便的东西。
业务想发展一方向需要去整合别人的资源同时也需要允许别人整合你。阿里的HSF
是一个看起来有点像thirft
的服务框架,看起来通过HSF
我们可以跨语言的提供服务,而现状并不是这样。我们需要提供服务出去,不仅仅是要给出对应的二方包,同时还需要提供对应Java可以直接使用的SDK,这里我们叫二方包。这点也决定了,除了Java我们没什么可选的空间。
说到底最终技术还是要去解决业务问题,用什么样的技术只要结果是好的,其他都不重要。换句话说今天Java与Node在我看来学习是一样的。除了Javascript语法与Java语法我更熟悉点,其他于我而言跟Java比没有区别,毕竟我是个Python党(2.X死忠,目前正在考虑十年内升到3.X)!其实Java的优势还是非常明显的,毕竟经历了这么多年的积累。
经历双11这一波我们才意识到原来线上服务真的没有我们想象的那么好做,但只要我们用心去做总能够到。
营销这条路我们只是开了个头,未来营销这件事该如何去做我们也思考了很多。我们相信所有经历的痛和苦都是值得的,至少我们打开了去往未来的门。今天我们站在阿里的平台之上去思考业务该如何成长、技术该怎么样沉淀,未来的路将是更苦更痛但这一切都是值得的。MT只是我们在营销支持中做的其中一件事,但是最重要的事。今天能将我们的故事分享给大家是我的荣幸,非常欢迎对营销对全栈有兴趣的同学加入我们,跟我们一起探寻营销之路。