转:各大互联网公司架构演进之路汇总

原文地址:各大互联网公司架构演进之路汇总 by HollisChuang
请转载时务必保留文章的上述原始出处。

Web

支付宝和蚂蚁花呗的技术架构及实践
支付宝的高可用与容灾架构演进
聚划算架构演进和系统优化 (视频+PPT)
淘宝交易系统演进之路 (专访)
淘宝数据魔方技术架构解析
淘宝技术发展历程和架构经验分享(视频+PPT)(2.3日更新)
高德——快速转型时期的稳定性架构实践(视频+PPT)(2.3日更新)
秒杀系统架构分析与实战
腾讯社区搜索架构演进(视频+PPT)
京东峰值系统设计
京东咚咚架构演进
新浪微博平台架构
微博图床架构揭秘
微博推荐架构的演进
当当网系统分级与海量信息动态发布实践
当当网架构演进及规划实现(视频+PPT)
LinkedIn架构这十年
Facebook’s software architecture(英文)
从0到100——知乎架构变迁史
豆瓣的基础架构
搜狗搜索广告检索系统-弹性架构演进之路(视频+PPT)
小米网抢购系统开发实践
小米抢购限流峰值系统「大秒」架构解密
海尔电商峰值系统架构设计最佳实践
唯品会峰值系统架构演变
1号店电商峰值与流式计算
蘑菇街如何在双11中创造99.99%的可用性
麦包包峰值架构实践
苏宁易购:商品详情系统架构设计
携程的技术演进之路
篱笆网技术架构性能演进(视频+PPT)
从技术细节看美团的架构(1.26日更新)
美团云的网络架构演进之路(2.3日更新)
百度开放云大数据技术演进历程(视频+PPT)(2.3日更新)
途牛供应链系统的架构演进(视频+PPT)(2.3日更新)
Airbnb架构要点分享(2.3日更新)
12306核心模型设计思路和架构设计(2.20日更新)

无线

阿里无线技术架构演进
支付宝钱包客户端技术架构(2.3日更新)
手机淘宝构架演化实践
手淘技术架构演进细节
手机淘宝移动端接入网关基础架构演进之路
微信后台系统的演进之路
微信红包的架构设计简介
微信Android客户端架构演进之路
Android QQ音乐架构演进(视频+PPT)
快的打车架构实践
Uber 四年时间增长近 40 倍,背后架构揭秘
Uber容错设计与多机房容灾方案
大众点评移动应用的架构演进(视频+PPT)
饿了么移动APP的架构演进

其他

魅族实时消息推送架构
魅族云端同步的架构实践和协议细节


欢迎补充!~

创业公司需要基础架构团队吗?[极牛编辑修改版]

关于「真格 · 极牛技术分享」

「真格 · 极牛技术分享」- 极牛为真格基金投资公司打造的定期技术分享交流活动,采用“微信群分享 + 线下沙龙”的方式,分享和讨论新技术优秀应用实践、知名创业项目架构分析、技术工具评测和分析等技术话题。极牛愿与真格基金投资公司一起努力,共同提高中国创业技术含金量,打造一流技术能力。

关于唐福林

雪球首席架构师,前微博技术委员会成员,微博平台架构师;Java 后端程序员,已经不写 PHP,C 和 Pascal 很多年;ACM/ICPC 和 NIO 比赛深度参与者。

技术交流欢迎在微博上关注我 @唐福林

炒股,理财,资产管理,量化交易相关,欢迎在雪球关注我 @唐福林 xueqiu.com/fulin


近期,在极牛举办的「真格 · 极牛技术分享」上,唐福林集中分享了在微博和雪球做架构师和带架构团队的经历,并且对创业公司是否需要基础架构团队这个问题给出了深度解答。以下是唐福林分享文字内容。

1. 基础架构团队到底做些什么

要解答创业公司到底需不需要基础架构团队这个问题,首先我们来来聊一聊基础架构团队的职能是什么。

基础架构团队到底做些什么?

  • 为实现业务功能:技术选型,决策
  • 为了更好的实现业务功能:引入新技术/做法,提供内部支持
  • 解决历史遗留的技术债务:发现问题,找出解决方案,并推动解决
  • 业务开发 与 线上运维 中间有很宽的“三不管”地带需要填充,还需要坚实的基础设施支持

架构组工作的特点有哪些?

  •  基础架构团队存在的价值是解决非业务逻辑的技术相关问题,没有产品或运营驱动
  • 从技术角度看,每个问题都有很多种解决办法
  • 这些问题一般都是重要不紧急,短期内不解决也不会崩
  • 解决这些问题带来的价值对于非技术人员(特别是老板)不是很直观

 

2. 基础架构团队是创业公司技术发展的必然产物

在“社会主义初级阶段”,还不需要独立的基础架构组。比如,一开始,1~3 人小团队team leader 自己做决策,出问题 team leader 解决,用啥语言?cache?db?上不上云?这些问题直接导致了团队后续技术力量的升级。

到了Demo阶段,也就是3~5 人小团队,这时候应该有个架构师了,技术问题就会留给架构师解决,比如用啥框架?第三方库怎么选择?

后期发展到上线阶段,大概是5~10 人小团队,可以分组了,每个组都要有一个架构师,解决的问题就变成相互之间怎么配合?怎么保持公共基础部分的一致性?怎么解决互相依赖问题?

做好了前期的准备工作,到了公司的发展阶段,技术团队变成10~30 人,就应该有专人负责基础架构了,主要负责业务无关的技术基础设施维护,服务化框架以及治理,上线的流程等一系列问题。

如果业务到了爆发阶段,有了30~100 人的团队,就应该设置专门的基础架构团队了,开始负责技术基础设施及服务,提供内部的 PaaS,或者 SaaS等。

最后到了100+人的“高级阶段”–平台阶段,应该设置平台团队了,将公司的主体核心业务功能做成服务,供商业化或创新业务使用。在平台内部设置架构组,提供高附加值的技术支撑,异地多机房部署,大规模虚拟化平台这些宏观上的部署和组建就要开始认真思索了。

 

3,基础架构能做的再好一点吗?

 

2012年,我在微博的个人的职责从工程师转变成了架构组的组长,最重要的职责从自己写代码,转变成了“如何创造条件让团队成员更好的写代码”。这一年,微博平台壮大,职责划分逐渐明晰,我开始真正从管理领导层面思考怎么才能让基础架构做的更好一点。

首先是怎么做的问题,最重要的要求是要主动多想,没有外力驱动的时候要自我驱动,提高主动性,寻求目标,进行自我评价,没有外力驱动,没人外人评价,我们很容易陷入一种自我满足的困境:看,我做好了,我做的很牛,这回肯定可以评个优,年底多发奖金了吧。

而实际上,大部分时候,我们做的都还不够好。这里的好有两层意思:从技术本身的角度评价,跟周边公司横向比较等等;另外,就是你做的东西有没有真正的完全解决问题,不是从做的人的角度看,而是从碰到问题需要解决的人的角度看,比如业务开发团队是不是觉得好用,是不是觉得这正是他们想要的?

其次在做事的态度上,要力往一处使,因为解决一个技术问题可能有很多种办法,基础架构团队的职责就是找出一种办法,并推行到所有适合的场合,在这个取其精华去其糟粕的过程中一定要见识一起改进,禁止另起炉灶。

做任何事都要讲求方式,做基础架构的方式就是用数据说话,找到合适的评价数据指标,比如写了一个牛B的rpc框架?到底好不好,好在哪里?

另外很重要的是对于选人的要求,要能耐得住寂寞,尤其是在业务爆发式增长时,基础架构团队更需要耐得住寂寞。组建一支牛B的基础架构团队,让业务开发人员跳槽到另外一家公司以后,还会想起你们的好。所有从 Google 出来的人,都会怀念 G 家的内部基础设施。

对创业公司来说,基础架构极其重要,尤其是小的创业团队应尽早安排一个“架构师”的职位,招聘或内部培养一个架构师,如果发现一个架构师忙不过来,那就是时候扩大成一个基础架构团队了。

漫谈基础架构团队的价值 [分享稿文字版]

漫谈基础架构团队的价值
@唐福林 weibo.com/tangfl
陆续在微博和雪球做了几年的架构师,也带了几次基础架构团队,因而在多个场合被问到类似创业公司需要基础架构团队吗”“基础架构团队怎么招聘,如何管理一类的问题。于是前些天在极牛举办的「真格 · 极牛技术分享」上集中分享了我做架构师和带架构团队的经历,以及我个人对架构团队的价值的理解和思考。现将分享的内容整理成文如下,请大家指正。
  • 关于我
     首先简单介绍一下我自己:
    • 雪球首席架构师
    • 前微博技术委员会成员,微博平台架构师
    • Java 后端程序员,已经不写 PHPC  Pascal 很多年
    • ACM/ICPC  NIO 比赛深度参与者
    • 技术交流欢迎在微博上关注我 @唐福林 weibo.com/tangfl
    • 炒股,理财,资产管理,量化交易相关,欢迎在雪球上关注我 @唐福林 xueqiu.com/fulin
  • 微博平台架构组经历分享
    • 2010年底加入微博平台部
      • 当时名称为微博开放平台
      • t.sina.com.cn 为两套独立体系

Description: weibo.png

     左边是当时的 t.sina.com.cn,内部一般称为主站PHP 写的。右边是我们的基于 Java  API 体系,当时称为 OpenApi,因为我们当时主要面向外面的第三方开发者,为他们提供 open apiOpenApi 主站之间通过 Queue 互相同步数据。微博当时选择的是内部开发的 MemcacheQ,简称 MCQ 。这种模式下最大的好处是互不影响,最大的问题呢,就是数据不一致,甚至业务逻辑不一致。
     当时我个人的职责是重构和维护微博短链接服务t.cn 。事实上,我最开始接手项目的时候,还是 sinaurl.cn,是用 PHP 写的,我拿过来用 Java 重写了一遍,正准备上线,老板说要把域名换成 t.cn,然后我就一通狂改代码。当时平台内部容器都是用 Tomcat 6,短链项目是第一个尝试用 Jetty,但后来失败了又换回 Tomcat 了。
     这一年最大的收获是:学会了怎么写好的业务实现代码。
    • 2011年微博平台化
      • 统一一个平台底层,为上层 OpenApiWeb主站和无线App端提供 api
      • 平台负责稳定性,性能和扩展性

