Freedom

淡泊以明志,宁静以致远。

A Little Throught About Microservices

知乎在 4 年前已经开始尝试服务化,至今也经历了好几个架构的变迁演化。我大约是 2013 年开始在知乎负责服务化的工作,对服务化的理解也从最初的模糊逐渐变得清晰,前段时间看了一篇叫做 Microservices – Not A Free Lunch! 的文章,也想趁着这个机会梳理总结目前为止我的一些感悟和想法。

香港帆船培训记录

曾经对香港的印象就是便宜的苹果电脑和遍地的茶餐厅,竟忘记了这是一个靠海的岛屿。作为一个在西部长大的孩子,对于海总是有很多憧憬。从小到大见过很多地方的海,有浑浊的,有碧蓝的,有挤满游客的,也有波涛汹涌的。其实海不一定就是蓝色的,只是人们习惯性地把自己的愿望加诸在别的东西身上,所以如果某一天你见到了不是蓝色的海,请不要抱怨它。

Auto Open Browser After Copy URL

前段时间看过一篇叫 Automate Everyday Tasks 的博客,其中的一些见解很有意思,我们日常工作中有很多细小但是重复的事情,如果能够将某些工作自动完成,会让生活更加舒适。我很喜欢 Mac 上一个叫 PopClip 的小 app,可以大大减少很多重复的操作。这篇博客就是介绍如何制作一个 app,当复制 URL 时自动在浏览器中打开。

Hello, Goodbye

2014 年第一天的清晨我改了一个 bug,买了一个 app,喝着已经凉了的白水,加湿器冒着白烟。这座城市还在熟睡,这个每天生活、工作、恋爱的地方,它的气息吸引着我,人们仿佛只能看到它的丑,殊不知都是我们自己种下的恶果。平安夜,临下车前我把苹果送给了司机师傅,一声谢谢让我们似乎都有了对于未来的企盼。2013 年的最后一天,吃饭时朋友特意点了鱼,喻为「年年有余」,三个「孤独」的男人就这样就着玉米汁品味这一年的最后一顿饭。也许我们对于未来都有不同的打算,但是如果能互相陪伴,彼此的人生也不会孤单。我相信人性的善,当一个人告诉我他再也不相信时,或许是你还没有遇到那个人,经历那件事。从来没有觉得自己如此重要,当被另一个人视若珍宝,我只能不争气地泣不成声。

You don’t know about real loss, cause it only occurs when you’ve loved something more than you love yourself.

这段话我想很难做到,但我们都会尽力实现它,因为有些事情是不能重来的。如果你要问我有什么新年愿望,我会说「Believe love, believe dream」。

我想骑着摩托载着你就这样在清迈古城闲逛

作为人生中的第一次境外游就献给了泰国,大约一周的时间,不长不短,遇见了很多人,经历了很多事,这恐怕是独自旅行才有的福利。对于泰国,几乎每一个交谈的人的第一印象都是「friendly」,这里的人们悠闲自在,热情好客,因为有着虔诚的信仰,会让你感受到每个人的善。作为一个历史更加悠久的国度,我们理应更加虔诚,但是如今的中国,信仰早已变质,我们也都是没有信仰的一代。

流浪汉,木偶和厨子

最近要为 Phabricator 搭建虚拟测试环境,Vagrant 是一个不错的选择(话说官网现在更新以后,变得颇为华丽)。Vagrant 官方只提供 Ubuntu 的 base box,不过 Vagrantbox.es 有提供很多其它的系统,甚至还有 Window$。也可以自己根据官方文档重新搭建一个 base box。

Provisioning 是 Vagrant 一个很棒的特性,可以通过工具来自动配置和管理虚拟机。目前支持的有 Puppet 和 Chef,这两个都是著名的配置管理工具,其中 Google、Twitter、GitHub 在用 Puppet,Facebook 在用 Chef,知乎目前用的是 Puppet。正好这次两个都了解了一点,可以简单比较一下。

从安装方式来说,因为都是基于 Ruby 的工具,所以都可以通过 gem 来安装,从这一点上来说还是很方便的(话说对于 Mac 用户,千万别用官方提供的烂方法)。Puppet 的命令行工具就叫 puppet,而 Chef 的叫做 knife,这倒是跟 Chef 本身名字很搭。初学工具,肯定要看官方文档,在这一点上我觉得 Puppet 做得更好,至少还有一个像模像样的 Learning Puppet 系列,由浅入深,循序渐进,基本上看完就可以对 Puppet 有个大概的了解和使用。而 Chef 就只扔给你一个不知道该从哪看起的页面,作为初学者表示很难入门。

Puppet 可以将一系列的配置文件打包成一个 module 供人下载,Chef 对应的则叫做 cookbook,这两者都提供了网站用于集中放置社区贡献的包,分别是 Puppet ForgeOpscode Community(不得不吐槽,这两个网站都很糙)。对于 module、cookbook 的安装及管理 Chef 略胜一筹,Puppet 的命令行工具可以很方便地安装 module,但是如果需要安装的包比较多,就只能通过自己写脚本来自动处理。而 Chef 有一个很好用的工具 Librarian-Chef,只需要定义好所有依赖包,并放到 Cheffile 中,就可以通过 librarian-chef 命令来安装和管理。

