无知的 TonySeek

Yet Another Seeker

ZooKeeper Session ID 的组成

ZooKeeper 的 Session ID 是每个会话的唯一标识,记录为一个 64 位的长整型。 只要对应会话未被服务器端主动关闭,它就一定能唯一关联上。且会话初次建立时 Session ID 会被写入 transaction log,这意味着会话是跨节点共享的。 客户端和一个节点断开连接后,只要会话还没过期,就仍然可以使用相同的 Session ID 连到另一个节点。这个会话创建的所有临时 ZNodes 也会相应保留。

指标显示 ZooKeeper 经常出现大量 outstanding requests (即节点上排队待处理的请求) 时,我们就需要诊断大量请求来自哪个 ZooKeeper 节点。无论是 leader、follower 还是 observer 节点都在本地处理读请求而将写请求转发给 leader 发起投票,所以节点自身的 outstanding requests 指标可能因参与投票而不是处理本节点的请求而飙高, 从而不一定能准确体现出请求来源。这个时候从 ...

GraphQL vs RESTful API 的一些想法

嗯其实又是一篇早就写了的碎碎念, 在我的 simplenote 里躺了有一年了。也发出来充数吧,好显得我并没有把这个博客弃坑…

GraphQL 出来的时候似乎有老司机说它会“重新定义后端”,当然我们心里知道这实际上是重新定义了重新定义。综合官方文章来看,它要解决的问题都很明确 —— 我认为在 HTTP 1.1 时代它是很有工业价值的。然而它并非唯一的解决方案,RESTful API + HTTP/2 就是一种不错的备选。

Git 中的状态

嗯,这是去年 lttxzmj 初学 Git 的时候写给她的小纸条。两年没写博客了,发出来充个数…

杀死 subprocess.Popen 的子子孙孙

Python 标准库 subprocess.Popen 是 shellout 一个外部进程的首选,它在 Linux/Unix 平台下的实现方式是 fork 产生子进程然后 exec 载入外部可执行程序。

于是问题就来了,如果我们需要一个类似“夹具”的子进程(比如运行 Web 集成测试的时候跑起来的那个被测试 Server), 那么就需要在退出上下文的时候清理现场,也就是结束被跑起来的子进程。

最简单粗暴的做法可以是这样:

process_fixture.py
 @contextlib.contextmanager
 def process_fixture(shell_args):
     proc = subprocess.Popen(shell_args)
     try:
         yield
     finally:
         # 无论是否发生异常,现场都是需要清理的
         proc.terminate()
         proc.wait()


 if __name__ == '__main__':
     with ...

Flask 的 Context 机制

用过 Flask 做 Web 开发的同学应该不会不记得 App Context 和 Request Context 这两个名字——这两个 Context 算是 Flask 中比较特色的设计。[1]

从一个 Flask App 读入配置并启动开始,就进入了 App Context,在其中我们可以访问配置文件、打开资源文件、通过路由规则反向构造 URL。[2] 当一个请求进入开始被处理时,就进入了 Request Context,在其中我们可以访问请求携带的信息,比如 HTTP Method、表单域等。[3]

所以,这两个 Context 也成了 Flask 框架复杂度比较集中的地方,对此有评价认为 Flask 的这种设计比 Django、Tornado ...

Git 忽略某个目录

有时候我们在给开源项目贡献代码的时候,会使用自己熟悉的工具链。比如 Python 项目,我可能就用 tox 来构建发型包并运行单元测试。或者有不习惯用 pyenv 或者 virtualenvwrapper 的同学,就可能直接使用 virtualenv 命令创建一个隔离的环境。

为 C/C++ 库定制 Python Binding

这应该是个非常常见的需求了吧。可能因为性能原因需要自己编写一部分 C 代码,可能因为需要的第三方库是 C/C++ 编写的。

我遇到这个问题是因为希望将淘宝发的一个切图实现 tclip 放到 Python 上用。和几个同事都尝试折腾了这个问题,总结出了几种可行的方法。

用装饰器注册 Python 函数

注册回调函数应该是开发中很常见的一种行为。这在 Python 中通常通过装饰器来实现,看起来比较漂亮:

flaskr.py
 @app.route("/")
 def home():
     return "It works."

但是这种用法常常带来一种隐藏的“惊讶”,比如说:

C 语言程序设计笔记

呵呵,看标题像是大一同学的学习笔记,事实上我是一个大四将毕业的人了。我在大一入学之后认认真真学习的第一个程序语言是 C 语言,当然,是在在课堂上。可是快四年来,我用的最多的却是各路动态语言(人生短暂我用 Python)。后来毕业设计需要选题,我跟了一个很有黑客精神的导师 [0] ,所以也就希望能挑战一下自己,选择了用我并不熟悉的 C 语言来做系统编程&网络编程。

那个项目 [1] 总算还花了我不少时间和精力,虽然答辩时遇到了奇葩的人并发生了不愉快的事情,但我终究是学到了不少东西。这篇博客用来记录我掉的那些坑,并让读者看到后可以对我说:“你还是回大一去重学吧”。

记录一些坑

用动态语言编写一些简单的应用时,好的 ORM 往往能带来开发效率的提升 —— 尽管 ORM 为不少大型项目所不齿。Python 社区的 ORM 框架最著名的莫属 SQLAlchemy,它的特点是利用 Python 的元编程支持构造了一套既能照顾到面向对象开发习惯,又能向下支持复杂数据库查询操作的 DSL。这类框架在分类上,应该属于抽象层。