ChatOps实战

ChatOps概念在国内已经有一些文章谈过,但是都处于理论范畴。而本文则是一篇ChatOps实践的文章。 有必要说明我对ChatOps的理解,ChatOps表面上就是在一个聊天窗口中,发送一个命令给运维机器人bot,然后bot根据我们预定义的操作进行执行,并返回执行结果。至于更深层次的作用,就是将重复性的手工的运维工作自动化了,开发人员、运维人员可以按需执行一些运维操作。 另外,我做到了自动化搭建这一套东西(感谢Github上那么多开源项目,让我少写很多Ansible脚本)。为什么要自动化搭建呢?因为我懒,我不想每次通过一条条shell手工搭建。 本文主题 在RocketChat的聊天窗口中命令Hubot执行一次Jenkins构建任务。 工具介绍 有必要简单说明一下我们此次实现ChatOps的这几个工具。 RocketChat 可以把RocketChat想像成一个具有更多功能的IRC或者微信。它依赖于MongoDB,所以,我们还将自动化安装MongoDB。 如果你了解过Slack的话,它可以作为Slack的开源替代表。 Hubot Hubot是Github出品的一个运维机器人。本质上就是一个接收命令消息,执行预定义操作的一个程序。而接收命令消息的这个组件在Hubot中被称为Adapter。比如我们希望Hubot接收来自RocketChat聊天窗口里的消息,我们就必须为Hubot安装一个RocketChat的Adapter。市面上,已经有很多Adapter了,我们很少需要自己实现自定义Adapter。 那么,Hubot接收到命令消息后,怎么知道执行哪些操作呢?这部分是需要我们实现了。本质上就是通过正则表达式匹配命令消息,然后操作。实际上通过写Coffescript脚本实现。比如: robot.respond /open the (.*) doors/i, (res) -> doorType = res.match[1] if doorType is "pod bay" res.reply "I'm afraid I can't let you do that." else res.reply "Opening #{doorType} doors" Jenkins 就这个就不用多介绍了。值得一提是Github已经有不少自动化搭建Jenkins的Ansible脚本了(完全不需要人工干预),本文使用的是geerlingguy的。 Ansible 能让开发人员快速上手的自动化运维工具。我们使用Ansible实现自动化。想简单了解Anbible,可以看看简单易懂Ansible系列 —— 解决了什么。 准备环境 需要准备几台机器: IP OS 安装 192.168.61.11 CentOS7 Jenkins,Openresty(for Jenkins) 192.168.61.14 CentOS7 Openresty(for RocketChat) 192.168.61.15 CentOS7 RocketChat Server, MongoDB,Hubot 因为我是在本地做实验的,所以需要在本机虚拟化3台机器。我使用Vagrant + VirtualBox的方式来实现。具体Vagrant如何使用,不在本文讨论范围。你也可以手工在VirtualBox或Vmware上创建相应的虚拟机。Vagrant只不过是自动化了这个过程。Vagrant会基于一个称为Vagrantfile的文件来创建机器。 ...

2017-10-08 · 1 min · 205 words · 翟志军 Jack Zhai

简单易懂Ansible系列 —— 实现ssh key主机之间复制

我们在搭建Hadoop完全分布式环境时,Hadoop的name node节点(理解为master节点)需要无密码登录到所有的data node节点。 当然,我们使用手工的方式很容易就实现了: 在name node节点上生成ssh key:ssh-keygen 将public key copy到所有的data node节点上:ssh-copy-id slave1 同时,你还必须设置~/.ssh/config,以防止登录时不停的问yes or no: ```yml Host * StrictHostKeyChecking no ``` 完了,还要设置这个文件的权限为400。 以上步骤当然可以手工一步步执行。但是,总有那么一些人:希望所有的操作都可以版本化,所有的操作都应该自动化。我属于这些人。 再说了,我发现在搭建Jenkins环境时,也遇到了同样的问题:需要将Jenkins master的public key加入到Jenkins agent机器中。 可以预见到将来我还会遇到类似的问题。于是,我找到一个方法来自动化以上操作。 在name node机器上执行task如下 创建用户的时候生成ssh_key: - name: create hadoop user user: name: "{{hadoop_user}}" group: "{{hadoop_group}}" createhome: yes generate_ssh_key: yes ssh_key_bits: 2048 ssh_key_file: .ssh/id_rsa tags: - hadoop 将id_rsa.pub拉取到ansible执行机器上 - name: fetch public key fetch: src: "/home/{{hadoop_user}}/.ssh/id_rsa.pub" dest: /tmp/ flat: yes tags: - hadoop 设置StrictHostKeyChecking no 因为我们只想修改这个用户的ssh行为,所以我们的ssh的配置只是针对当前这个用户的: ...

2017-08-19 · 1 min · 157 words · 翟志军 Jack Zhai