Description: weibo2.png

     当时我的个人职责是负责引入Redis来实现计数器和关系缓存功能。微博大约是国内第一家大规模应用Redis 的公司了吧,到2011年底的时候,我们已经部署了超过100台服务器,总计超过8T的内存。我们有自己修改过的RedisCounter专门用来高效的存储计数(用户的关注数粉丝数,每条微博的转发数,评论数,赞数等等)。我在Jedis client 的基础上包装了内部使用的客户端,增加了大量的异常处理,HAFail Fast等功能,还开发了一个支持滚动删除旧数据的 Redis 集群功能。
     这一年最大的收获是:学会了怎么设计并实现一个大的模块功能,做到高可用,以及如何应付高并发流量。
     PS,这也是我现在给创业公司推荐的架构,后端HttpHttps Rest Api,优先推荐Java技术栈实现,Cache 推荐使用RedisDB推荐使用Mysql,前端WebAndroid iOS、微信公众号等等都独立实现,或者共享某些 H5 页面。如下图所示

Description: commonArch.png

 
    • 2012年,平台壮大,职责划分
      • 用户关系
      • 内容
      • 私信IM
      • 公共:通知,提醒,导航 etc
      • 架构
     当时我个人的职责从工程师转变成了架构组的组长,最重要的职责从自己写代码,转变成了如何创造条件让团队成员更好的写代码。那一年微博平台架构团队最重要的几个产出包括:
      • 新版聚合框架 poly
      • redis 二次开发
      • 多机房同步队列 weibus
      • 数据管道firehose
      这一年,我最大的收获是,在摸索中逐渐理解了基础架构团队应该做什么,应该怎么做,并且逐渐的学习如何带基础架构团队,如何为团队中的其它人创造更好的条件,帮助他们写更好的代码。
    • 2013年,微博高可用改进
      • 压测平台 touchstone
      • 平台SLA体系
      • 平台多机房隔离部署
    • 2013年,微博平台服务化
      • RPC 框架 motan
      • 服务化治理体系:config servicetrace 系统,monitorCI & CD
     2013年因为人员变动,我从架构组组长空降到用户关系组任组长。虽然换到了业务组,但还是主导了平台的多个重大技术改造项目,比如压测平台touchstonerpc框架motan,以及motan上线后的服务化治理体系。
     这一年,我最大的收获是,从业务组的角度观察架构团队,更清晰的感受到了架构组的作用和价值,也更深的理解了架构组如何做项目,如何将项目成功落地推广。
    • 2014年,微博上市
      • 商业化:各种商业化需求支持
      • 成本缩减
      • feed流性能优化
     2014年主要的技术工作是feed流性能优化,和成本缩减。在feed流性能优化项目中,我负责探索从 App 客户端到 PHP 再到 Java Api 再到 Cache 最后到 DB 的全链路耗时监控统计;而成本缩减项目最后演变成了 Docker 应用预研。后来我离职后,Docker 的应用转交给用户关系组的接任组长继续进行了。
     这一年,我最大的收获是,学会了从更高层(部门,公司,甚至行业)的角度去理解基础架构团队的工作,去决策做什么,以及更重要的:不做什么。
  • 雪球平台组经历分享
    • 2015年,雪球首席架构师
      • 上半年牛市:性能优化,可用性改进
      • 下半年熊市:大数据平台,推荐,反垃圾,流式计算平台
      • 对外分享,招聘面试
      • 对内建立技术规范,上线流程
     在2015年底,雪球基础架构组升级成了平台组。当前负责维护雪球内部多个重要服务,包括用户关系服务,IM服务,搜索服务,大数据平台,推荐服务,反垃圾服务,以及开发流程和代码质量改进等等。
     这一年,我最大的收获是理解了基础架构团队在不同的公司中,以及公司的不同发展阶段的差异,包括价值观,做事方式,评价方式等等。
  • 基础架构团队的价值与思考
首先来聊一聊基础架构团队应该做什么
    • 做什么
      • 为实现业务功能:技术选型,决策
      • 为了更好的实现业务功能:引入新技术/做法,提供内部支持
      • 解决历史遗留的技术债务:发现问题,找出解决方案,并推动解决
      • 业务开发  线上运维 中间有很宽的三不管地带需要填充,还需要坚实的基础设施支持
从团队发展历程的角度看
    • 一开始,1~3 人小团队
      • team leader 自己做决策
      • 出问题 team leader 解决
      • 用啥语言?cachedb?上不上云?
    • Demo阶段,3~5 人小团队
      • 应该有个架构师了
      • 技术问题架构师解决
      • 用啥框架?第三方库选择?
    • 上线阶段,5~10 人小团队
      • 应该分组了
      • 每个组有一个架构师
      • 怎么配合?怎么保持公共基础部分的一致性?怎么解决互相依赖问题?
    • 发展阶段,10~30 人团队
      • 应该有专人负责基础架构了
      • 业务无关的技术基础设施维护
      • 偏技术的
        • 性能,高可用等等
        • docker
        • HadoopELK
      • 偏工程的
        • 重构
        • 服务化框架,治理
        • 公共第三方依赖管理,升级:jvmtomcatlog4j
      • 偏运维的
        • trace 系统
        • monitor
        • alert
        • 线上开关系统
      • 偏流程的
        • 开发流程规范
        • 代码质量保证:UTcode review
        • 上线流程:CI & CD
    • 爆发阶段,30~100 人团队
      • 应该设置基础架构团队了
      • 技术基础设施即服务
      • 提供内部的 PaaS,或者 SaaS
        • DB / Cache / Queue Service
        • 虚拟化平台
        • 大数据平台
        • 流式计算平台
    • 平台阶段,100+ 人团队
      • 应该设置平台团队了
      • 平台即服务
      • 将公司的主体核心业务功能做成服务,供商业化或创新业务使用
        • 用户服务
        • 帖子服务
        • 商品服务
        • 评论服务
      • 在平台内部设置架构组
      • 提供高附加值的技术支撑
        • 异地多机房部署
        • 大规模虚拟化平台
    
     再往后?我也不知道,大概是设立研究院之类的吧
    • 架构组工作的特点
      • 基础架构团队存在的价值是解决非业务逻辑的技术相关问题,没有产品或运营驱动
      • 从技术角度看,每个问题都有很多种解决办法 
      • 这些问题一般都是重要不紧急,短期内不解决也不会崩
      • 解决这些问题带来的价值对于非技术人员(特别是老板)不是很直观
    • 怎么做
      • 最重要的要求:主动,多想
        • 没有外力驱动:自我驱动
        • 没有产品KPI:自己寻找目标
        • 没有外人评价:自己评价
        • 有哪些要做的,哪些应该先做,哪些应该延后做
        • 最后一公里:我能做的再好一点吗
     没有外力驱动,没人外人评价,我们很容易陷入一种自我满足的困境:看,我做好了,我做的很牛,这回肯定可以评个优,年底多发奖金了吧。而实际上,大部分时候,我们做的都还不够好。这里的好有两层意思:从技术本身的角度评价,跟周边公司横向比较等等;另外,就是你做的东西有没有真正的完全解决问题,不是从做的人的角度看,而是从碰到问题需要解决的人的角度看,比如业务开发团队是不是觉得好用,是不是觉得这正是他们想要的?

 

      • 做事的态度:力往一处使
        • 解决一个技术问题有很多种办法
        • 基础架构团队的职责就是找出一种办法,并推行到所有适合的场合
        • 觉得不满或有意见?一起改进,禁止另起炉灶
      • 做事的方式:数据说话
        • 找到合适的评价数据指标
        • 写了一个牛Brpc框架?到底好不好,好在哪里?
        • 服务质量数据指标三板斧
        • qpsp99响应时间,error rate
      • 选人的要求:耐得住寂寞
        • 业务爆发式增长时,基础架构团队需要耐得住寂寞
        • 业务不增长时,基础架构团队更需要耐得住寂寞
    • B的基础架构团队
      • 让业务开发人员跳槽到另外一家公司以后,才想起你们的好
      • 举例:所有从 Google 出来的人,都会怀念 G 家的内部基础设施
  • 简单总结
    
     简单总结一下,结论就是
    • 基础架构很重要,应尽早安排一个“架构师”的职位,招聘或内部培养一个架构师;如果发现一个架构师忙不过来,那就应该扩大成一个基础架构团队了
    • 架构师自己要有想法,知道要做什么,知道先做什么,知道要做成什么样
    • 架构师自己要动手写代码
    • 架构团队不能离业务太远,要适当负责一些底层业务
    • 用数据说话,不仅架构团队,整个技术团队都应该这样
 
啰嗦了很多,回过头一看,自己感觉还是有些凌乱,大概是自己也还有很多没有想清楚的地方吧。欢迎大家就这个话题一起来讨论。

从LinkedIn,Apache Kafka到Unix哲学

原文链接:
http://www.confluent.io/blog/apache-kafka-samza-and-the-Unix-philosophy-of-distributed-data
作者:Martin Kleppmann
译者:杰微刊-macsokolot(@gmail.com)

当我在为我的书做研究时,我意识到现代软件工程仍然需要从20世纪70年代学习很多东西。在这样一个快速发展的领域,我们往往有一种倾向,认为旧观念一无是处——因此,最终我们不得不一次又一次地为同样的教训买单,这真艰难。尽管现在电脑已经越来越快,数据量也越来越大,需求也越来越复杂,许多老观点至今仍有很大的用武之地。

在这篇文章中,我想强调一个陈旧的观念,但它现在更应该被关注:Unix哲学(philosophy)。我将展示这种哲学与主流数据库设计方式截然不同的原因;并探索如果现代分布式数据系统从Unix中学到了一些皮毛,那它在今天将发展成什么样子。

LinkedIn,ApacheKafka,Unix

