域名转移到 Name Cheap 了

早上收到 DNSPod 的告警邮件提示域名快要过期时,我才意识到一年一度的域名续费时间又到了。我的域名是2011年在 GoDaddy(俗称狗爹)上申请的,当时价格很便宜,就忍受了狗爹那极其垃圾的后台和三天两头发送的垃圾邮件。后来续费时也都能找到合适的优惠码,也就继续忍了。

不过今天搜索了半天也没找到一个合适的狗爹优惠码,唯一一个能用的也是要满 50$ 才能省 10$。而 .me 的域名续费就要 19.9$,一次要续费好几年才能用这个优惠不说,还省不了太多。我发现不少人都有这样的抱怨,并且有人已经因此迁移域名到别家了,当即决定不再继续忍受狗爹了,果断换之。

找了一圈发现 NamecheapNamesilo 比较靠谱,续费价格公道。比较了一下发现两家的 .me 域名续费价格都一样,就选择了页面看起来更简洁的 Namecheap。按照其网站上的 狗爹转移指南 操作,很快就把域名转移过来了,并续费一年,一个域名 99 RMB 左右,比狗爹便宜了不少,还赠送了 WhoisGuard 用于保护 whois 信息,很不错。登录其后台看了一下,界面简洁不少,不会像狗爹那样到处都是推销链接,续费的时候更是不会有乱七八糟的引诱购买其他产品的链接,嗯,我喜欢。

狗爹,再见了。

对 MongoDB 的一些吐槽

首先声明,我们对 MongoDB 的使用谈不上深入,我更是没有太多经验,所以下文的这些吐槽不一定都是对的。下面提到的问题,有的可能是我们的使用方式不对;有的可能是没找到合适的解决方案;有的可能根本就不是适合 MongoDB 的使用场景。总之,希望这些不会成为你使用/不使用 MongoDB 的参考,如果你是 MongoDB 高手,也请不吝赐教。

0. 背景

我们使用 MongoDB 是为了存储一些机票检索的历史数据以便于后期的分析,是典型的 OLAP 类的使用方式。数据一旦写入就不会有 Update,只有读取。单条很庞大,经过精简后的纯 JSON 大小也有几十上百 K(我怀疑 MongoDB 并不适合存储太大的 Document )。

我们初期使用了三个节点部署 MongoDB,组成一个 Replication Set,其中两个实际承载数据,另一个充当 Arbiter,只投票。

后来其中的 Secondary 因为严重的硬件故障送修了,Replication Set 实际上变成了单节点在运行。修复好了以后 Secondary 跟不上 Primary 了,重建 Secondary 也因为一些原因(后面详述)没能搞定,只能作罢。

现在的状况是原 Master 单节点运行(Arbiter 等于没用),但磁盘分区快被占满,急需进行迁移;Secondary 是全新安装的实例,我们打算直接切换,跑两个单实例,不再做 Replication Set。

Read on →

又被 Python 的 Unicode 坑了

很久没更新博客了,不是没什么可写,而是因为工作生活的种种原因没有心情更新。趁着今天有点时间,还是开个头继续写吧。

这次遇到的问题还是与 Python 的 Unicode 有关。请看下面的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[~/tmp]$ cat test.py
#coding:utf8

foo = u'测试'

print foo
[~/tmp]$ python test.py
测试
[~/tmp]$ python test.py > /tmp/foobar.txt
Traceback (most recent call last):
  File "test.py", line 5, in <module>
    print foo
UnicodeEncodeError: 'ascii' codec can't encode \
  characters in position 0-1: ordinal not in range(128)

简简单单打印一个 Unicode 对象,直接输出不会报错,但重定向到文件就会挂掉,这实在让人想“呵呵”。

Read on →

去除 Org-mode 输出 HTML 时多余的空格

用 org-mode 写文档、写 slides 有一段时间了,org-mode + Tex Live 这个组合真是棒极了,写文档,制作 slides 的效率高多了,输出的 PDF 也很漂亮。但偶尔也会有输出 HTML 的需要(比如写 Blog),此时有一个不大不小的问题:输出的 HTML 里的中文段落会多出来很多不必要的空格。

究其原因,Emacs 默认启用了 autofill,会自动将段落的宽度控制在 80 个字符。当这样的段落被输出成 HTML 的时候,换行符就被替换成了空格。在英文文章里这不是问题,因为英文本来就是用空格来分割单词,但在中文里就很让人不爽了。