简单易懂Ansible系列 —— 解决了什么

不知什么时候,Ansible的slogan从“IT Automation Software for System Administrators”变成了“AUTOMATION FOR EVERYONE”。 从一个给系统管理员使用的工具变成了给所有人使用的工具。 但是,现实中,发现了解Ansible的人,还是太少了。同时,自己断断续续学习Ansible也有一段时间,希望拿出来和大家交流。所以就决定不定期写写一个关于Ansible的系列。如果你觉得我写得还可以,到文末扫码请我喝杯茶。 此文为“简单易懂Ansible”系列文章的开篇 —— Ansible解决了什么 Ansible解决了什么 首先,它是一个运维工具。当然要解决运维过程中遇到的问题了。运维过程遇到了什么问题? 想像一下,你要在一台新的机器上安装Tomcat,你会怎么样呢,条件反射的: ssh [email protected] wget -c http://apache.fayea.com/tomcat/tomcat-8.5.15.tar.gz tar -zxf apache-tomcat-8.5.15.tar.gz .....省略 好,10分钟后你愉快地完成了老板给你的任务。但是现在你需要给100台机器安装Tomcat呢?手工的重复100次? 而Ansible能让我们只定义一次,理论上可以在无限台机器上执行。换句话:减少运维工作中的重复工作。 同时,如果是人工执行100次,那么失误是难免的!自动化运维工具会严格根据我们所给指令来执行,而不会因为失恋而手抖执行了:sudo rm -rf /。 不少人反对自动化,认为那样太危险,因为一不小心就在上百台机器删错文件。显然,他们没有注意到:自动化实现的是准确地执行指令,解决人类执行任务时存在的指令理解不正确、执行不严格的问题。而机器不会出现这些问题的概念几乎为零。 没有达到预期效果,往往是我们人类下达的指令不正确。 所以,Ansible还解决了人执行指令不准确的问题。 如果使用Ansible来实现上述的运维需求,怎么做呢?你需要做三件事情: 定义目标机器的列表:一种被称为inventory的类ini文件 定义这些机器的配置:使用YAML格式的文件来描述你机器的配置 执行 ansible-playbook -i inventory playbook.yml 以下是inventory文件: [tomcat-servers] 111.111.111.111 112.112.112.112 .... 而这些ip的配置写在一种被称为playbook的YAML文件中: --- - hosts: tomcat-servers tasks: - name: download tomcat get_url: url: http://apache.fayea.com/tomcat/tomcat-8.5.15.tar.gz dest: /tmp - name: unarchive tomcat to /usr/local unarchive: src: /tmp/apache-tomcat-8.5.15.tar.gz dest: /usr/local/ remote_src: true .....省略 如果你想再添加100台机器,你需要做的,也只是在inventory文件里添加100个ip,再执行一遍ansible-playbook命令。 ...

2017-06-12 · 1 min · 123 words · 翟志军 Jack Zhai

即将三十,我不敢说我精通任何一项技术