特别是,我觉得Unix管道与ApacheKafka有很多相似之处,正是由于这些相似性使得那些大规模应用拥有良好的架构特性。但在我们深入了解它之前,让我稍稍跟你提一下关于Unix哲学的基础。或许,你之前就已经见识过Unix工具的强大之处——但我还是用一个大家相互都能讨论的具体例子来开始吧。
假设你有一个web服务器,每次有请求,它就向日志文件里写一个条目。假设使用nginx的默认访问日志格式,那么这行日志可能看起来像这样:
216.58.210.78 – – [27/Feb/2015:17:55:11 +0000] “GET /css/typography.css HTTP/1.1”
200 3377 “http://martin.kleppmann.com/” “Mozilla/5.0 (Macintosh; Intel Mac OS X
10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36”
(这里实际上只有一行,分成多行只是方便阅读。)此行的日志表明,服务器在2015年2月27日17:55:11从客户端地址216.58.210.78收到了一个文件请求/css/typography.css。它还记录了其他各种细节,包括浏览器的用户代理字符串。
许多工具能够利用这些日志文件,并生成您的网站流量报告,但为了练练手,我们建立一个自己的工具,使用一些基本的Unix工具,在我们的网站上确定5个最热门的网址。首先,我们需要提取出被请求的URL路径,这里我们可以使用awk.
awk并不知道nginx的日志格式——它只是将日志文件当作文本文件处理。默认情况下,awk一次只能处理一行输入,一行靠空格分隔,使之能够作为变量的空格分隔部件$1, $2, etc。在nginx的日志示例中,请求的URL路径是第7个空格分隔部件:

LinkedIn,ApacheKafka,Unix

现在我们已经提取出了路径,接下来就可以确定服务器上5个最热门的网站,如下所示:
这一系列的命令执行后输出的结果是这样的:
4189 /favicon.ico
3631 /2013/05/24/improving-security-of-ssh-private-keys.html
2124 /2012/12/05/schema-evolution-in-avro-protocol-buffers-thrift.html
1369 /
915 /css/typography.css

LinkedIn,ApacheKafka,Unix

如果你并不熟悉Unix工具的话,上述命令看起来有点难懂,但它真的很强大。这几条简单的命令能够在几秒钟内处理千兆字节的日志文件,而且你可以根据需要,非常容易地更改分析内容。比如说,你现在想统计访问次数最多的客户端IP地址,而不是最热门的那几个网页,只需更改awk的参数'{print $1}’
按需求使用这些组合命令awk, sed, grep, sort, uniq , xargs的话,海量数据分析能够在几分钟内完成,其性能表现让人出乎意料。这不是巧合,是Unix设计哲学的结果。

LinkedIn,ApacheKafka,Unix

Unix哲学就是一套设计准则, 在20世纪60年代末与70年代初,这些准则是在设计和实现Unix系统时才逐渐出现的。关于Unix哲学有非常多的阐述,但有两点脱颖而出,由Doug McIlroy, Elliot Pinson 和Berk Tague在1978年描述如下:
1. 每个程序只做好一件事。如果有新的任务需求,那就编写一个新的程序而不是在一个旧的程序上加一个新的“功能”,使其越来越复杂。
2. 期望每个程序的输出都能是其他程序的输入,即使是未知的程序。
这些准则是能把各种程序连接成管道的基础,而有了管道就能完成复杂的处理任务。这里的核心思想就是一个程序不知道或者说不需要关心它的输入是从哪里来的,输出要往哪里去:可能是一个文件,或者操作系统的其他程序,又或者是完全由某个开发者开发的程序。

LinkedIn,ApacheKafka,Unix

操作系统附带的工具都是通用的,但是它们被设计成能够组合起来执行特定任务的较大的程序。
Unix的设计者遵循这种程序设计方法所带来的好处有点像几十年后出现的Agile 和DevOps的成果:脚本与自动化,快速原型编码(rapid prototyping),增量迭代,友好的测试(being friendly to experimentation),以及将大型项目分解成可控的模块。再加上CA的改变。(Plus ?a change.)

LinkedIn,ApacheKafka,Unix

当你在shell里为2个命令加上管道的标示符,那么shell就会同时启动这2个命令程序,然后将第一个程序处理的输出结果作为第二个程序的输入。这种连接机构由操作系统提供管道系统调用服务。

请注意,这种线性处理不是由程序本身来完成的,而是靠shell——这就使得每个程序之间是“松耦合”,这使得程序不用担心它们的输入从哪里来,输出要往哪里去。

LinkedIn,ApacheKafka,Unix

1964年,管道(Pipe)由Doug McIlroy发明,他首次在Bell实验室内部备忘录里将其描述为:“我们需要一些连接各种程序的方法就像花园里的软管——当它成为另一种必要的消息数据时,需要拧入其他的消息段。” Dennis Richie后来将他的观点写进了备忘录

LinkedIn,ApacheKafka,Unix

他们也很早就意识到进程间的通信机制(管道)与读写文件机制非常相似。我们现在称之为输入重定向(用一个文件内容作为一个程序的输入)和输出重定向(将一个程序的结果输出到一个文件)。
Unix程序之所以能够有这么高的组合灵活性,是因为这些程序都遵循相同的接口:大多数程序都有一个数据输入流(stdin)和两个输出流(stdout常规数据输出流和stderr错误与诊断信息输出流)。

LinkedIn,ApacheKafka,Unix

程序通常除了读stdin流和写stdout流之外,它们还可以做其它的事,比如读取和写入文件,在网络上通信,或者绘制一个用户界面。然而,该stdin/stdout通信被认为是数据从一个Unix工具流向另一个的最主要的途径。
其实,最令人高兴的事莫过于任何人可以使用任意语言轻松地实现stdin/stdout接口。你可以开发自己的工具,只要其遵循这个接口,那么你的工具能和其他标准工具一样高效,并能作为操作系统的一部分。

LinkedIn,ApacheKafka,Unix

举个例子,当你想分析一个web服务器的日志文件,或许你想知道来自每个国家的访问量有多少。但是这个日志并没有告诉你国家信息,只是告诉了你IP地址,那么你可以通过IP地理数据库将IP地址转换成国家。默认情况下,你的操作系统并没有附带这个数据库,但是你可以编写一个将IP地址放进stdin流,将输出国家放进stdout流的工具。
一旦你把这个工具写好了,你就可以将它使用在我们之前讨论过的数据处理管道里,它将会工作地很好。如果你已经使用了Unix一段时间,那么这样做似乎很容易,但是我想强调这样做非常了不起:你自己的代码程序与操作系统附带的那些工具地位是一样的。
图形用户界面的程序和Web应用似乎不那么容易能够被拓展或者像这样串起来。你不能用管道将Gmail传送给一个独立的搜索引擎应用,然后将结果输出到wiki上。但是现在是个例外,跟往常不一样的是,现在也有程序能够像Unix工具一样能够协同工作。

LinkedIn,ApacheKafka,Unix

换个话题。在Unix系统开发的同时,关系型数据模型就被提出来了,不久就演变成了SQL,被运用到很多主流的数据库中。许多数据库实际上仍在Unix系统上运行。这是否意味着它们也遵循Unix哲学?

LinkedIn,ApacheKafka,Unix

在大多数据库系统中数据流与Unix工具中非常不同。不同于使用stdin流和stdout流作为通信渠道,数据库系统中使用DB server以及多个client。客户端(Client)发送查询(queries)来读取或写入服务器上的数据,server端处理查询(queries)并发送响应给客户端(Client)。这种关系从根本上是不对称的:客户和服务器都是不同的角色。

LinkedIn,ApacheKafka,Unix

Unix系统里可组合性和拓展性是指什么?客户端(Clients)能做任何他们喜欢的事(因为他们是程序代码),但是DB Server大多是在做存储和检索数据的工作,运行你写的任意代码并不是它们的首要任务。
也就是说,许多数据库提供了一些方法,你能用自己的代码去扩展数据库服务器功能。例如,在许多关系型数据库中,让你自己写存储过程,基本的程序语言如PL / SQL(和一些让你在通用编程语言上能运行代码比如JavaScript)。然而,你可以在存储过程中所做的事情是有限的。
其他拓展方式,像某些数据库支持用户自定义数据类型(这是Postgres的早期设计目标),或者支持可插拔的数据引擎。基本上,这些都是插件的接口:

你可以在数据库服务器中运行你的代码,只要你的模块遵循一个特定用途的数据库服务器的插件接口。
这种扩展方式并不是与我们看到的Unix工具那样的可组合性一样。这种插件接口完全由数据库服务器控制,并从属于它。你写的扩展代码就像是数据库服务器家中一个访客,而不是一个平等的合作伙伴。

LinkedIn,ApacheKafka,Unix

这种设计的结果是,你不能用管道将一个数据库与另一个连接起来,即使他们有相同的数据模型。你也不能将自己的代码插入到数据库的内部处理管道(除非该服务器已明确提供了一个扩展点,如触发器)。
我觉得数据库设计是很以自我为中心的。数据库似乎认为它是你的宇宙的中心:这可能是你要存储和查询数据,数据真正来源,和所有查询最终抵达的唯一地方。你得到管道数据最近的方式是通过批量加载和批量倾倒(bulk-dumping)(备份)操作,但这些操作不能真正使用到数据库的任何特性,如查询规划和索引。
如果数据库遵循Unix的设计思想,那么它将是基于一小部分核心原语,你可以很容易地进行结合,拓展和随意更换。而实际上,数据库犹如极其复杂,庞大的野兽。Unix也承认操作系统不会让你真的为所欲为,但是它鼓励你去拓展它,你或许只需一个程序就能实现数据库系统想要实现所有的功能。

LinkedIn,ApacheKafka,Unix

在只有一个数据库的简单应用中,这种设计可能还不错。
然而,在许多复杂的应用中,他们用各种不同的方式处理他们的数据:对于OLTP需要快速随机存取,数据分析需要大序列扫描,全文搜索需要倒排索引,用于连接的数据图索引,推荐引擎需要机器学习系统,消息通知需要的推送机制,快速读取需要各种不同的缓存表示数据,等等。
一个通用数据库可以尝试将所有这些功能集中在一个产品上(“一个适合所有”),但十有八九,这个数据库不会为了某个特定的功能而只执行一个工具程序。在实践中,你可以经常通过联合各种不同的数据存储和检索系统得到最好的结果:例如,你可以把相同的数据并将其存储在关系数据库中,方便其随机访问,在Elasticsearch进行全文搜索,在Hadoop中做柱状格式分析,并以非规范化格式在memcached中缓存。
当你需要整合不同的数据库,缺乏Unix风格的组合性对于整合来说是一个严重的限制。(我已经完成了从Postgres中用管道将数据输出到其他应用程序,但这还有很长的路要走,直到我们可以简单地用管道将任一数据库中的数据导出到其他数据库。)

