AImager

2016总结

#技术 #总结

2016年,基本上扮演的是工程师和学习者的角色,这两个角色都离不开技术,所以自然的2016总结变成了2016技术总结。

工程师文化

工程师文化是个奢侈品,这是个稍显悲观的论调,但如果抱着乐观的态度去看,会发现即使是奢侈品,也是存在的,既然存在,就可以去追求。

工程师文化是什么?『工程师文化是一种群体产生的实事求是用技术解决问题的氛围』,这是个人观点,我没法去论证它的正确性,因为它本身就是个定义问题。当然,这并不是在逃避问题,只是在一年的观察中,发现即使是技术,主观性也大的惊人,包括对技术的理解、评价,也包括对技术人的理解和评价。这种主观性本身没问题,不过一旦夹杂个人欲望就会严重影响问题的解决,或者说影响根本问题的解决,通俗点?Google下PPT架构师就理解了。所以技术人实事求是是基本准则,这不仅是工程师文化的结果,更是工程师文化产生的源动力。但生活很艰难,社会很浮躁,个人欲望总是会压过些东西,所以嘴炮少不了,傲慢少不了,恐惧少不了,贪婪少不了,无知少不了。目前我自然也有这些问题,但还是希望成为工程师文化的参与者。

工程师文化有什么用?能吃吗?这问题没法答,很多公司要活下来都难,谁还有心情管工程师?而且还要弄什么工程师文化?但对工程师而言,这东西就像言论自由一样,你说没它也能活,就是不爽而已。

服务架构

在还未涉猎足够多的需求场景之前,我只能谈面向服务的架构,事实是,大数据趋势下需要的分布式能力也很容易被面向服务的架构所组织和使用。

SOA和微服务是面向服务架构里面两个很火的概念,两者的区别大家一直都在争论,但个人观点是『两者在工程上没有区分的必要』,为什么这么说呢?我们不妨先来看看大家争论区别的关键点是什么,主要是两块,一是中心化和ESB总线,二是服务的边界。一个个说,先说第一点,SOA采用星型结构设计,通信都需要走中心节点,即总线,而微服务则走去中心化的路线,但在实际工程中,某种小范围的中心化更容易管理和统一,比如数据集成和分发、异步中间件等,而整体上,为了保证高可用,服务间的调用经常会不走某个特定节点,所以是否采用中心化的方案、何时采用实际上还是由业务决定,而不是我们当前采用SOA或者微服务就一定要中心或者去中心了,那么从这个角度讲,SOA和微服务都没法提供完善的最佳实践,区分不区分意义就不大了。再说服务边界,这本身是极难确定的,即使OASIS给出了SOA的标准定义,在真正进行服务分割的时候,标准上的划分办法还是难以执行,这都源于业务场景的复杂性和概念现实的难对应性。既然概念本身没法帮我们解决问题、提供更好的实践,不如取概念中的精华,关注业务,该中心化的中心化,该拆分服务的拆分服务,以解决问题、发现问题、预测问题做指导,结果总是会更好的。

抛开SOA和微服务的抉择,聚焦到具体业务,接下来需要做的就是层次的划分和服务的划分。对于一个O2O的小体量企业而言,层次的划分几乎都可以照搬『数据层、公共子模块、业务层、前端』这样的结构,所以不做赘述。这里只单独提下公共子模块,类似推送、短信这些极其通用的模块因为每个公司几乎都有用到,所以抽象出来的技能很容易被循环使用,而随着互联网创业潮发展起来的一批BaaS企业也更加降低了这层的门槛(同时也屏蔽了硬件层),使得这一层在整个开发周期上占比愈发的少,当然对这一层的业务有高要求的另算,比如无延时推送,精准定位等。

一个服务只做一件事,事实上这种划分原则几乎所有人都同意,可什么叫一件事?营销系统只做营销,积分营销系统也只做积分营销,但两者显然有包含关系,所以服务划分最终还是转换到对服务能力边界以及服务能力粒度的确定上。理论上分析,一个服务过粗过大就会出现臃肿、维护麻烦、迭代慢的问题,而过细则会带来依赖处理麻烦、集成困难的问题。举个实际的例子,最初推送是由业务层直接调用第三方推送完成的,但由于需要推送的设备类型和业务模块很多,所以考虑做一个推送服务模块,为了把推送内容的生成控制在业务层,推送服务模块完全做成了业务无关的形式,结果随着业务层对推送的要求逐渐增加,很多业务层做不了或做不好的事开始往推送上加,导致推送服务开始加入和业务相关的推送内容处理逻辑,这就使每次这部分更改的时候都需要同步,白白double了修改时间和沟通时间,而这些问题就是由于对推送模块所应当承担的功能划分的不当导致的。说了这么多,有没有实用的划分方案,我读了些文章,比如S++建模过程,但也许是了解的不够透彻,觉得这样的过程不具备通用性,所以至今还未建立个人的建模方法论,因此还需要多学习和斟酌。

更新:一个广泛接受的服务架构概念关注的核心就是『如何分』与『如何合』的问题,而不是上面分析的『是否分』和『是否合』的问题,可以参见SOA标准文档。

业务服务设计

这一块更多的是一些Tips了,散列在一些博文中,这里就不啰嗦了,只说我目前的一个核心结论,在面向服务的小体量架构下,单个业务服务设计的好坏主要取决于接口设计和数据库设计的好坏,但这一切都基于对需求了解清楚的情况下。