图片来源:http://www.imdb.com/title/tt0395699/ 回顾自己的技术成长之路,具体技术真心没有一样敢说精通,对于一个像我这样工作6、7年的人来说,实在有些难以启齿。 现在中国整个的技术环境看重的是技术深度,而我从一开始就认为应该先广度再深度,自然在同行中被认为是异类。我没记错的话,大神左耳朵耗子的观点就是深度优先。 为什么要广度优先,而不是深度优先。我有自己理由: 技术变化太快,当你还没有深挖到某一个框架的本质,这个框架就可能已经过时了,特别是JS框架 容易只见树木、不见森林:比如你花很多时间去研究如何分布式存储你业务应用中的文件,但是你可能不知道世界上还有AWS S3这样的东西 手里有把锤子,全世界都是钉子:精通写bash脚本的人,所有的运维工作都倾向于写bash来解决运维问题,不知道世界上还有Ansible这样方便的东西,也不知道有时候根本问题不在运维,而在开发 我说出这些理由,并不是说我们就不需要深入研究某个框架和技术,只是想说明我们的选择的优先级会决定,至少会影响我们的思维方式。 这几年,我开始输出一些体现我思维方式的文章,比如: 《耦合的本质》 《关于自动化配置还有什么好说的呢?》 《也许,这样理解HTTPS更容易》 《Puppet,Chef,Ansible的共性》 (根据自己的一次分享整理) 《信息检索中,索引的本质》 很少人发现这些文章的真正价值,因为看起来和他们的实际工作没有任何关系,这些文章不会告诉你怎么快速搭建好https环境,也不告诉你怎么用Ansible copy一个文件到所有的目标机器上。 在一次面试时一位老架构师两次问我:《耦合的本质》真的是你自己写的?显然他不相信写这篇文章的人30不到。确认之后,他说他不完全认同“耦合的本质是假设”,但是他欣赏这样的思维方式。 我头一回感觉到有人看懂这篇文章。 总的来说,这些文章体现出来思维方式是: 利用概念推导、还原事物的形成过程、找共性这3个手段来找到事物的本质,再从这个本质推导基于此事物的上层建筑。 比如我根据我们实际运维过程所要做的事情,推导出要实现自动化所要解决的问题,然后再通过“找共性”的方法,最终找到了这Puppet,Chef,Ansible 三款工具之间的共性。 但是有什么用呢?其实,找到共性后,当遇到第四种自动化运维工具Salt时,我们就很容易提问了: Salt如何与受控机器通信 如何组织机器的? 使用什么DSL来描述这些机器的配置 最后根据这些问题进行深入地学习,这样我们就可以从被动学习变成主动学习,有方法论的学习方式。甚至找到这些工具的知识边界。 然而这只是我的个人学习方式,不一定适用于所有人。也不代表我的学习方式就是好的。 我只想说明:深度优先和广度优先的选择会改变我们的思维方式。 按道理,使用这样的思维方式(有点像方法论),任何一门技术都可以做到精通,但是我目前就是没做到精通。 因为我排斥用脑袋记东西。我认为记不了的东西或者能不记的东西,它就不值得记忆。比如如何将字符串ip转成一个整型数字、Ansible里某个module的具体用法。 而现实中,我对比其他的运维人员,我发现我用Ansible用得已经非常好了,Ansible里的概念我基本已经理解透了。但是我仍然不敢说精通Ansible。我实在记不了unarchive这个module的所有参数。 所以,即将三十了,我仍然不敢说我精通任何一项技术。这成为我的困境。 这时,很多人就会说了,你应该考虑转管理了。 但是,我要问了:为什么要转管理呢? 不少人的回答: 因为你老了,你没有精力去学习更多的新语言、新框架了,你拼不过小鲜肉了。 这个观点里有,有两个假设:第一,到三十后,你学不会,或学得慢新语言、新框架是因为没有精力;第二,小鲜肉没有能力做管理; 第一点假设不成立,因为那只是借口——不想做的人,会找理由,想做的人,会找办法。第二点假设只是概率性问题,小鲜肉也可以做管理。 转不转管理,决定于你是否真的Ready好了,是否真的喜欢做管理。和你年龄没有任何关系。 说到底,写不写代码,做不做管理,都是个非常私人的问题。我们没必要那么在意别人怎么看。 最后,我深爱着写代码。这不会因为我目前或将来是否精通某项技术而改变。

2017-05-10 · 1 min · 44 words · 翟志军 Jack Zhai

为什么站会会成为形式

图截自:http://agilemanifesto.org/iso/zhchs/manifesto.html 最近,项目上遇到了以前我从来没有遇到的事情:10多个人一个团队(概念上的),要应对9个外部需求提出方;要维护超过10个子系统,这个“大系统”还是从另一个不愿意配合的团队接手过来的;项目管理者中,有倾向于敏捷的,也有倾向于瀑布的;最可怕的是这支团队完成组建才1个多月,只有3个人有站会经验,平均工作经验在7年以上😱。 所有的这些条件混合在一起,管理就变得异常复杂,困难。面对这样复杂的乱麻,谁都很难有勇气一刀切。 然而,事情还要做。比如站会。上周我自荐主持一次站会。说实在,那次站会是失败的,因为期间还是有两个人拿手机来刷。 有人拿手机出来刷,说明站会上的内容和他们无关,进一步说明站会是无效的。 但是,为什么呢?我会后一直都在思考这个问题。 我想起自己一年多前,也是带团队从零开始实践敏捷开发。为什么不会出现这样的情况? 突然,一个词蹦出来:共同语言! 站会成为形式的根本原因,就是整个团队没有共同语言!。没有共同语言使站会沦为形式。 好,现在我必须解释两个问题: 为什么整个团队没有共同语言导致站会成为形式? 为什么整个团队没有共同语言? 我先解释为什么整个团队没有共同语言,再解释为什么没有共同语言的团队站会是形式。 为什么整个团队没有共同语言 团队的沟通模型 第一个使整个团队没有共同语言的因素是:团队的沟通模型。 为了方便讨论,我们假设团队的沟通模型为: 项目管理A,对接需求方1、2、3,然后再将任务拆分给Q、W、E。项目管理B、C依此类推。 这样的沟通模型下,为什么团队成员会没有共同语言? 在这样的沟通模型下,开发人员Q平时只与A沟通需求,尽管可能私底下与其他开发人员沟通一下实现,可以说,开发人员Q与项目管理A才会有共同语言。依此类推,每个开发人员只与他的直接上级有共同语言。 我的结论是:趋向于单向沟通的团队沟通模型决定团队成员之间没有共同语言。而且这种单向沟通的结构时间越长,团队成员之间共同语言就越少!现象是,同处一个团队,你不知道你隔壁坐的同学到底在做什么。 没有统一业务术语 第二个整个团队没有共同语言的因素是:团队内部没有统一业务术语。 我们假设站会时,移动团队里的iOS、Anroid、H5三个小组一起参加同一个站会。而在站会时,iOS针对功能A使用了“激活”业务术语,而Android的同学对同一功能A却使用“上线”业务术语。 不统一业务术语不仅导致成员之间没有共同语言,导致更严重的问题是:沟通效率低下。 为什么整个团队没有共同语言导致站会成为形式 其实道理很简单,你问问自己,你喜欢与自己有更多共同语言的人交谈,还是反之?这是人性! 站会时,我们更倾向于听我们关心的,和我们听得懂的。但是因为没有共同语言,所以,我们即不关心,也听不懂! 站会当然也就是形式而已。 怎么破? 这下肯定会有人问,那为什么要站会?取消不就可以了。问这样的人是因为不了解站会的本质:站会一种团队快速反馈的机制。 至于为什么需要快速反馈,很简单:(真正有效的)每日站会的团队可以每天根据站会内容(反馈)来对人员、需求、发布时间进行调整,调整的时间是以天计。而如果只有周会的团队,那么,这个团队调整的时间是以周计,那你觉得哪种团队面对变化时更敏捷,迅速? 说回来,如何让站会更有效,而不至于成为一种形式呢? 至少可以肯定的是这不是一个主持人就能解决的。 剩下的先留给大家思考,我们下篇文章再讨论。 你也可以先读读我之前写过的文章: 每日站会、代码审查、结对编程 之开源中国实践 反馈机制在企业中的作用? 如何防止程序员上班迟到?