LinkedIn,ApacheKafka,Unix

我们说Unix工具可组合性是因为它们都实现相同的接口——stdin,stdout和stderr——它们都是文件描述符,即:可以像文件一样读写的字节流。这个接口很简单以致于任何人都可以很容易地实现它,但它也足够强大,你可以使用它做任何东西。
因为所有的Unix工具实现相同的接口,我们把它称为一个统一的接口。这就是为什么你可以毫不犹豫地用管道将gunzip数据输出WC中去,即使开发这两个工具的作者可能从来没有交流过。这就像乐高积木,它们都用相同的模式实现节位和槽位,让你堆乐高积木的时候能够随心所欲,不用管它们的形状,大小和颜色。

LinkedIn,ApacheKafka,Unix

Unix文件描述符的统一接口并不仅仅适用于输入和输出的过程,它是一个非常广泛的应用模式。如果你在文件系统上打开一个文件,你将得到一个文件描述符。管道和Unix套接字提供一个文件标识符,这个标示符能够在同一机器上为其它程序提供一个通信通道。在Linux中,/dev下的虚拟文件是设备驱动程序的接口,所以你在这里面可以跟USB端口甚至GPU打交道。/proc下的虚拟文件是内核的API,但是它是以文件形式存在,你可以使用相同的工具,以普通文件的方式访问它。
即使是通过TCP连接到另外一台机器上的程序也是一个文件描述符,虽然BSD套接字API(最常用来建立TCP连接)不像Unix。Plan 9显示,即使是网络可以被完全集成到相同的统一接口中去。
可以做这样一个类比,所有东西在Unix里都是一个文件。这样的统一性从逻辑上来说将Unix下的工具就像一根线分成了很多段,使其更加能够灵活组合。 sed 根本就不需要关心与其交互的是一个管道还是其他的程序,或者一个套接字,或者设备驱动程序,又或者是一个真正在文件系统上的文件。因为这些都是一样的。

LinkedIn,ApacheKafka,Unix

一个文件是一些字符流,或许在某个位置会有文件末尾(EOF)的标识,这就说明这个字符流到此为止了(字符流可以是任意长度,因此程序不能提前预知这个输入流有多长)
一些工具(如gzip)纯粹是操作字节流,而不关心数据的结构是什么样子。但是大多数工具需要对输入流进行转码,以便能做更有用的事情。为此,大多数Unix工具在一行的每个记录上,在制表符或空格或逗号分隔的区域上使用ASCII码。
如今,这种字节流文件显然是一种很好的统一接口的体现。然而,Unix的实现者对文件的处理却是截然不同的。例如,他们也许用函数回调接口处理方式,使用一个事务在进程与进程之间传递记录。或者他们用共享内存的方式(像之后的System V IPC ommap一样)。又或者使用比特流而不是字节流的处理方式。
在某种意义上讲,字节流是能够达统一的最低标准— —可能是最简单的接口。一切都可以用字节流来表示,但是对于传输媒介来说根本不知道它是什么(与另一个进程连接的管道,磁盘文件、TCP 连接、磁带等等)。这也是一种劣势,我们稍后再讨论这个问题。

LinkedIn,ApacheKafka,Unix

我们看到Unix为软件开发带来了很多很好的设计原则,而数据库系统走的却是另一条大道。我很高兴能够看到这样一个未来:我们能从这两家学习到各自的核心思想,然后将它们结合起来。
那么怎么样把Unix哲学运用到21世纪的数据系统中,使其变得更好呢?在接下来的内容中,我将探索数据库系统的世界到底会变成什么样。

LinkedIn,ApacheKafka,Unix

首先,让我们承认,Unix并不完美。尽管我认为简单,统一接口的字节流是非常成功的,这使得这个生态系统拥有灵活性,可组合性,以及拥有功能强大的工具,但Unix也有一定的局限性:
1.  它只能在单一机器上使用。随着应用程序需要处理更多数据和流量,并要求更高的正常运行时间,因此分布式系统将成为必然趋势。虽然TCP连接似乎能够被当成文件处理,但我不认为这是合理的方案:因为这只在双方连接都已经打开的情况下工作,而且这里还有一点语义混乱的味道(somewhat messyedge case semantics)。
纵然TCP很好,但作为分布式管道的实现,它过于低级了。
2. Unix中管道被设计成只有一个发送者进程和一个接受者进程。你不能通过管道将输出发送到多个进程,或者从几个进程中收集输入。(你可以用tee分支一条管道,但一个管道本身就是一对一。)
3. ASCII文本(或者,UTF-8)能够很好使数据更加可控(explorable),但这很快就会变得很糟糕。每个进程需要给各自的输入进行转码:首先,将字节流分解成记录(通常通过换行符分隔,当然有人主张用 0x1e-ACSII记录分割器)。然后将记录再分解成各个域,就像在前文awk提到的$7。出现在数据中的分隔字符需要以某种方式进行转义。即使是一个相当简单的工具如xargs,约有大半的命令选项来确定输入需要怎样进行解析。基于文本接口使用起来相当好,但回想起来,我敢肯定,更丰富的数据模型,清晰的事务模式会更好些。
4. Unix处理进程通常不能长久的运行。例如,如果处于管道中间的处理进程崩溃了,那么没有办法从当前输入管道恢复,使得整个管道任务失败,必须从头开始运行。如果这些命令运行只有几秒钟那是没有问题的,但如果一个应用程序预计需要连续运行多年,这就需要更好的容错能力。

我想我们可以找到一个解决方案,既克服这些缺点,又传承Unix哲学。

LinkedIn,ApacheKafka,Unix

最令人兴奋的事是,这样的解决方案其实早就存在,那就是这两个开源项目——KafkaSamza,它们协同工作能够提供分布式流处理服务。
你也许在这个博客其他文章中已经了解到这两个项目,Kafka是一个可扩展分布式消息代理,而Samza是一个框架,这个框架让你的代码能够生产和消费数据流。

LinkedIn,ApacheKafka,Unix

事实上,当你用Unix标准去剖析Kafka,它看起来很像一个管道——将一个进程的输出与另一个进程的输入相连。Samza看起来更像一个标准的库,这个库可以帮助你读stdin流和写stdout流(还有一些有用的功能,如部署机制,状态管理,度量工具(metrics)和监测)。
Kafka 和Samza中,流处理任务的风格,有点像Unix传统的精简且可组合的工具。
1.  在Unix中,操作系统内核提供了一个管道,一个进程从另一个进程中获取字节流的传输机制。
2.  在流处理中,Kafka提供了发布-订阅流(publish-subscribe streams),一个流处理任务能够从另一个流处理任务获取消息的传输机制。

LinkedIn,ApacheKafka,Unix

Kafka解决了我们前面讨论过的有关Unix 管道的缺点:
1. 单机限制被解除:Kafka本身就是分布式的,并且任何使用它的流处理器也可以分布在多台机器上。
2. Unix管道连接一个进程的输出与一个进程的输出,而Kafka流可以有多个生产者和消费者。多输入对于在多台机器上分布的服务至关重要,而多输出使卡夫卡更像一个广播频道。这非常有用,因为它允许相同的数据流独立地、因为不同的目的而被消耗(包括监控和审核的目的,这些往往是外部应用程序本身)。在Kafka中,消费者往往来去都比较自由,而不会影响其他消费者。
3. Kafka还提供了良好的容错性:数据被复制到多个Kafka节点,所以如果一个节点失败,另一个节点可以自动接管。如果某个流处理器节点出错并重新启动,那它可以在其最后一个检查点恢复处理操作。
4. Kafka提供的是一个消息流而不是字节流,这个消息流存储了第一步输入的转码状态(将字节流分解成序列化记录)。每个消息流其实是一个字节数组,因此你可以使用你最喜欢的序列化格式来定制你的消息:JSON, XML, Avro, Thrift或者Protocol Buffers,这些都是合理的选择。将一种编码标准化是非常有意义的,Confluent为Avro提供了一种非常好的架构管理支持。这使得应用程序能用有意义的字段名称的作为处理对象,不必担心输入解析或输出转义。它还提供良好的事务推进支持而不会破坏兼容性。

LinkedIn,ApacheKafka,Unix

关于Kafka与Unix管道还是有一些不同的,这里指的提一提:
1. 上文提到,Unix管道提供字节流,而Kafka提供的是消息流。特别值得注意的是,如果有多个进程同时对相同的流进行写入:在一个字节流,来自不同作者字节流可以交叉存取,将导致出现无法解析错误。因为消息具有粗粒度(coarser-grained)和自包含(self-contained)的特性,它们就可以安全地进行交叉存取,使其多个进程能够安全地同时写入相同的流。
2. Unix管道只是一个较小的内存中的缓冲区,而Kafka持续地将所有消息都写入到磁盘。在这方面,Kafka不太像一个管道,更像是一个写临时文件的进程,而其他几个进程不断地读取这个文件,通过的尾缀-f(每个消费者独立的跟踪该文件)。Kafka的这种方式提供了更好的容错性,因为它允许在消费者出错并重新启动的情况下,不跳过消息。Kafka自动能将这些“临时”文件分割成段,并能在日程配置里配置旧段垃圾收集计划。
3. 在Unix中,如果在管道中的消费进程读取数据非常缓慢,导致缓冲区已满并阻塞了管道中的发送进程。这是背压式(backpressure)的一种。在Kafka中,生产者和消费者都更解耦: 慢消费者有输入缓冲池,所以它不会使生产者或其他消费者慢下来。只要缓冲区在Kafka的可用磁盘空间内,较慢的消费者也能后来居上。这使得系统对个别缓慢组件的不太敏感,而组成更强大的整体。
4. 在Kafka中数据流称为一个topic,你可以参考它的名字(这使它更像Unix中被称之为的管道pipe)。一个Unix程序管道通常是运行一次,所以管道通常不需要确切的名字。另一方面,一个长期运行的应用程序随着时间的迁移通常有比特添加,删除或替换,所以你需要名字,以告诉系统你想连接到哪里。命名也有助于检索和管理。
尽管有这些不同,我仍然认为Kafka是作为分布式数据的Unix管道。例如,他们有一个共同点是,Kafka让信息有一个固定的顺序(就像Unix管道,使字节流有一个固定的顺序一样)。对于事件日志数据,这是一个非常有用的属性:事件发生的顺序通常是有意义的,这需要保护好。其他类型的消息代理,像AMQP和JMS,就并没有这种有序性。