Read on →

Cron 导致的乱码问题

几天前为公司的生产环境写了个应用内存监控工具,定时通过 jstat 查看当前机器上所有的 Tomcat 进程的 GC 信息,发现 Eden 和 Old 占用持续超过一定阈值时自动重启相关进程(我知道这方案很山寨,求别黑……)。部署上后看似很 Happy,让服务质量有所提升。

但好景不长,没过多久,多个系统纷纷反映出现了奇怪的乱码问题,而这些系统都是被这个监控脚本重启过的。这个监控脚本是通过 crontab 定期执行的,联想到以前遇到过的 crontab 下 PATH 不对导致的 command not found 问题,我不禁把怀疑的目光再次投向了 cron 这货。一番 Google 后果不其然,很多人都遇到了同样的问题(Google 出来的第一页记录有几个日文网页,CJK 伤不起啊),而原因其实都是一样的: cron 会使用一个最小化的环境来执行任务。

Read on →

神秘的40毫秒延迟与 TCP_NODELAY

最近的业余时间几乎全部献给 breeze 这个多年前挖 下的大坑—— 一个异步 HTTP Server。努力没有白费,项目已经逐渐成型了, 基本的框架已经有了,一个静态 文件模块也已经实现了。

写 HTTP Server,不可免俗地一定要用 ab 跑一下性能,结果一跑不打紧,出现了一个困扰了我好几天的问题:神秘的 40ms 延迟。

Read on →

记一次数据恢复过程

上周因为停电(理由竟然是没交电费,无力吐槽)导致公司的一台测试服务器出现故障,无法启动。今天上午忙了半天,各种 Google 之后,终于搞定了,恢复了大部分数据,在这里记录一下。

Read on →

ThreadLocal 和神奇的 0x61c88647

我之前提到说想把找工作面试过程中被问到的一些问题进行一下整理和记录,借刚刚完成一个小feature 的空闲时间开始第一篇吧。这一次的主题是 ThreadLocal,以及在探索过程中发现的一个很神奇的魔数 0x61c88647。

当时面试的过程中,我针对面试官的另一个问题提到了一个基于 ThreadLocal 的解决方案,然后面试官就抓住这一点进行了追问,让我画 ThreadLocal 的内部结构图并解释原理。自诩 Java 基础还可以的我,硬是在这翻船了。我当时给出的答案是,ThreadLocal 内部有一个以 Thread Id 为 key 的 map,不同的线程通过自己的 Thread Id 作为索引来查找对应的值。面试官接着追问说这样是不是会带来不必要的 contention,性能不好,我一下就语塞了。还好后来回忆起来 Java 的 Thread 类里有一个字段叫 threadLocals,隐隐觉得不对劲,修改了我的说法,换成了一个比较接近真相的答案。

回来以后赶紧翻开源代码验证一下,以下是我的发现。

Read on →

重新开始

好几个月没更新博客了,前几天看了下 Page Rank 又掉回到 2 了。坚持写博客不是一件容易的事情,但是为了能持续积累自己的思考过程,我要坚持下去!

从 2 月份到现在,发生了很多事情。首先,我离开了上一家公司,也离开了电信行业。换工作的过程也破废了些周折,我十分向往的 AVOS 拒绝了我,让我失去了一个用自己最喜爱的语言工作的机会;而另一家对我印象颇好的公司,因为种种原因被我拒绝了。最后我加入了现在这个做国际机票预订业务的互联网企业(如果你有预订国际机票的需求,不妨试试我们的非凡旅行网,也许价格上能给你一些惊喜)。总之,既然现在已经安定下来了,不如沉下心来好好做一段时间,不断提升自己才是王道,提升的同时能获得一些乐趣就更棒了!

Read on →

小探 Java 泛型系统的不协变问题和类型推断

这个问题起源于最近在生产代码中写下的这样一个方法:

protected Set<Class<? extends Module>> getAppModuleClasses() {
    return Sets.<Class<? extends Module>> newHashSet(DAOModule.class,
                                                     ACSModule.class,
                                                     TR069Module.class,
                                                     STUNModule.class);
}

那句显式的类型参数实在是太碍眼了,但是去掉它则会导致编译无法通过。在忍 受了这段代码一段时间后,我决定对这个问题好好研究一下。

Read on →