2017-05-07 · 1 min · 40 words · 翟志军 Jack Zhai

什么?项目延期有解药?

图片来源:link 摘要:当我们要考虑如何让项目不延期时,我们是否做到让每个员工都满负荷了?我们追求的是不延期,还是追求更卓越的产品? 这一两个星期和同事讨论如何使用看板进行项目管理时,总的来说,我遇到最频繁的问题有: 如何能看出项目是否延期? 如何拆任务? 其实,我遇到的问题是:如何能看出项目是否延期?然后经我将问题深挖,才发现他们更本质的问题是:拿到需求,如何拆任务,拆到什么粒度。 讨论这类问题,最好举个例子,否则整个讨论过程会很虚。 比如我们的项目经理从产品经理那里拿到一个需求:改版APP。这款APP有12个界面,所有的界面都需要改。而你手下有6个人。 这时,可以以两种粒度来拆分: 以界面为粒度 拆分成更可以量化的粒度。 关于什么是可以量化的粒度,下文会阐述。 按界面粒度来拆分 可以看出,以界面粒度来拆分,简单粗暴:24人天的任务,我们有6个人,所以,理论上我们只需要4天完成“改版APP”。我们可以很容易看出这个项目是否延期,只要每个界面都没有延期。 放到看板上,理所当然,每个界面一张卡。 现实中,我们的项目经理可能还会这样分到人头上: 为什么一定要分到人头上?除了方便KPI(表面上),背后还有一定的文化因素:因为当项目延期时,我们就可以找出那个相应的人进行问责。这种问责的机制导致的后果:人们更愿意推卸责任,而不是共同协作。 放大一些这个问题,公司内部多个技术部门也会因为这种问责的文化,导致部门之间更趋向责怪对方不按期,而不是共同协作完成一件事情。 再再放大一些这个问题:在人们的意识里往往认为,问责后,坏的事情就可以避免问题再发生。放到我们本篇文章讨论的上下文里,也就是问责可以避免延期。但是,可能吗?因为延期已经发生,我们应该在延期发生前进行协调资源来解决延期。 我们举个例子:在项目进行的过程中,人员B在做界面3,4时,在第3天时被一个问题卡住了。而人员C其实在第3天时就已经完成了,第4天开始优化。其他人准时完成了自己的任务。最后人员B的延期导致项目延期了2天。这时,如果你问责人员B,那么,这次的延期能倒退吗?也许你会说,问责后,这个人下次就不会延期了。 我想说: 延期不延期和你问责没有任何关系。如果有关系,你在项目开始时,就每个人问责一下,这样项目就不会延期了? 我们应该追求的是每个项目都不延期,而不是下一个项目不延期 我们追求的是不延期,还是追求更卓越的产品? 回头看这次延期,也许我们是可以避免的,比如在第3天的站会上,人员C说出自己被某个问题卡住了。这时,可能其他人员一句话就点通人员C的问题了。还有可能是人员C遇到的问题是需要其它部门来协助才能根本解决,这时项目经理就需要与其它部门沟通了。 回到问题“按界面粒度来拆分任务”这个问题本身。 将界面再拆分成可量化的粒度 这种方式要我们的项目经理拿到需求后,让最熟悉这个APP的人或团队对需求再进行拆分成一系列工作单元,然后再分别估算这些工作单元在现有的人员基础上需要多少天。最后估算出一个总的交付时间点。我们假设完成这个需求,我们同样需要4天完成。 至于拆分到什么程度,就是我们上文提到的可量化的程度。 什么叫可量化? 上面我们看到将需求拆分成一系列工作单元后,我们可以更灵活的安排优先级。同时,这样也帮助我们发现界面1和界面2有一个工作单元3是有交集的。有交集的工作单元,我们应该让同一个人来完成以避免其中的沟通成本。总的来说,拆分成一系列可量化的工作单元后,我们可以: 更灵活的优先级调控 发现有交集的工作单元,也就能发现可减少沟通成本的空间。 但是,什么样的工作单元叫可量化? 代码行数是最简单的,估计完成APP改版需要写10万行代码。一个工作单元,我们定1万行?这种工作单元是可以量化,但是写完那么多行代码,你就是完成APP改版这个任务了? 我们举个例子来说明什么样的工作单元叫可量化,比如对于界面1,我们需要: 把“完成”按钮的颜色从绿色改成蓝色 当完成值为100时,不显示100,显示成“恭喜,已完成” 缓存从服务器获得的任务完成值,对于多次操作,只向服务器请求一次,以提升用户操作的流畅感 从这个例子,我们可以看出,每个工作单元都应该是: 准确的:将绿色改成蓝色,而不是红色 不可分割的:不显示100,显示成“恭喜,已完成”,这个工作单元,你不能再分割了 体现了业务含义:代码行数并不能体现业务含义,但是提升用户操作的流畅感有业务含义的。 可量化的工作单元、站会与看板 有了可量化的工作单元后,再结合站会和看板,这样,我们每天都可以知道(可视化)团队的工作状态了。延不延期,大家都可以看得到,大家都是成年人了: 谁做得快,谁捡更多的卡来做的。而且可以捡优先更高的卡先做,也降低延期的风险。我们可以从这个过程中识别人才。 站会的第3天,人员B还在做_#3_卡,我们其他成员可以加快速度做其它卡以弥补人员B的慢速度,同时项目经理也可以更早的介入这个可能延期的卡中帮助人员B 当出现质量问题时,人员D的卡会被打回Todo多次,因为有站会,我们所有人都很感觉到_#5_这张卡可能存在一定难度或者人员D在协作方式存在问题,这时,我们其他人就会主动帮助人员D解决问题,而不是责怪他。 慢慢地,团队的协作方式变得以解决问题为导向,而不是以问责为导向。 拆分成可量化的工作单元,一样会延期 但是,我个人的经验看来即使我们将需求拆分成可量化的工作单元,项目一样可能会延期。 看板只能帮助我们更可视化,更容易地了解到项目当前的状态,对于这个状态,我们的项目经理要如何反应,完成是个人问题了。 同时,看板也能帮助我们找到延期的根本原因,比如是某个人的卡在In Progress上拖了很长时间、某个人请假了、其它部门中间改需求了、项目人员在某项技术的能力问题…… 所以,要延期的项目一定会延期,我们应该正确面对,找到原因并根本解决。我们要做的只是保证每个人每个工作日都是满负荷的。 这里,留给大家一个思考题:如果其它外部条件不变,每个人每个工作日都是满负荷了?如何不延期? 拆成可量化的工作单元会增加项目经理的工作量? 然而,又会有人说了,这么多项目,我每个项目都要拆分成可量化的,我们项目经理会增加很多工作量。 其实,如果真的有作用了,这些工作量是值得的,只要你真的理解可量化工作单元的作用。同时,当出现多个项目时,你忙不过来时,说明现在是你培养另一个项目经理的时机了。你可以尝试将一些项目管理的工作交给团队成员来完成。但前提是项目经理本身也是超负荷工作,影响正常工作了。 小结 想让项目不延期,我们首先关注的是如何将需求拆分成可量化的工作单元,然后想办法保证这些工作单元真正被有效的执行。办法通常可以有: 使用看板可视化所有的工作单元 通过站会了解工作单元执行过程可能的风险 通过协作来取长补短 通过优先级来降低延期时的风险 通过打包有交集的工作单元减少沟通成本 通过以上方法可以将团队“调”到可能的最优状态。但是如果还是延期,原因可能就不在团队了。 ...