LinkedIn,ApacheKafka,Unix

所以我们知道Unix工具和流处理器看上去十分相似。都是读相同输入流,然后以某种方式修改或改转换它,并产生一个输出流,从某种程度上这都来自于输入。
更重要的是,处理工作不修改输入(input)本身:它仍然是不可改变的。如果你在相同的输入文件上运行AWK,该文件还是处于未修改的状态(除非你明确选择覆写它)。同时,大多数Unix工具是确定的,即如果你给他们同样的输入,他们总是产生相同的输出。这意味着你可以重新运行相同的命令,想多少次就多少次,然后逐步迭代成你想做的工作程序。这是个很棒的实验,因为如果你混乱地进行处理,你还是可以随时返回到你的原始数据。
这种确定性和无副作用的效果处理看起来很像函数式编程。这并不意味着你必须使用象 Haskell 那样的函数式编程语言 (如果你想这么做的话也非常欢迎),但你仍然能从函数式代码中收获很多。

LinkedIn,ApacheKafka,Unix

这种类Unix设计准则的Kafka,使其能够构建一个大型的可组合的系统。在大型的公司中,不同的团队能够通过Kafka发布各自的数据。每个团队能够独立的开发和维护处理任务——消费各种流和生产新的流。因为一个流可以有很多独立的消费者,产生一个新的消费者不需要事先协调。
我们将这种思想成为流数据平台。在这种架构中,Kafka数据流扮演的是不同团队系统沟通的通道。每个组在整个系统中只是负责自己的那部分,并且将这一块事情做好。正如Unix工具能够被组合而完成数据处理任务一样,分布式流系统也以被组合成一个超大规模的处理组织
Unix 方法是通过降低耦合性来控制大系统的复杂性: 多亏了流接口的统一性,每个部件能够独立的开发和部署。由于良好的容错性和管道的缓存性 (Kafka),当问题发生在系统的某个部分时,它仍然只是局部。并且策略管理允许对数据结构作出更改使其更加安全,以便每个团队可以加快脚步而不打乱其他团队的步伐。

LinkedIn,ApacheKafka,Unix

为总结全文,让我们思考下发生在 LinkedIn的 一个真实的例子。如你所知,公司可以在 LinkedIn 上发布他们空缺的职位,求职者可以浏览并申请这些职位。那么,如果 LinkedIn 会员 (用户) 查看了这些发布的职位,会发生什么?
知道谁看过哪些职位非常有用,因此该服务会处理职位浏览记录,随即发布一个事件给Kafka,类似于“会员123在789时刻浏览了编号为456的职位”。
现在这些信息都在Kafka里了,那么它将被用来干好多有用的事情:
1. 监视系统:公司用LinkedIn发布他们空缺的职位,因此确保该网站能够正常的工作很重要。如果职位浏览率意外地骤降,那么就应该给出警示,因为这暗示着这里存在问题,需要展开调查。
2.相关推荐:持续给用户看同样的一种东西,那他会很恼火,因此跟踪并统计用户浏览哪些职位和次数的是一种好的做法,这样就能将这些数据给评分程序。持续跟踪哪些用户浏览了什么也能够对推荐进行协同过滤(用户既浏览了X,也浏览了Y)。
3.防止滥用:LinkedIn并不希望人们能够把所有职位都浏览,然后提交垃圾邮件,或者违反网站服务条款。知道谁在做什么是检测和阻止滥用的第一步。
4.职位海报分析:发布职位空缺的公司希望看到统计数据(谷歌分析的一种方式),谁正在查看他们的帖子,例如,他们可以测试哪些措辞能够吸引最佳候选者。
5.导入到Hadoop和数据仓库:可以是LinkedIn的内部业务分析,可以为高层管理人员的提供向导,用于处理数字数据——能在华尔街进行发布,用于A / B测试评估,等等。
所有这些系统都是复杂的,由不同的团队来维护。Kafka提供了一个可容错,可扩展式的管道。基于Kafka的数据流的平台,允许所有这些不同的系统能够独立开发,并以强大的方式连接和集成。
如果你喜欢这篇文章,你将同样会喜欢由O’Reilly出版的Designing Data-Intensive Applications
感谢 Jay Kreps, Gwen Shapira,Michael Noll,Ewen Cheslack-Postava,Jason Gustafson, 和Jeff Hartley 为这篇文章的初稿提出了意见和建议,也要感谢Jay提供了“LinkedIn职位浏览”的这样一个例子。

人生夜航时那一盏温暖的照明灯

注:upyun 技术博物馆及架构与运维大会活动约稿。转载请注明出处。

【技术博物馆】独家签名 ACM 教程,夜航时的明灯

我有一本《算法艺术与信息学竞赛》,作者签名版。不是普通的作者签售,只签了作者名字的那种,而是写了我的名字作为抬头,有单独的寄语。这是我的书架中最宝贵的一本书。

我的书架

那是 2003 年底,我在北京过的第一个冬天,感觉很冷。身体冷,心也冷。刚刚过去的 2003 年夏天,高考失利的阴影依然未能散去,考的不如预期,分不低,但因志愿填的“不服从专业调剂”而落榜,依靠 NOI (国家信息学奥赛)的获奖而被补录到北师大。来到大学,曾经所有骄傲的过往都成了往事,再也不是老师眼中的尖子生,再也不能轻松拿高分,我变成了以前自己嘲笑的对象:非常努力的学习,却怎么也追不上前面的优等生。

唯一的安慰是,我还在做编程比赛。只是比赛的名字从 NOI 换成了 ACM,比赛的形式从单人作战变成了 3 人的队伍,比赛用的语言从 Pascal 换成了 c/c++。在师大的 ACM 集训队里,牛人很多,我依然不是主力,只能非常努力地追赶,努力地保持自己的位置。每天上完课后,我都会跑到位于演播楼里的集训队训练室里默默地码代码。一度短暂地上过 poj(北大在线题库)排行榜第一页。真怀念那些年在 poj 上玩各种搞笑 Nick Name。

那段时间那些牛人队友们给了我很大压力,同时也给了我很大的动力。还有一些经常一起做题一起讨论的朋友,和一些久闻其名但一直无缘得见的前辈。《算法艺术与信息学竞赛》的作者刘汝佳老师就是这样一位前辈,虽然我们年龄相仿,但他大一时即参加 ACM/ICPC 国际大学生程序设计竞赛,获得 2001 年亚洲-上海赛区冠军和 2002 年世界总决赛银牌(世界第四),并担任 2002 年和 2003 年北京赛区裁判。

我对他仰慕已久,终于因偶然的机会见了一面。当时我们相谈甚欢,临别时我主动跟他说希望能送我一本他新写的书,由于书还没有正式出版,他答应说等第一批样书印出来就送我一本,让我帮忙找找有没有印刷错误。后来果然收到快递送过来的书,打开一看,还有作者的亲笔签名和寄语。

扉页签名

这本书陪伴我度过了后来 ACM 所有的时光。ACM 比赛时,每道题都会分配一种颜色的气球。当某个队伍做出这道题后,就会在他们的桌子上挂上一个气球。比赛过程中可以抬头看见别的队都挂了哪些颜色的气球,从而知道他们都做出了哪些题。《算法艺术与信息学竞赛》,和我一起见证了那些飘荡在赛场中的五颜六色的气球,那些 Accept,Wrong Answer 和 Time Limit Exceeded1,那些快乐和失落,那些荣耀和沮丧。

两年后的 2005 年冬天,ACM-ICPC 北京赛区,我带领的 Bnu Arbiter 队获得铜牌。走出赛场后,我登录 poj,最后一次修改签名“停止做题,离开 acm--2005 年 11 月 13 日  晴”。从 2000 年高一第一次接触编程,到 2005 年底以这样一种方式结束,我觉得自己还有遗憾,但是已经可以结束了。

后来的日子里,我依然写着各种各样的代码,从 PHP 到 C,从 Java 到 ObjC 。偶尔我还会想起那些算法,虽然我再也没有写过它们。

———————–

本次,唐福林将在“UPYUN 架构与运维大会『北京站』”的架构产品专场发表主题演讲,UPYUN 也将在大会现场展出这本《算法艺术与信息学竞赛》——唐福林人生夜航时那一盏温暖的照明灯。

注1:AC,WA,TLE 等ACM专有名词含义解释见 http://poj.org/page?id=1000

大会详情:http://upyun-archops-beijing.eventdove.com/

转:从开发人员到管理者,我学到了什么

技术工程师的晋升之路

技术工程师的晋升之路大体上可以分为两个方向,一是在技术方向上作为Individual Contributor(IC)继续深造,二是以管理者的身份管理工程师团队。IC这条路比较单纯,能走多远主要取决于个人的技术实力与经验。与IC相比,转型为管理者可以说是一种颠覆性的变化。管理者的工作不再是以个人或项目的成功作为主要目标,而是专注于整个团队的成功。这种目标的变化将直接改变管理者的心态与工作方式,以及与他人的互动方式。可以说,向管理者的转型是一个具有更大挑战性的选择。

David Haney来自于Stack Overflow团队,他是开源软件dache的作者,也曾在InfoQ上发表文章。今年二月,Haney被提升为工程经理。在担任经理的几个月中,他感受到了许多完全不同的挑战。在近期的一篇博文中,Haney详细地记录了这段时间以来所领悟的管理方法心得。

信任第一

Haney认为:要成为一个成功的管理者,首要条件就是取得团队成员的信任。因为没有谁愿意为一个他所不信任的人工作,这一点往往是员工离职的首要因素,其重要性显而易见。但信任不是凭空得来的,你必须表现出你是一个值得依赖的管理者。在这一点上Haney有一定的优势,因为他已经在作为团队成员的一年时间内凭着良好的表现博得了大家的信赖。如果没有共同工作的经历,那么就需要更大的耐心去逐步建立你的信任度。