数据仓库

互联网公司,大家都靠着一堆指标做运营,所以数据重要,数仓也重要,而对于面向B端的公司而言,看数据的除了运营还有商户,那么数据的意义就又上升了一个层次。既然是做数仓,必然会考虑ETL流程,至于是通过ETL工具还是代码本身是经过一番讨论和调研的,但列出的优缺点和网上说的并没有什么本质区别,支持工具的还是支持工具,支持代码的还是支持代码,后来大家达成共识,觉得与其争论一些没结果的,不如先做做看,所以像我一样的代码派暂时放弃了个人追求,大家统一使用ETL工具处理。kettle自然是开源ETL届的首选,虽不好用,好歹也搭建了一个还算完整的数仓,遇到的一些坑,比如『历史拉链表遇到的问题』都已经记下来了,这里就不重复了。回过头来说下kettle和代码的比较,kettle适合做逻辑清晰,共性强的数据操作,比如数据集成、简单的联表统计操作等,且kettle在作业的统一管理上要强于代码(前提是没有用代码做出调度和管理工具前),这也是kettle类ETL工具只在传统领域内盛行的原因;而代码则在灵活性和复杂业务逻辑处理上面要远强于kettle,适合做对数据的深度处理。最后说一下,为什么我们不上Hadoop、Impala这些东西,原因很简单,数据量不够大,机器不够多,上了徒增启动时间,增加运维成本。

前端

Web前端处理的不多,但下意识的认为工程化很重要,还需要学习以及深入的思考。App前端应该很长一段时间内不会去研究,所以就先放这了。

运维

『在没建立完善的监控机制前,你做任何事都是错的,只要出事就是你背锅』,这句话不记得谁说的了,但是也是给所有运维提了个醒,做好监控,即使出事也能甩锅。当然,不是说为了推卸责任,而是严谨的对待事故bug也是一种工程师文化的实践。

你该监控些什么?看看NetData监控的项目你就有个大概的监控指标了,不过NetData监控的主要是服务可用性的问题,还有一些问题,比如操作日志就需要单独记录了,还有产品偏向的指标,比如响应时间,这也是监控的一个方面。

监控外还有个上线的问题,在缺乏专职运维的时候,程序员经常会做一些不规范的上线操作,比如代码配置不抽出来做环境隔离,版本号混乱,通过代码比较的方式上线等等,这些问题在不解决的时候觉得问题不大,一旦上线的时候就发现坑死人不偿命。

数学+算法+机器学习

离开了学校,算法用到的比想象中的还少,刷题的习惯也因为工作停了好长时间,不过前段时间开始捡起来了,不知道是对深度学习产生了兴趣,还是希望换点东西学,但不管怎么样,是好事,就是时间总是个大问题。

『对于某类任务T和性能度量P,如果一个计算机程序在T上以P衡量的性能随着经验E而自我完善,那么我们称这个计算机程序在从经验E学习』,这是关于机器学习的形式化定义,所以从这个定义上走,机器学习并不困难,而这也是我可以在很短时间内一个人搭建出一个推荐系统的原因。不过,做出来不难,要做好却异常艰难,因为时间和业务的不允许,所以这一块只能算涉猎。但还是希望在学校里打的一些数学建模的底子未丢掉前,能抽出更多的时间学习下。

技术栈

做网站,简单点LNMP,Phalcon、Laravel、Yii随便选,异步?swoole,Restful、RPC看喜好,重方案?Java生态,node.js性能不错,Go并发很强大哦,想站在鄙视链高层?C++,前沿上Rust,逼格还不够?写Lisp。协同开发,用git,代码库管理,gitlab。mysql不够学术范?上Postgresql,多机关系型?TiDB,Nosql?暂时不考虑,Cache上redis代替memcached,队列用beanstalkd,要上分布式?有Kafka。量大了,要买机器了,阿里云太贵,自己上Openstack,负载高了用LVS、DNS智能解析,该招运维了?不用,鼓吹Devops,用Ansible、Docker、kubernetes。服务经常挂要上监控啊,Zabbix走起,麻烦?上Netdata,日志系统用ELK。数据量起来了,可以搞数据挖掘了,单机跑不动?Hadoop加Hive,慢?Imapla,听说Spark更快,用用看,老离线跑不行啊,Storm流式计算。数据拿出来了,搞点机器学习,python+numpy+scikit-learn,Deep Learning?用Tensorflow。

上面列的这些技术,有些试过了,有些还没试,尤其是很多技术没在生产环境中用到,就导致选型存在主观性,不过总是会有个主观的过程,多踩踩坑,自然会客观起来。

经验泛化

技术方案的选择从来是个权衡的过程,因为无论哪个技术方案,都会同时包含优点和缺陷两方面,以ORM为例子,这东西大家争吵了十余年,说它抽象数据的还是认为它好,说它繁琐性能低的还是觉得它差,所以很多情况下,时间泛化的不仅仅是经验,可能还是偏好,因此时刻记住:开发的最终目标是满足需求,而开发过程中需要满足的目标则是高效率以及少bug

写在最后

说了这么多,全是技术的事,也不知道该庆幸自己专注还是懊恼自己乏味,身体也开始报警了,所以来年还是需要花些时间在生活上,最后还是给自己些期望吧

  1. 个性再洒脱些,心态再平和些,克制而张扬,随性而含蓄
  2. 规律作息,1000公里目标
  3. 培养个爱好,练习下英语,出国见见外面的世界