2017-04-14 · 1 min · 68 words · 翟志军 Jack Zhai

如何防止程序员上班迟到?

P.S. 这里的“迟到”指的是故意迟到。 看看满大街的招聘信息上都写着: 弹性上班,不打卡 我们还有必要思考如何防止程序员上班迟到吗?我不讨论有没有必要,因为肯定有不少公司存在员工上班迟到的同时,没把事情做好的。 也许你又会问了:如果是这样,上KPI不就好了,给他一个活,规定好时间不就可以了? 这个问题,我觉得不在本文讨论范围内。我只想讨论:如何防止程序员上班迟到。 了解我的人,都知道,当我遇到问题时,我往往先想的是为什么,然后再想怎么。只有知道为什么,才能根治。 那么他们为什么要迟到呢?这个问题似乎是无解的。就似常常迟到的小学生,被老师问起原因一样,每个小学生,每一天都有自己的理由。 好吧,对于似乎无解的问题,我们暂且放一放。 回到问题本身:怎么“防”? 一提这个问题,绝大数人就想到了:上打卡机呗。 以前,我也是这绝大数人的其中一个。可是最近,另一个疑问进入到我的大脑: 为什么去年我带团队时,没有迟到现象? 晨会——这个词突然击中我。是的,因为团队每天早上上班时间点过20分钟都会准时进行晨会。 晨会就是指所有团队成员站着过任务卡,晨会一般都会很短。好处什么的,具体可以看我的另一篇博客:每日站会、代码审查、结对编程 之开源中国实践 晨会是如何“防止”程序员上班迟到的呢? 因为我们团队达成一致:上班时间点过20分钟进行晨会。假如10点上班,你一个人10点20了还没来到,你好意思吗? 不知道有人想到其中的腻味?人是会不好意思的,在团队这个交际圈里,除非你不想在这个团队待了。换句话说,这样的晨会在一定程度上利用了人性对交际的焦虑来实现“防迟到”。 但是,我要申明,我要申明,我要申明:晨会的真正目的不是为了防止程序员上班迟到!晨会达到自己的目的的同时,恰好解决了“迟到”这个企业难题。 有人会问,为什么10点上班,10点20才开始晨会?因为我们需要给团队成员一点时间进入工作状态,给团队成员一些空间融合。 小结 做水利工程时,与其围堵,不如疏导。这样的战略方针,在企业管理中同样有用。我们在思考如何“防”时,不应该只想着如何围堵,疏导可能是更好的解决方案。而晨会就是一种疏导方案。 题外话,员工为什么会故意迟到?这是另一个有更有深度的问题,留给大家。:)