为了取得团队的信任,Haney特别列举了以下几个要点,这是作为一名优秀的管理者最重要的品质:

  • 与员工之间的对话是一种隐私,不要在人背后嚼舌根。
  • 保持一种开放的姿态,让员工感到可以无所顾忌地与你谈论任何话题。
  • 一言九鼎,说到的就要做到。
  • 不要承诺一些你办不到的事,较好的说法是:“我尽力而为,但无法保证一定能做到。”
  • 绝对不要撒谎!员工不仅会失去对你的信任,而且一见到你就会远远躲开。
  • 不要逃避困难,即使有些事情确实令你感到不舒服,但逃避只会令问题失控。
  • 不要对员工宣泄你的情绪,也不要在背后指指点点。如果确实需要宣泄一下压力,也应当寻找一种合适的渠道,而不是冲着你的员工发火。
  • 公开表扬,私下批评。不要在整个团队面前让人感到难堪。
  • 保持客观与公正,不要在团队中搞特殊化待遇。

人类无法像代码一样伸缩自如

作为开发者,Haney能够写出具有高度可伸缩性的代码。但一名管理者却无法像代码一样做到伸缩自如。正如你很难在20个与会者之间达成一致一样,要有效地管理好20个员工也是一件难以完成的任务。Haney认为,向管理者直接汇报的员工数量最好在4至10人之间。一旦超出了这个数量,你就无法对每个人都给予足够的关注,这会让员工感到被忽视,乃至怀疑自己在团队中的重要性。同时过多的人反而会降低工作效率,因此最好是启用另一名管理者来分担你的工作。

将处理人际关系作为工作重心

对于开发者来说,人际关系往往会对工作产生干扰,而成为一名管理者之后,这一点就成为了你的工作重心。在Haney看来,人际关系不仅限于你的团队,还包括与其它团队打交道,这同样也应当具有较高的优先级。同时应当尽量表现出一定的灵活性,以配合其它团队的时间安排。

另一项重要的工作是与员工定期进行一对一的谈话,让员工借此机会表达他们的想法、意见、困难,并且通过员工的反馈改进管理者的工作。Haney每隔三周就会与每位员工进行一次45分钟的谈话,在他看来,这对他的工作产生了很大的帮助。

要注意的是,如果无故地推迟或取消原定的谈话,会令员工感到遭受轻视。因此要尽可

能避免这种情况的出现,它会使员工的士气受到很大的影响。

接受令人不安的谈话

在Haney看来,当你还是一位开发者的时候,你可能会时常与其他人抱怨一些令你感到不爽的人或者公司政策,这很正常。而作为经理,你的工作就是帮助他们直接处理好这些问题。你应当鼓励员工之间开诚布公地对话,而不是与同事在私底下嘀咕。同时,优秀的管理者也应当为员工树立一个良好的榜样。

如果有某位员工直接找到你投诉某人,你应当做的是让双方坐到一起,让他们坦诚地表达他们的感受。然后居中调解,以解决他们的问题。这种对话开始时往往会令人感到尴尬与不安,但你必须接受它,并让它成为团队文化的一部分。Haney认为,经过数次这种对话之后,员工就应当能够做到在无需他参与的情况下自行开展这种对话。重要的是确保问题最终能够得以解决,而不是随着时间的推移而变得越来越严重。

衡量你的成功并不容易

开发者有一个很大的优势,他们的工作都是为了解决某个特定的问题,其范围总是确定的,并且其成果总是能够很快地显现出来。与之相比,管理者的工作似乎没有那么具体,因为这些工作的影响往往是无形的,例如员工的想法、感受、软技能以及他们的总体成长。并且这些工作没有一个具体的开始与结束时间,因为学习与进步是永无止境的。

Haney认为,管理者的任务总是与帮助员工成长有关,而这些工作的成就感通常来自于他人的反馈。比如有员工对于你的建议与反馈表示感谢,或是有人告诉你他看到团队产生了积极的变化,以及来自于团队外部的称赞等等。这些反馈能够有效地表现出你的工作是否达到预期,但管理者需要保持足够的耐心。

没有人了解你的实际工作

开发者的工作是非常透明的,其他人可以很清楚地了解你的工作内容和完成的任务,代码库里的签入记录也会清晰地反映出你的工作。与之相对的是,管理者总是在做一些幕后的工作,这很容易给别人造成一种印象:这家伙根本什么事都不干!而Haney认为,这种误解是因为他与员工的谈话往往是私下进行的,他坚持通过一对一的形式与员工谈论沟通技巧以及人际关系上的问题。由于这种交流的私密性,使其他人无法了解管理者的工作情况,因此产生了管理者不干活的误解。

在Haney看来,只有通过团队成员的各方面不断提高,才能够表现出管理者的工作价值。这是一个缓慢的过程,但当团队发现团队之间的人员互动正朝着积极的方面转变时,他们就会体会到管理者的辛勤工作。随着员工的成长与进步,团队将变得愈加强大与高效,员工们也会承认你为团队所做出的贡献。

你的成功就是他人的成功

在这篇博文的最后,Haney简单地总结了他的观点。管理工作最重要的是取得信任,通过直接的对话解决问题(虽然这种对话有时会令人不安),在幕后完成你的工作,同时保证工作方式的直接与公正性。管理工作具有很高的挑战性,同时也能够带来极大的回报。

最后,Haney引用了动画“飞出个未来”中的一名名言,它非常贴切地表现出了管理者的工作特性。

“如果某件事你做的足够出色,那么人们甚至不会感觉到它。”

 

转自 infoq http://www.infoq.com/cn/news/2015/08/developer-to-manager

雪球在股市风暴下的高可用架构改造分享

本文根据唐福林老师在“高可用架构”微信群所做的《股市风暴下的雪球架构改造经验分享》整理而成,转发请注明来自微信公众号ArchNotes。

 

唐福林,雪球首席架构师,负责雪球业务快速增长应对及服务性能与稳定架构优化工作。毕业于北京师范大学,之前曾任微博平台资深架构师,微博技术委员会成员。长期关注并从事互联网服务后端性能及稳定性架构优化工作。

 

分享主题


一. 雪球公司介绍

二. 雪球当前总体架构

三. 雪球架构优化历程

四. 聊聊关于架构优化的一些总结和感想

 



一. 雪球公司介绍

 

雪球 聪明的投资者都在这里。

 

  • web 1.0:新闻资讯,股价信息,K线图
  • web 2.0:SNS 订阅,分享,聊天
  • web 3.0:移动 APP,交易闭环

 

雪球现在员工数还不到100,其中技术人员占一半。去年9月C轮融资4kw刀。我们现在的技术栈由下列组件组成:Java,Scala,Akka,Finagle,Nodejs,Docker ,Hadoop。我们当前是租用IDC机房自建私有云,正在往“公私混合云”方向发展。

 

在雪球上,用户可以获取沪深港美2w+股票的新闻信息,股价变化情况,也可以获取债券,期货,基金,比特币,信托,理财,私募等等理财产品的各类信息,也可以关注雪球用户建立的百万组合,订阅它们的实时调仓信息,还可以关注雪球大V。雪球当前有百万日活跃用户,每天有4亿的API调用。App Store 财务免费榜第 18 名。历史上曾排到财务第二,总免费榜第 19。

 

二. 雪球当前总体架构

 

作为一个典型的移动互联网创业公司,雪球的总体架构也是非常典型的设计:

 

  • 最上层是三个端:web端,android端和iOS端。流量比例大约为 2:4:4 。web3.0 的交易功能,在 web 端并不提供。

     

  • 接入层以及下面的几个层,都在我们的自建机房内部。雪球当前只部署了一个机房,还属于单机房时代。正在进行“私有云+公有云混合部署”方案推进过程中。
  • 我们当前使用 nodejs 作为 web 端模板引擎。nodejs 模块与android 和 ios 的 app 模块一起属于大前端团队负责。
  • 再往下是位于 nginx 后面的 api 模块。跟 linkedin 的 leo 和微博的 v4 一样,雪球也有一个遗留的大一统系统,名字就叫 snowball 。最初,所有的逻辑都在 snowball 中实现的。后来慢慢的拆出去了很多 rpc 服务,再后来慢慢的拆出去了一些 http api 做成了独立业务,但即便如此,snowball 仍然是雪球系统中最大的一个部署单元。
  • 在需要性能的地方,我们使用 netty 搭建了一些独立的接口,比如 quoto server,是用来提供开盘期间每秒一次的股价查询服务,单机 qps 5w+,这个一会再细说;而 IM 服务,起初设计里是用来提供聊天服务,而现在,它最大的用途是提供一个可靠的 push 通道,提供 5w/s 的消息下发容量,这个也一会再细说。
  • 雪球的服务化拆分及治理采用 twitter 开源的 finagle rpc 框架,并在上面进行了一些二次开发和定制。定制的功能主要集中在 access log 增强,和 fail fast,fail over 策略及降级开关等。 finagle 的实现比较复杂,debug 和二次开发的门槛较高,团队内部对此也进行了一些讨论。
  • 雪球的业务比较复杂,在服务层中,大致可以分为几类:第一类是web1.0,2.0 及基础服务,我们称为社区,包括用户,帖子,新闻,股价,搜索等等,类比对象就是新浪财经门户+微博;第二类是组合及推荐,主要提供股票投资策略的展示和建议,类比对象是美国的motif;第三类是通道,类似股市中的“支付宝”,接入多家券商,提供瞬间开户,一键下单等等各种方便操作的功能。
  • 雪球的业务实现中,包含很多异步计算逻辑,比如搜索建索引,比如股票涨跌停发通知,比如组合收益计算等等,为此,我们设计了一个独立的 Thread/Task 模块,方便管理所有的后台计算任务。但随着这些 task 越来越多,逻辑差异越来越大,一个统一的模块并不是总是最佳的方案,所以,我们又把它拆成了两大类:流式的,和批量式的。
  • 雪球的推荐体系包括组合推荐“买什么”和个性化推荐。我们最近正在重新梳理我们的大数据体系,这个感兴趣的话可以单聊。
  • 最下面是基础设施层。雪球基础设施层包括:redis,mysql,mq,zk,hdfs,以及容器 docker。
  • 线上服务之外,我们的开发及后台设施也很典型:gitlab开发,jenkins打包,zabbix 监控系统向 openfalcon 迁移,redimine向confluence迁移,jira,以及内部开发的 skiing 后台管理系统。

 


三. 雪球架构优化历程

 