Puppet 在易用性,社区质量和包的扩展性上来说要比 Chef 略优,能查到的文档资料也更多一点,最终我选择了 Puppet,这里是我的适用于 Phabricator 的配置文件,对 Chef 有兴趣的同学也可以看这个示例配置。

Little Tips: Redis MONITOR Command

前段时间知乎的 cache 服务器中的某个数据总是错乱,想到了几个可能修改缓存的源头,同时在代码中搜索相关代码,把这些服务都重启了。但是问题依旧,只是没有之前那么严重。好吧,这下肯定是某个不知名的地方仍然在访问缓存。那就从根源查起,猛然发现 Redis 的 MONITOR 命令,可以实时打印出此时正在执行的命令,正合我意,修改缓存的命令我是知道的,只需要监测这个命令,然后就可以查到来源了。

$ redis-cli monitor | grep '"set" "alist"'

给未来的你

孩子,你的一生会遇见很多不一样的人,在陌生的城市和环境里结交着朋友,找寻着恋人。你每天都会很忙,忙到没有时间喝水,没有时间吃饭,没有时间思考。你会羡慕那些生活得悠闲自在的人,仿佛他们生来如此。看到街上的情侣你也会想她是否也在想着你,因为你们仰望着同一片星空。你向往着有一天和她一起生活,你们想要的生活。

孩子,还记得我讲过的怎样遇见你母亲的故事吗?那是一个明媚的午后,记忆中的阳光总是很灿烂。当那个女生出现时,时间仿佛凝固,她没有注意到你,你知道这是一个需要你用一生去爱的女人。是的,一生。年轻人总是有无尽的诺言,但是诺言是沉重的,兑现诺言的过程是洗礼,也是炼狱,你们虽然彼此伤害,却靠得更近。

我对你的爷爷奶奶知之甚少,大部分是从旁人那里听说。他们小学是一个学校的,奶奶上学会经过爷爷的屋前。后来奶奶高中毕业后就开始教书,而爷爷则继续深造师范学校,传说他们从这时便已经在谈恋爱,分隔两地免不了很多的思念与痛苦,爷爷常常笑着说当年可是拒绝了很多女生的诱惑。爷爷毕业后回到了奶奶教书的学校,多年的长跑也终于有了结果。其实你还有一个姑姑,不过连我也没有见过。她是爷爷奶奶的第一个小孩,听人说长得很乖巧,但在十几岁时便由于生病去世了。爷爷奶奶教了一辈子学生,却不怎么跟我说起他们的故事,也许是不知如何表达。

我们都会老去,我们也曾年轻,你的困惑就是我们曾经的困惑,你的烦恼就是我们曾经的烦恼。如果你想倾诉,别忘了在远方还有你的母亲,还有我,不管发生什么,我们永远都是你最亲的人。我知道你曾经也恨过我们,但那不是真正的恨,我相信有那么一天我们能彼此释然。

到那时,你会了解,我们是如此深深地爱着你。

使用 Bootstrap 的几个问题

Responsive 与 Modal

在开启 responsive 后,小屏幕设备上显示 modal 时会变成一闪而过,然后浮动窗口就不见了。具体效果可以缩小浏览器尺寸,在这个页面的 Live demo 点击「Launch demo modal」看到。Issue #2130 专门讨论了这个问题,目前比较好的解决办法是使用这个插件,根据页面大小来动态调整 modal 的位置,不过貌似用了之后 modal 那个由上至下显示的动画就没有了。这个 issue 现在还处于开启状态,看来官方短期内是不会解决这个问题的。

Responsive 与 Navbar

responsive 模式下的 navbar 显示效果很赞,但是有一个很令人费解的事情,默认情况下所有 dropdown menu 都是展开的,对于使用多个菜单项,且子菜单条目很多的场景这是不能接受的。于是 Issue #3184 出现了,这次的方案比较 hack,需要修改 bootstrap-responsive.css,将 .nav-collapse .dropdown-menu 里的 display: block; 注释掉。这时你会惊喜地发现 dropdown menu 默认折叠了,点击也能展开子菜单。 最新版 Bootstrap 已经修复了 dropdown menu 默认展开的问题,但是(总是有很多但是),在触屏设备上子菜单是选不中的。托 filod 同学的福,修改 bootstrap-dropdown.js 中的一段代码:

1
2
3
4
5
6
7
8
/* APPLY TO STANDARD DROPDOWN ELEMENTS
 * =================================== */

$(document)
  .on('click.dropdown.data-api touchstart.dropdown.data-api', clearMenus)
  .on('click.dropdown touchstart.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
  .on('click.dropdown.data-api touchstart.dropdown.data-api'  , toggle, Dropdown.prototype.toggle)
  .on('keydown.dropdown.data-api touchstart.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)

这里同时监听了 click 和 touchstart 事件,于是在触屏设备上先有 touchstart 将子菜单隐藏,再有 click 点击到隐藏后该位置的菜单项,因此你永远都不可能点到想点的子菜单。根本原因也是因为我们之前注释了 display: block; 引起,改变了 Bootstrap 的使用场景,于是 JS 出现如此纰漏。解决方法便是不监听 touchstart 事件,虽然会造成些小问题,不过也算基本满足要求。这个 issue 官方明确表示不会采纳,不过还是希望以后有机会增加一个开关选项给用户。 关于这个问题的讨论可以看 Issue #4550,不明白为什么官方一直不解决,我的修改可以见这个这个 commit。