2017-03-03 · 1 min · 25 words · 翟志军 Jack Zhai

我从Airbnb联合创始人的Talk里学到的

P.S. 如果你没有了解过互联网产品,下文可能不适合你,因为我没打算写得能让所有人都懂。 Airbnb,就不详细介绍了。而Joe Gebbia则是这家公司的首席产品官兼共同创始人。 他在Ted上有一个Talk:How Airbnb designs for trust。而在网易公开课上翻译成:如何与陌生人建立信任? 这个标题翻译得是否合适,仁者见仁了。 但从Talk本身,我学到了不少关于**“做产品”**的东西。以下是我所学到的,但对你来说这是二手知识,推荐你自己先看一遍视频,再继续阅读本文。 是什么驱动产品设计 我们的社会从小给就我们灌输了陌生人 = 危险的观念。同时,家是一个人最私密的地方,你怎么才会将这个私密的地方公开给一个陌生人住呢? 而Joe知道Airbnb这款产品的本质是什么。是信任!如果不打破人们陌生人=危险这个观念,Airbnb不可能成功(至少当前是成功的)。 他们(似乎)研究了如何增加陌生人之间的信任。Talk中,他说: 事实证明:一个精心设计的信誉体系,是建立信任的关键。 P.S. 我想到了支付宝 然后才有Airbnb不一样的评论机制:只有房东和租客都评论后,评论才展示。这里有个问题需要你来思考:为什么要这样控制评论的展示时机?而不是追求评论数?哈哈。 说到这里,我最想说的是:原来这就是产品的本质驱动产品设计。 但是怎么做? 但是当我们知道产品的本质后,如何做?或者说是如何在做产品的过程中慢慢发现这个本质? Talk中,Joe说了Airbnb与斯坦福大学合作。不知道怎么合作,反正他们发现: 我们更喜欢与我们相似的人,与我们差异越大,我们越是不信任他们。这是人们与生俱来的天性。正确的设计可以帮助我们克服人们扎根心底的认知偏见。 P.S. 看到这里,我第一反应是:他们怎么会想到和大学合作? 最后,他们通过数据分析发现: 当评论大于10条时,高的信誉评论比高的相似度更可信! 房客的自我介绍是如何影响自己的被接受率的 是的,通过数据分析,我们就可以做各种实验并进行实验对照,以找到增加陌生人之间的信任度的方法。 这似乎是个老掉牙的问题了。 亲近你的用户 产品初期,Joe用自己的手机号码做起了客服。所以,他才会知道现有产品会有哪些不足。 这也是个老掉牙的问题了。 后记 上文绝属我个人虚构,Joe是不是这样想的,只有他知道。😂 本次Talk还有讲共享经济,而我只说了“做产品”这部分。 部分内容摘自字幕,如有侵权,麻烦告知。谢谢。

