谈谈创业公司的技术选型

txsq9181 8年前
   <p>从公司成立第一天起,我们就以 Google 的技术标准要求团队,鼓励使用新技术、鼓励重新造轮子、鼓励全栈,同时因为业务涉及视频、电商、社交多个领域,我们在创业环境下对微服务、DevOps、自动化测试和部署、搜索、交易、数据监控、直播技术方面的技术选型积累了一定经验。非常高兴能把这些经验分享给各位同在创业的小伙伴。</p>    <h2><strong>我们的技术选型原则</strong></h2>    <p>技术选型对创业公司至关重要,好的选型会让你少走弯路,产品更快推向市场,比竞争对手更快赢得客户,获得更多融资,有更多资源投入产品研发和市场扩展 … 如此往复形成良性循环。相反,每一个错误选型都会带来巨大的技术债务,我知道一些创业公司把 demo 时的选型一直用到 A 轮甚至 B 轮,然后不得不停下业务花几个月时间去重构整个系统。</p>    <p>可以说,对初创团队的技术 leader,最重要的事情就是选择正确的技术体系。</p>    <p>下面是我们技术选型的三个原则:</p>    <h3><strong>一、利用好创业公司技术选型的后发优势</strong></h3>    <p>大公司的基础设施往往超过 N 年没有更新,在建立之初可能是前沿的,但很多已经远落后社区,而且因为所谓的稳定性和技术栈的统一,不允许团队使用最新的技术。创业了,就打开了所有的禁忌,do what the fuck you want,只要你精挑细选,总有一款工具是最适合你的。工具不仅能提高工程师的生产力,工具更定义了你的工作模式,选择你的工具,而不是被工具选择。</p>    <p>这对从大公司出来的技术 leader 尤为重要,把之前 BAT 的那套放在脑后,重新出发,你的面前就会打开一扇宝库大门。</p>    <h3><strong>二、第三方付费服务很多不靠谱,小心绕开雷区</strong></h3>    <p>花钱买的未必就好,有时候花钱买来的是坑,还得自己填。第三方服务,小的不稳定,大的没法订制,提个需求都可以排到两个月后了。这里的名单很长,特别留心那些给无线开发者提供的服务,很多不靠谱。</p>    <p>解决方案:让第三方服务成为可动态配置的组件,多个服务方互备,配置而不集成。比如我们的 SMS 推送服务就使用了多个服务互备,极大降低了短信丢失率,另外可以通过配置随时替换服务方,降低了对单一服务方的依赖。</p>    <h3><strong>三、自力更生、重造轮子</strong></h3>    <p>因为轮子是你的车最重要的组件,同时没有哪个轮子合适装在你的车上,你的车是独一无二的喷气火箭战车。我不是说你需要重写 MySQL 或者 CDN,而是把你的业务系统中除了网络和存储的组件自己开发,从交易到账号到搜索到推送系统,网络和存储交给公有云并克制在这块造轮子的冲动。</p>    <p>你应该重写 leancloud,重写 fir.im,重写 elasticsearch,而且要在两周内完成。如果你对此嗤之以鼻,说明你没找到最优秀的工程师,或者是他们的野心还没有被发动。相信我,这不难,我们已经这样做了而且比使用外部服务更好。</p>    <p>创业,要有“无论什么技术我们都可以实现而且比其他人做的更好”的信念,这是创业赋予你最大的自由,抓住这个自由。</p>    <h2><strong>我们选择的技术</strong></h2>    <p>下图是我们后台系统选择的一部分技术栈: </p>    <p><img src="https://simg.open-open.com/show/a0c81b53b196bc6b6a319e9aa3a82412.jpg"></p>    <h3><strong>一、Go 语言</strong></h3>    <p>我经历过的两家公司, Google 主要用 C++,阿里用 Java。前者是一种存在天生设计缺陷的语言,而且 C++ 的开发效率真不算高,即使是对 Google 这样的工程团队,也做了 Style Guild 来规避 C++ 存在的雷区。 而 Java 过于臃肿,缺乏原生的多线程支持,运行环境庞大不适合容器化微服务,如果你给 Java 程序打过 docker 包就知道了,动辄上百兆的运行时。</p>    <p>从创业的第一天,我们选择 Go 作为后台系统开发语言,现在看来是我们做过的最好的决定之一。Go 的优点包括:原生支持多线程编程,可编译为 standalone binary 无需运行时环境(docker 镜像一般 10 几兆就搞定了),自带格式化工具能够统一团队的编程风格,极适合写微服务,而且学习上手快,Java 或者 C++ 程序员只要一个星期就可以达到熟练运用的水平。</p>    <p>创业以来我们用 Go 从头实现了整套后台系统,包括 RTMP 直播服务器、用户体系、交易、IM、搜索、监控、小二后台,我们甚至用 Go 写机器学习代码和机械臂控制程序(我们在用的 Google 的tensorflow 最近也加入了 Go 语言支持) … 实践证明 Go 完全可以胜任所有的后台开发工作,而且有极高的效率和工程实现质量。</p>    <h3><strong>二、Kubernetes</strong></h3>    <p>我们是微服务的坚定践行者,微服务技术的核心是容器编排系统,现在最流行的三个容器编排系统是 Kubernetes,Mesos,Swarm。</p>    <p>通过比较我们选择了 Kubernetes(简称 k8s),因为 Kubernetes 的设计最吸引我们,有 Google 支持,社区活跃度和发展前景俱佳。我们整个后台系统基于 Kubernetes,并且已经完全微服务化,有 80 多个微服务数百个容器在运行。</p>    <p>我们在实战中使用 Kubernetes 的几点经验如下。</p>    <p>1、二进制版本和配置版本要做分离,且代码化</p>    <p>微服务的配置 yaml 文件 checkin 到 git 代码库,而且做 binary/config 分离,分别控制二进制和配置环境的版本,所有的线上部署的改动都在代码中反映出来。举个 k8s 中微服务配置的例子,如下图。 </p>    <p><img src="https://simg.open-open.com/show/6849662ad2c03ed11977953de12abf3e.jpg"></p>    <p>这是我们一个微服务的 deployment 文件,我们用 git 的版本号做 docker 镜像的 tag(jenkins 自动打包后加上去的),docker 镜像里只包含 binary 文件,配置文件通过 configmap 的 volume mount 为容器内的一个目录,而且配置文件也做了版本号控制,数据库密码等不走代码,而是由集群管理员手工输入为 kubernetes 的 secret,不留任何记录,从而避免了敏感信息的泄露。</p>    <p>2、集群管理</p>    <p>考虑混合云上多 k8s 集群的管理需求,我们用 zone 来标识不同数据中心的 kubernetes 集群,zone 由三个字母标识,如下图 </p>    <p><img src="https://simg.open-open.com/show/f8456a80e0831a86cff0d3eedf56dc8a.png"></p>    <p>通过三字母标识法,我们将混合云部署统一化,极大方便了代码和文档中的服务标识。</p>    <p>3、使用 Namespace</p>    <p>Kubernetes 的 namespace 极有用,我们用 production namespace 指代生产环境,staging 指代预发,kube-system 指代集群系统级别的服务比如 DNS、prometheus 监控和报警等。</p>    <p>另外 k8s 也支持通过 namespace 的 node selector 来指定某个服务需要运行在哪类机器节点上,这样就可以将预发和生产环境运行在不同的机器上,做到不同环境的资源隔离。</p>    <p>4、基于 DNS 的自动化服务注册、发现和负载均衡</p>    <p>通过 skyDNS 就可以将一个服务的分布在不同服务器上的 instance 命名归一化,比如通过调用 ama-server.production.svc.k8s:20001 就可以将调用请求自动路由到某个服务节点上,调用端不需要关心服务是怎么部署的,服务注册和服务发现自动完成。</p>    <p>关于 Kubernetes 和微服务化还有很多细节,如果有机会再分享给大家。</p>    <h3><strong>三、Prometheus 和 Grafana 监控系统</strong></h3>    <p>如果你知道 ELK,那 Prometheus+Grafana 实现了一套更为优秀的数据监控系统。比如我们在 gRPC 服务的 /metrics 下添加了类似下面的指标来监控 RPC 性能: </p>    <p><img src="https://simg.open-open.com/show/8208d4f90656bb28049d72fff4cf93c5.jpg"></p>    <p>然后 prometheus 会根据 kubernetes 的配置自动找到这些 metrics,我们设置这样的语句进行计算 </p>    <p>最后在 Grafana 里通过这样的界面展示出来: </p>    <p><img src="https://simg.open-open.com/show/7be0e405ad24aa755b02036e89bda6a3.jpg"></p>    <p>如果你在 Google 工作过会心中窃喜,这不就是 Google 的 Borgmon 嘛!对的,Prometheus 就是由一位 xoogler 工程师写的,参考了 Google 内部数据监控系统的设计。</p>    <p>这套体系和 ELK 相比较轻,且非常容易扩展,我们写了几个模块把服务日志和前端访问记录融合在一起做分析,同时 Prometheus 指标描述能力非常强大几乎可以做任何运算(事实上这种语言是图灵完备的)。</p>    <h3><strong>四、gRPC</strong></h3>    <p>集群内部服务间通讯我们用 Google 开源的 gRPC,最近出了 1.0 稳定版。你可能听说过无数个基于 protobuf 的 RPC 实现,请放弃它们转用 Google 自己的 gRPC 吧。</p>    <h3><strong>五、Github</strong></h3>    <p>我们用 Github 做代码仓库,她的用户分组和权限管理很有用,而且支持通过 webhook 提醒 Jenkins 完成后续的持续集成工作。</p>    <p>使用 Github 的另一个好处是,当你想把一个内部项目开源时,只要点几个按钮就可以了,后续开发流程不变,无缝衔接。</p>    <h3><strong>六、Phabricator</strong></h3>    <p>非死book 的一款项目管理工具,我们用它做文档中心和代码审查工具。</p>    <h3><strong>七、Bearychat</strong></h3>    <p>非常好用的团队沟通工具,好到让你想放弃邮件沟通,因为这比写邮件快多了。我们建了几十个频道,大家分组针对特定话题做深入讨论。而且 bearychat 支持机器人,可以把各种系统通知平滑衔接进来,ChatOps 的利器。</p>    <h3><strong>八、Jenkins</strong></h3>    <p>我们在 Jenkins 上做微服务和 iOS/Android app 的测试和打包,可以说 Jenkins 是整个持续集成的枢纽,任何的代码改动都可以从这里触发后续行为,从 docker 自动打包,到推送 bearychat 消息提醒,到服务或 app 发布等。</p>    <h3><strong>九、Bugtags</strong></h3>    <p>付费服务,帮助我们组织测试环节的部分工作流程,避免上线前遗漏 bug fix。</p>    <h3><strong>十、Whiteboard </strong></h3>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/33679b564d9c087150adc8bbcc8ef1ef.jpg"></p>    <p>就是白板啦!我们将任务分解为原子 task,子团队纵切(产品、UED、前端、后端),任务状态横切(待开始、进行中、blocked、完成),不同迭代版本使用不同颜色,每日晨会更新,进度一目了然,“石器时代”的技术选型还是那么有效 :)</p>    <p>最后的话</p>    <p> </p>    <p> </p>    <p> </p>    <p>来自:http://mp.weixin.qq.com/s?__biz=MjM5ODIzNDQ3Mw==&mid=2649966152&idx=1&sn=af685139039907fddcd73cab2b63f03f&chksm=beca364e89bdbf5854e3e517fc49577e3d322ef0bb1cc5a38ab47f5971f1149e18462a98e261&scene=0</p>    <p> </p>