首先描述一下标题中的“股市动荡”定语修饰词吧:

 

上证指数从年初的3000点半年时间涨到了5000多,6月12号达到最高点5200点,然后就急转直下,最大单日跌幅 8.48%,一路跌回4000点以下。最近一周都在3900多徘徊。

 

3月最后一周,A股开户 166万户,超过历史最高纪录 2007年5月第二周165万户。

 

4月份,证监会宣布A股支持单用户开设多账户。

 

6月底,证金公司代表国家队入场救市。

 

7月份,证监会宣布严打场外配资。

 

 

7月27号将近2000股跌停,IM推送消息数超过平时峰值300倍

 

 

外网带宽消耗,一年10倍的增长

 

中国好声音广告第一晚,带来超过平时峰值200倍的注册量


挑战:小 VS 大:

 

  • 小:小公司的体量,团队小,机器规模小
  • 大:堪比大公司的业务线数量,业务复杂度,瞬间峰值冲击

     

     

     

     

     

     

雪球的业务线 = 1个新浪财经 + 1 个微博 + 1 个 motif + 1 个大智慧/同花顺。由于基数小,API调用瞬间峰值大约为平时峰值的 30+ 倍。

 

挑战:快速增长,移动互联网 + 金融,风口,A股大盘剧烈波动。


首先,在app端,在我们核心业务从 web2.0 sns 向 3.0 移动交易闭环进化的过程中,我们开发了一个自己的 hybrid 框架:本地原生框架,加离线 h5 页面,以此来支撑我们的快速业务迭代。当前,雪球前端可以做到 2 周一个版本,且同时并行推进 3 个版本:一个在 app store 等待审核上线,一个在内测或公测,一个在开发。我们的前端架构师孟祥宇在今年的 wot 上有一个关于这方面的详细分享,有兴趣的可以稍后再深入了解。

 

雪球App实践—构建灵活、可靠的Hybrid框架 http://wot.51cto.com/2015mobile/ http://down.51cto.com/data/2080769

 

另外,为了保障服务的可用性,我们做了一系列的“端到端服务质量监控”。感兴趣的可以搜索我今年4月份在环信SM meetup上做的分享《移动时代端到端的稳定性保障》。其中在 app 端,我们采用了一种代价最小的数据传输方案:对用户的网络流量,电池等额外消耗几乎为0

 

每个请求里带上前一个请求的结果

  • succ or fail : 1 char
  • 失败原因:0 – 1 char
  • 请求接口编号: 1 char
  • 请求耗时:2 – 3 char
  • 其它:网络制式,etc

     

炒股的人大多都会盯盘:即在开盘期间,开着一个web页面或者app,实时的看股价的上下跳动。说到“实时”,美股港股当前都是流式的数据推送,但国内的A股,基本上都是每隔一段时间给出一份系统中所有股票现价的一个快照。这个时间间隔,理论上是3秒,实际上一般都在5秒左右。 交了钱签了合同,雪球作为合作方就可以从交易所下属的数据公司那里拿到数据了,然后提供给自己的用户使用。

 

刚才介绍总体架构图的时候有提到 quote server ,说到这是需要性能的地方。

 

业务场景是这样的,雪球上个人主页,开盘期间,每秒轮询一次当前用户关注的股票价格变动情况。在内部,所有的组合收益计算,每隔一段时间需要获取一下当前所有股票的实时价格。起初同时在线用户不多,这个接口就是一个部署在 snowball 中的普通接口,股价信息被实时写入 redis ,读取的时候就从 redis 中读。后来,A股大涨,snowball 抗不住了。于是我们就做了一个典型的优化:独立 server + 本地内存存储。开盘期间每次数据更新后,数据接收组件主动去更新 quote server 内存中的数据。 后续进一步优化方案是将这个接口以及相关的处理逻辑都迁移到公有云上去。

 

对于那些不盯盘的人,最实用的功能就是股价提醒了。在雪球上,你除了可以关注用户,还可以关注股票。如果你关注的某只股票涨了或跌了,我们都可以非常及时的通知你。雪球上热门股票拥有超过 50w 粉丝(招商银行,苏宁云商)粉丝可以设置:当这支股票涨幅或跌幅超过 x%(默认7%)时提醒我。曾经连续3天,每天超过1000股跌停,证监会开了一个会,于是接下来2天超过1000股涨停

 

 

原来做法:

 

  • 股票涨(跌)x%,扫一遍粉丝列表,过滤出所有符合条件的粉丝,推送消息

 

新做法:

 

  • 预先建立索引,开盘期间载入内存
  • 1%:uid1,uid2
  • 2%:uid3,uid4,uid5
  • 3%:uid6
  • 问题:有时候嫌太及时了:频繁跌停,打开跌停,再跌停,再打开。。。的时候

     

内部线上记录:

  • 4台机器。
  • 单条消息延时 99% 小于 30秒。
  • 下一步优化目标:99% 小于 10 秒

 

IM 系统最初的设计目标是为雪球上的用户提供一个聊天的功能:


  • 送达率第一
  • 雪球IM:Netty + 自定义网络协议
  • Akka : 每个在线client一个actor
  • 推模式:client 在线情况下使用推模式
  • 多端同步:单账号多端可登录,并保持各种状态同步

     

     

移动互联网时代,除了微信qq以外的所有IM,都转型成了推送通道,核心指标变成了瞬间峰值性能。原有架构很多地方都不太合适了。

 

优化:

 

  • 分配更多资源:推送账号actor池
  • 精简业务逻辑:重复消息只存id,实时提醒内容不推历史设备,不更新非活跃设备的session列表等等
  • 本地缓存:拉黑等无法精简的业务逻辑迁移到本地缓存
  • 优化代码:异步加密存储,去除不合理的 akka 使用

     

akka这个解释一下:akka 有一个自己的 log adapter,内部使用一个 actor 来处理所有的 log event stream 。当瞬间峰值到来的时候,这个 event stream 一下子就堵了上百万条 log ,导致 gc 颠簸非常严重。最后的解决办法是,绕过 akka 的 log adapter,直接使用 logback 的 appender

 

线上记录:5w/s (主动限速)的推送持续 3 分钟,p99 性能指标无明显变化

 

7月10号我们在中国好声音上做了3期广告。在广告播出之前,我们针对广告可能带来的对系统的冲击进行了压力测试,主要是新用户注册模块,当时预估广告播出期间2小时新注册100万

 

压测发现 DB 成为瓶颈:

 

  • 昵称检测 cache miss > 40%
  • 昵称禁用词 where like 模糊查询
  • 手机号是否注册 cache miss > 80%
  • 注册新用户:5 insert

     

优化:

  • redis store:昵称,手机号
  • 本地存储:昵称禁用词
  • 业务流程优化:DB insert 操作同步改异步

     

     

     

下一步优化计划:

  • 将 sns 系统中所有的上行操作都改成类似的异步模式
  • 接口调用时中只更新缓存,而且主动设置5分钟过期,然后写一个消息到 mq 队列,队列处理程序拿到消息再做其它耗时操作。
  • 为了支持失败重试,需要将主要的资源操作步骤都做成幂等。


前置模块HA:


  • 合作方合规要求:业务单元部署到合作方内网,用户的敏感数据不允许离开进程内存
  • 业务本身要求:业务单元本身为有状态服务,业务单元高可用

     

解决方案:

 

  • 使用 Hazelcast In-Memory Data Grid 的 replication map 在多个 jvm 实例之间做数据同步。
  • java 启动参数加上 -XX:+DisableAttachMechanism -XX:-UsePerfData,禁止 jstack,jmap 等等 jdk 工具连接

     

关于前置模块,其实还有很多很奇葩的故事,鉴于时间关系,这里就不展开讲了。以后有机会可以当笑话给大家讲。


组合净值计算性能优化:


  • 一支股票可能在超过20万个组合里(南车北车中车,暴风科技)
  • 离线计算,存储计算后的结果
  • 股价3秒变一次,涉及到这支股票的所有组合理论上也需要每 3 秒重新计算一次

 

大家可能会问,为什么不用户请求时,实时计算呢?这是因为“组合净值”中还包括分红送配,分股,送股,拆股,合股,现金,红利等等,业务太过复杂,开发初期经常需要调整计算逻辑,所以就设计成后台离线计算模式了。当前正在改造,将分红送配逻辑做成离线计算,股价组成的净值实时计算。接口请求是,将实时计算部分和离线计算部分合并成最终结果。

 

实际上,我们的计算逻辑是比较低效的:循环遍历所有的组合,对每个组合,获取所有的价值数据,然后计算。完成一遍循环后,立即开始下一轮循环。

 

优化:

  • 分级:活跃用户的活跃组合,其它组合。
  • 批量:拉取当前所有股票的现价到 JVM 内存里,这一轮的所有组合计算都用这一份股价快照。

     

关于这个话题的更详细内容,感兴趣的可以参考雪球组合业务总监张岩枫在今年的 arch summit 深圳大会上的分享:构建高可用的雪球投资组合系统技术实践 http://sz2015.archsummit.com/speakers/201825

 

最后,我们还做了一些通用的架构和性能优化,包括jdk升级到8,开发了一个基于 zookeeper 的 config center 和开关降级系统

 

四. 聊聊关于架构优化的一些总结和感想

 

在各种场合经常听说的架构优化,一般都是优化某一个具体的业务模块,将性能优化到极致。而在雪球,我们做的架构优化更多的是从问题出发,解决实际问题,解决到可以接受的程度即可。可能大家看起来会觉得很凌乱,而且每个事情单独拎出来好像都不是什么大事。

 

我们在对一个大服务做架构优化时,一般是往深入的本质进行挖掘;当我们面对一堆架构各异的小服务时,“架构优化”的含义其实是有一些不一样的。大部分时候,我们并不需要(也没有办法)深入到小服务的最底层进行优化,而是去掉或者优化原来明显不合理的地方就可以了。

 

在快速迭代的创业公司,我们可能不会针对某一个服务做很完善的架构设计和代码实现,当出现各种问题时,也不会去追求极致的优化,而是以解决瓶颈问题为先。

 

即使我们经历过一回将 snowball 拆分服务化的过程,但当我们重新上一个新的业务时,我们依然选择将它做成一个大一统的服务。只是这一次,我们会提前定义好每个模块的 service 接口,为以后可能的服务化铺好路。

 