2017-02-24 · 1 min · 40 words · 翟志军 Jack Zhai

也许,这样理解HTTPS更容易

摘要:本文尝试一步步还原HTTPS的设计过程,以理解为什么HTTPS最终会是这副模样。但是这并不代表HTTPS的真实设计过程。在阅读本文时,你可以尝试放下已有的对HTTPS的理解,这样更利于“还原”过程。 我们先不了聊HTTP,HTTPS,我们先从一个聊天软件说起,我们要实现A能发一个hello消息给B: 如果我们要实现这个聊天软件,本文只考虑安全性问题,要实现 A发给B的hello消息包,即使被中间人拦截到了,也无法得知消息的内容 如何做到真正的安全? 这个问题,很多人马上就想到了各种加密算法,什么对称加密、非对称加密、DES、RSA、XX、噼里啪啦~ 而我想说,加密算法只是解决方案,我们首先要做的是理解我们的问题域——什么是安全? 我个人的理解是: A与B通信的内容,有且只有A和B有能力看到通信的真正内容 好,问题域已经定义好了(现实中当然不止这一种定义)。对于解决方案,很容易就想到了对消息进行加密。 题外话,但是只有这一种方法吗?我看未必,说不定在将来会出现一种物质打破当前世界的通信假设,实现真正意义上的保密。 对于A与B这样的简单通信模型,我们很容易做出选择: 这就是对称加密算法,其中图中的密钥S同时扮演加密和解密的角色。具体细节不是本文范畴。 只要这个密钥S不公开给第三者,同时密钥S足够安全,我们就解决了我们一开始所定问题域了。因为世界上有且只有A与B知道如何加密和解密他们之间的消息。 但是,在WWW环境下,我们的Web服务器的通信模型没有这么简单: 如果服务器端对所有的客户端通信都使用同样的对称加密算法,无异于没有加密。那怎么办呢?**即能使用对称加密算法,又不公开密钥?**请读者思考21秒钟。😜 答案是:Web服务器与每个客户端使用不同的对称加密算法: 如何确定对称加密算法 慢着,另一个问题来了,我们的服务器端怎么告诉客户端该使用哪种对称加密算法? 当然是通过协商。 但是,你协商的过程是没有加密的,还是会被中间人拦截。那我们再对这个协商过程进行对称加密就好了,那你对协商过程加密的加密还是没有加密,怎么办?再加密不就好了……好吧,进行鸡生蛋蛋生鸡的问题了。 如何对协商过程进行加密 新问题来了,如何对协商过程进行加密?密码学领域中,有一种称为“非对称加密”的加密算法,特点是私钥加密后的密文,只要是公钥,都可以解密,但是公钥加密后的密文,只有私钥可以解密。私钥只有一个人有,而公钥可以发给所有的人。 虽然服务器端向A、B……的方向还是不安全的,但是至少A、B向服务器端方向是安全的。 好了,如何协商加密算法的问题,我们解决了:使用非对称加密算法进行对称加密算法协商过程。 这下,你明白为什么HTTPS同时需要对称加密算法和非对称加密算法了吧? 协商什么加密算法 要达到Web服务器针对每个客户端使用不同的对称加密算法,同时,我们也不能让第三者知道这个对称加密算法是什么,怎么办? 使用随机数,就是使用随机数来生成对称加密算法。这样就可以做到服务器和客户端每次交互都是新的加密算法、只有在交互的那一该才确定加密算法。 这下,你明白为什么HTTPS协议握手阶段会有这么多的随机数了吧。 如何得到公钥? 细心的人可能已经注意到了如果使用非对称加密算法,我们的客户端A,B需要一开始就持有公钥,要不没法开展加密行为啊。 这下,我们又遇到新问题了,如何让A、B客户端安全地得到公钥? 我能想到的方案只有这些: 方案1. 服务器端将公钥发送给每一个客户端 方案2. 服务器端将公钥放到一个远程服务器,客户端可以请求得到 我们选择方案1,因为方案2又多了一次请求,还要另外处理公钥的放置问题。 公钥被调包了怎么办?又是一个鸡生蛋蛋生鸡问题? 但是方案1有个问题:如果服务器端发送公钥给客户端时,被中间人调包了,怎么办? 我画了张图方便理解: 显然,让每个客户端的每个浏览器默认保存所有网站的公钥是不现实的。 使用第三方机构的公钥解决鸡生蛋蛋生鸡问题 公钥被调包的问题出现,是因为我们的客户端无法分辨返回公钥的人到底是中间人,还是真的服务器。这其实就是密码学中提的身份验证问题。 如果让你来解决,你怎么解决?如果你了解过HTTPS,会知道使用数字证书来解决。但是你想过证书的本质是什么么?请放下你对HTTPS已有的知识,自己尝试找到解决方案。 我是这样解决的。既然服务器需要将公钥传给客户端,这个过程本身是不安全,那么我们为什么不对这个过程本身再加密一次?可是,你是使用对称加密,还是非对称加密?这下好了,我感觉又进了鸡生蛋蛋生鸡问题了。 问题的难点是如果我们选择直接将公钥传递给客户端的方案,我们始终无法解决公钥传递被中间人调包的问题。 所以,我们不能直接将服务器的公钥传递给客户端,而是第三方机构使用它的私钥对我们的公钥进行加密后,再传给客户端。客户端再使用第三方机构的公钥进行解密。 下图就是我们设计的第一版“数字证书”,证书中只有服务器交给第三方机构的公钥,而且这个公钥被第三方机构的私钥加密了: 如果能解密,就说明这个公钥没有被中间人调包。因为如果中间人使用自己的私钥加密后的东西传给客户端,客户端是无法使用第三方的公钥进行解密的。 话到此,我以为解决问题了。但是现实中HTTPS,还有一个数字签名的概念,我没法理解它的设计理由。 原来,我漏掉了一个场景:第三方机构不可能只给你一家公司制作证书,它也可能会给中间人这样有坏心思的公司发放证书。这样的,中间人就有机会对你的证书进行调包,客户端在这种情况下是无法分辨出是接收的是你的证书,还是中间人的。因为不论中间人,还是你的证书,都能使用第三方机构的公钥进行解密。像下面这样: 第三方机构向多家公司颁发证书的情况: 客户端能解密同一家第三机构颁发的所有证书: 最终导致其它持有同一家第三方机构证书的中间人可以进行调包: 数字签名,解决同一机构颁发的不同证书被篡改问题 要解决这个问题,我们首先要想清楚一个问题,辨别同一机构下不同证书的这个职责,我们应该放在哪? 只能放到客户端了。意思是,客户端在拿到证书后,自己就有能力分辨证书是否被篡改了。如何才能有这个能力呢? 我们从现实中找灵感。比如你是HR,你手上拿到候选人的学历证书,证书上写了持证人,颁发机构,颁发时间等等,同时证书上,还写有一个最重要的:证书编号!我们怎么鉴别这张证书是的真伪呢?只要拿着这个证书编号上相关机构去查,如果证书上的持证人与现实的这个候选人一致,同时证书编号也能对应上,那么就说明这个证书是真实的。 我们的客户端能不能采用这个机制呢?像这样: 可是,这个“第三方机构”到底是在哪呢?是一个远端服务?不可能吧?如果是个远端服务,整个交互都会慢了。所以,这个第三方机构的验证功能只能放在客户端的本地了。 ...

2017-02-20 · 1 min · 110 words · 翟志军 Jack Zhai

我故意写了个死循环

导致CPU100%的原因很多,而程序中出现死循环就是原因之一。然而,并不是每个人在工作中都有机会踩中这个坑。我就是其中一个没踩过的。人生似乎有些不完整。 所以,我做了一个很重要的决定:在程序中写一个死循环。看看会发生什么事情。 当然,不是在生产环境。😜 我搭建了一个实验环境来做实验。只是这个实验环境不仅可以用于这个死循环实验。以下是这个环境的结构图: 还是老样子,使用Vagrant + Virtualbox + Ansible自动化搭环境。代码及搭建步骤在文末。 我们会写一个简单的Spring MVC 应用,然后其中一个接口里会有死循环代码: @RequestMapping(value = "/loop", method = RequestMethod.GET, produces = "application/json; charset=UTF-8") public void endlessLoop() { int i = 0; while (true) { System.out.println(i += 1); } } 以下是我自己尝试找出这个死循环的过程。 使用top,查看是哪个进程的问题 我请求一次:http://192.168.88.10:9898/web/loop 然后,我打开新窗口,又请求一次 这里,我好奇CPU没有到200%。一直在120%和130%之间。P.S. 我一定是某个知识点不牢固,要不,不会有这个疑问。 堆空间 因为不涉及JVM堆空间问题,执行 jstat -gcutil 32593 1s 没看出什么问题。32593为Java进程ID,1s指1秒抽样一次。 栈 堆没问题,就看看是哪个线程占用得高。 列出java进程的线程,top -H -p <java 进程pid> 将jvm的栈dump下来 jstack -l <其中一个线程PID> >> stack.log,这里我选3596。 ...

2017-02-17 · 1 min · 102 words · 翟志军 Jack Zhai