在创业公司里,重写是不能接受的;大的重构,从时间和人力投入上看,一般也是无法承担的。而“裱糊匠”式做法,哪里有性能问题就加机器,加缓存,加数据库,有可用性问题就加重试,加log,出故障就加流程,加测试,这也不是雪球团队工作方式。我们一般都采用最小改动的方式,即,准确定义问题,定位问题根源,找到问题本质,制定最佳方案,以最小的改动代价,将问题解决到可接受的范围内。

 

我们现在正在所有的地方强推3个数据指标:qps,p99,error rate。每个技术人员对自己负责的服务,一定要有最基本的数据指标意识。数字,是发现问题,定位根源,找到本质的最重要的依赖条件。没有之一。

 

我们的原则:保持技术栈的一致性和简单性,有节制的尝试新技术,保持所有线上服务依赖的技术可控,简单来说,能 hold 住。

能用cache的地方绝不用db,能异步的地方,绝不同步。俗称的:吃一堑,长一智。

 

特事特办:业务在发展,需求在变化,实现方式也需要跟着变化。简单的来说:遗留系统的优化,最佳方案就是砍需求,呵呵。

当前,雪球内部正在推行每个模块的方案和代码实现的 review,在 review 过程中,我一般是这样要求的:

 

技术方案:

 

  • 20倍设计,10倍实现,3倍部署
  • 扩展性:凡事留一线,以后好相见

 

技术实现:

 

  • DevOps:上线后还是你自己维护的项目,实现的时候记得考虑各种出错的处理
  • 用户投诉的时候需要你去解释,实现的时候注意各种边界和异常
  • 快速实现,不是“随便实现”,万一火了呢:性能,方便扩容

     


 

Q&A

 

Q1:im能详细讲下吗?


关于雪球 im 和推模式,有群友问到了,我就再展开讲一下(其实下周我约了去给一家号称很文艺的公司内部交流IM实现):雪球自己设计了一套 IM 协议,内部使用 netty 做网络层,akka 模式,即为每一个在线的 client new 一个 actor ,这个 actor 里面保持了这个在线 client 的所有状态和数据。如果有新消息给它,代码里只要把这个消息 tell 给这个 actor 即可。actor 里面会通过 netty 的 tcp 连接推给实际的 client。

 

Q2:问一个小问题,App的接口可用上报里 如果是网络问题引起的故障 怎么兼容?


app 如果发起一个请求,因为网络问题失败了(这其实是我们的上报体系设计时,最主要针对的场景),那么 app 会把这个失败的请求记录到本地内存,等下一次发请求时,把上次的这个失败请求结果及相关信息带上。如果连续多次失败,当前我们的做法是,只记录最后一次失败的请求结果,下次成功的请求里会带上它。

 

Q3:监控系统为何从zabbix切换到openfalcon,原因是什么?


简单来说,机器数上百之后,zabbix就会有很多问题,个人感受最大的问题是,新增 key 非常不方便。小米因为这些问题,自己做一个 falcon,然后开源了。我们碰到的问题很类似,看了看小米的,觉得可以不用自己再折腾了,就用它了。

 

Q4:前置模块的Hazelcast In-Memory Data Grid 的稳定性怎么样,采用的考虑是什么呢?用sharding redis 怎么样呢?


稳定性不能算很好,只能说还好。因为上线几个月,已经出了一次故障了。采用它,主要是开发简单,因为它就只有一个 jar 包依赖,不像其它备选项,一个比一个大。至于为什么不用 redis,因为这是要部署到别人的内网的啊,更新很麻烦的啊,运维几乎没有的啊,各种悲剧啊。我们当前为了做到“一键更新”,把shell脚本和所有jar包都打成一个自解压的文件这事我会随便说吗?

 

Q5:雪球im如何判断用户是否在线?要给给定的用户发消息,怎么找到对应的actor?不在线的时候消息如何存储?

 

IM 用户在线判断(转化成指定的 actor 是否存在)和路由,这些都是 akka 内置提供的,感兴趣的,算了,我个人建议是不要去碰 akka 这货。用户不在线的时候,消息会进 mysql 和 redis

 

Q6:大师,为了支持失败重试,需要将主要的资源操作步骤都做成幂等。这个怎么理解,具体怎么玩?

 

举个例子:用户发一个帖子,api调用的时候已经给用户返回成功了,但后端写 db 的时候超时了,怎么办?不能再告诉用户发帖失败了吧?那就重试重试再重试,直到写 db 成功。但万一重试的时候发现,上次写入超时,实际上是已经写成功了呢?那就需要把这个写入做成幂等,支持多次写入同一条记录。简单来说,db 层就是每个表都要有业务逻辑上的唯一性检查

 

Q7:另外用户对应的Actor需不需要持久化呢?

 

actor 不持久化。重启 server 的话,app 端会自动重连的

 

Q8:基于zookeeper的config center设计有什么指导原则或遇到什么坑吗?如何方便业务开发修改又不影响到其他?

 

我们的 config center 有两个版本:一个是参考 netflix 的 archaius,另一个是纯粹的 zk style 。风格问题,我个人的回答是:大家喜欢就好。 config center 本来就不影响业务开发修改啊?没有太明白问题点,sorry

 

Q9:刚才的追问下 如果只报最后一次故障 那么会不会不能准确评估影响?

 

不会的,因为这种情况一般都是用户进电梯或者进地铁了,呵呵

 

Q10:rpc是怎么选的呢,比如为什么不用thrift呢?

 

finagle 底层就是 thrift 啊。就我个人而言,我个人对于任何需要预先定义 proto 的东西都深恶痛绝。所以现在我们也在尝试做一个基于 jsonrpc 的简单版本的 rpc 方案,作为我们后续微服务容器的默认 rpc

 

Q11:实质上是用actor包住了netty的session吧?不建议用akka的原因是量大了后承载能力的问题吗?雪球im的dau约在50万左右吧?

 

是的,actor 内部持有网络连接。不建议用 akka 的原因是:我个人的原则是,我 hold 不住的东西就不做推荐。就当前来说,我觉得我 hold 不住 akka:使用太简单太方便,但坑太多,不知道什么时候就踩上了,想用好太难了

 

Q12:唐老师您好,雪球的架构中,rabbitmq 主要用在哪些场景,rabbit的 负载是通过哪些手段来做呢?

 

当前我们的 mq 功能都是有 rabbitmq 提供的,我们在内部封装了一个叫 event center 的模块,所有的跟 queue 打交道的地方,只需要调用 event center 提供的 api 即可。我们对于 rabbit 并没有做太多的调优,大约也是因为现在消息量不大的缘故。后续我们的大数据体系里,queue 的角色会由 kafka 来承担

 

Q13:大师,能说说akka为啥不推荐么

 

看上面问题 12

 

Q14:唐大师,关于交易这块,能说下你们的账户体系吗?

 

股票交易跟支付宝模式还是很大不一样的,本质上,雪球上只是一个纯粹的通道:钱和股票都不在雪球内部。所以,我们当前的账户体系就像我们页面上描述的那样:将用户的券商账号跟雪球id做绑定

 

Q15:性能规划上有什么经验或者推荐资料阅读吗?谢谢。

 

通读 allthingsdistributed 上的精华文章 http://www.allthingsdistributed.com/

 

Q16:唐大师,雪球的docker是怎么用?怎么管理的?

 

参考雪球sre高磊在 dockercn 上的分享

 

Q17:追加一个问题:对业务合规要求的需求不是很了解,但是“-XX:+DisableAttachMechanism -XX:-UsePerfData”这样无法禁止“jstack -F”的吧,只是禁止了普通的jstack。

 

应该是可以禁止的,因为 jvm 内部所有挂载机制都没有启动,jstack 加 -f 也挂不上去。要不我一会测一下再给你确认?

 

Q18:帮我问个问题:这么多系统,如何保证迭代保质保量按时交付?

 

这就要感谢我们雪球的所有技术,产品,运营同事们了 [Tongue]

 

Q19:为什么用kafka替换rbt?

 

因为 rbt 是 erlang 写的啊,我不会调优啊,出了问题我也不会排查啊。事实上,event center 模块极偶发的出现丢消息,但我们一直没有定位到根源。所以,只好换了

 

Q20:请问百万活跃用户session是怎么存储的?怎么有效防止大面积退出登录?

 

用户登录 session 就存在 jvm 内部。因为是集群,只要不是集群突然全部挂,就不会出现大面积重新登录的

 

Q21:每个请求里带上前一个请求的结果,这个得和用户请求绑定上吧?

 

收集 app 端的访问结果,大部分情况下用于统计服务质量,偶尔也用于用户灵异问题的追逐

 

Q22:akka的设计居然和Erlang的抢占式调度很像,也存在单进程瓶颈问题?

 

可以这么说,主要是它的 log actor 是单个的

 

Q23:集群环境下如何保存在jvm内部?各个jvm如何共享的?

 

我们的 im 系统其实分 2 层,前面有一层接入层,后面是集群。接入层到集群的链接是按 uid 一致性 hash。简单来说,一个用户就只连一个 jvm 服务节点。所以我们只在收盘后更新服务。在雪球,盘中严禁更新服务的

 

Q24:接入层的实现架构方便描述一下吗?

 

雪球IM的接入层分为2类:app接入层和web接入层。app接入层是一个 netty 的 server,开在 443 端口,但没有使用 ssl ,而是自己用 rsa 对消息体加密。netty 收到消息后,解包,根据包里的描述字段选择发往后端的业务节点。web 接入层是一个基于 play 的 webserver,实现了 http 和 websocket 接口,供 web 使用

 

(完)


 

雪球App是一款解决股票买什么好问题的手机炒股应用。因为独特的产品设计和运营策略,雪球App在市场上拥有领先的份额和影响力。雪球正在招聘,热招职位请参考 http://xueqiu.com/about/jobs (可点击阅读原文进入) 我们在望京 SOHO 等你!

 

本文策划 庆丰@微博, 内容由王杰编辑,庆丰校对与发布,Tim审校,其他多位志愿者对本文亦有贡献。读者可以通过搜索“ArchNotes”或长按下面图片,关注“高可用架构”公众号,查看更多架构方面内容,获取通往架构师之路的宝贵经验。转载请注明来自“高可用架构(ArchNotes)”公众号