Monthly Archives: February 2015

HostUS把服务器搬到洛杉矶了

前两天收到邮件,说要把服务器从vegas搬到LA去,对我来说当然是个好消息,理论上从国内连过去的速度能快上一些。搬好之后测试了一下,发现之前平均185的ping在搬迁后竟然略微上升到了190-200.估计是BGP还没更新,可能要等几天才会好。


今天又测试了一下,已经降到175了,但是和搬瓦工150-160的逆天延迟还是没法比啊。但是搬瓦工最近晚上高峰时间网速很慢,很烦人。


 

再更新一下,其实网速很慢不是搬瓦工的锅,而是因为港大网络的出国带宽不够大,一到高峰时间就堵住了,换成非港大网络就会好很多。

HTTPS & Referer

There are basically two usages of HTTP header “Referer”. One is to trace the origin of the visit, which could be used to analyse the visitor’s browsing path. The other is to identity and block illegal visits to some privately owned web resources, like images & files.

There are some tricky things about “Referer” when it comes to HTTPS. Generally speaking, for safety reasons, a redirect from a HTTPS page to a HTTP page will drop the “Referer” header. Thus, the server will never know where this request really comes from. Some websites use a https-http redirect to bypass the restrictions of private web resources. For example, a webpage quote an image from sinaimg.cn. Sinaimg.cn does not accept requests unless it has empty Referer or the Referer is one of Sina owned domains. To let the browser drop the Referer header, the <img> tag uses a src of https://example.com/redirect?url=sinaimg.cn?xxxxx instead of the original one. The only function of this https://example.com/redirect is to redirect the request to the URL that is specified by the “url” parameter. Therefore, the “Referer” header is dropped and the image file could be visited from other domains.

One known fact about Google is that it uses HTTPS on all of its search results. Most other websites, however, are still using HTTP. As a result, the referer info will be dropped when redirecting from google search result to the webpage. If there is some auto-tracing tools installed on the server, it may never know that the request comes from Google search result.

To solve the problem, two things have been done by Google. One thing is the introduction of “referrer policy” to webkit. Details of it can be found here: https://wiki.whatwg.org/wiki/Meta_referrer. Basically it uses a <meta> tag to tell the browser how to deal with referrers. The current policy used by Google is “origin”, which sets “https://www.google.com” as referrer with no extra information. This is only a little bit better than no referrer, since the tracing tool cannot collect keyword information from the referrer. The other thing is the redirecting page between Google search result and the real target page. Google owned tracing tool, like Google Analytics, can use this redirecting page to collect required data.

What about non-webkit bowsers? Google uses a http redirect page instead of  a https one. This page uses JavaScript for redirecting, not a 301 or 302 redirection. In that way, the target page can collect the correct “Referer” information.

《阿司匹林传奇》——从阿司匹林窥探西方医药的发展历史

当我还在清华的时候,我就在图书馆里读过这本书:小小的一本书,不是很厚,大概两个小时就能看完。阿司匹林是一种用途广泛的药物,主要用途有退烧、止痛、防止血液粘稠。这本书按照时间顺序,介绍了阿司匹林的诞生、发展和现状。不过在我看来,这本书最有趣的地方在于,在介绍阿司匹林发展史的同时,为我们描绘了一幅现代医学的进化图谱。窥一斑而见全豹,阿司匹林的发展史,其实也正是西方医学从懵懂走向科学的历史。

阿司匹林的化学名称是乙酰水杨酸,水杨酸对于上过高中化学的人应该都不算陌生,最早的“阿司匹林”确实也就是水杨酸,只是后来为了减少对胃的刺激进行了乙酰化。在很早的年代,全世界不同地方都有记载嚼食柳树皮来退烧的记录。人们只知道发烧的时候可以食用柳树皮退烧,但是并不知道其中的原理,随着人类社会的发展和变迁,这种缓解发烧症状的疗法逐渐的失传,直到18世纪,它才被人们重新发现,彼时,人们依然不知道其中的原理。到了19世纪,一些化学家开始尝试从草药中分离有效的物质,几次不成功的尝试之后,柳树皮中真正有效的成分——水杨酸被分离出来,而到了19世纪末,经过一系列的实验之后,乙酰化的水杨酸,乙酰水杨酸,被确定成为一种正式的药物,即阿司匹林,开始上市销售。

然而即使是19世纪末20世纪初的药品市场依然非常混乱,秘方药大行其道。什么是秘方药?就是有点类似云南白药这种东西,只告诉你这玩意对什么症状有效,同时选择性的告诉你里面有白芍等名贵中药材,但是又以秘方为名,不告诉你全部的的配方,给你形成一种错觉,就是这个药之所以有效是因为里面的名贵中药材,然而实际上起效的是什么呢?当时西方的药品市场就是如此的混乱,一如现今的中药、中成药市场。书中提到一个例子,当时的阿司匹林开始销售之后,由于制药公司并没有大力宣传,一些私人药剂师就开始往它们的秘方药里添加阿司匹林,但是并不告诉病人里面有阿司匹林,而是宣称里面有神奇秘方。病人吃了之后,确实可以退烧止痛,于是以为是秘方药确实有效的缘故,但实际上起效的,是阿司匹林。但是阿司匹林本身是有副作用的,会引起胃部不适以及血小板减少,血小板减少会使得伤口处血液凝固变慢,如果一个本身血小板就缺乏的人服用了阿司匹林,会有严重的失血风险,而这些风险,所谓的秘方药,都不会告诉你。

中成药也有同样的风险,以太极复方甘草口服溶液为例,说明书上的成分表是这么写的:每100毫升含甘草流浸膏12毫升、甘油12毫升、酒石酸锑钾0.024克、浓氨溶液适量、复方樟脑酊12毫升、乙醇3毫升。看起来都比较正常,主料看起来都是正儿八经的草药,化学品基本上含量不多,应该只是辅料,说明书上也没有说可能有成瘾性,应该是一款很好的止咳中药,真的是中医之光啊!别这么急下结论,我们看看这个所谓的复方樟脑酊是什么:1ml含樟脑3mg、阿片酊0.05ml、苯甲酸5mg、八角茴香油0.003ml。阿片酊,看到这个你也大致猜到是什么了,继续看阿片酊的成分:0.95%-1.05%的无水吗啡+酒精。吗啡作为一种强力的镇咳镇静药,从19世纪就开始被西方医学使用,但是吗啡具有成瘾性,不能长期大量服用,这也是所有含有吗啡的西药里都会有提醒你不能长期大量服用的原因,然而在太极复方甘草溶液这种药里,通过层层包装,让患者难以发现真正起作用的其实还是西药吗啡,而且也没有提醒大量长期服用的成瘾危险,这种做法,和西方医学史上的秘方药,又有什么本质区别呢?

不过对于西方医学来说,值得庆幸的是,这样的做法到了20世纪上半叶,就随着几次因为秘方药导致的死亡事件,而彻底得到了整顿,美国编制了药典来规范所有的药物,禁止成分不明的药物生产和销售,从此秘方药退出了历史的舞台,而明示药物主要成分,进行大量双盲实验确认有效性,进行大量人体实验和长期观察记录不良反应,为新式西药的安全性和有效性打下了坚实的基础。

纵观西方医药史,我们可以看出来,早起的西方医药和现如今的中药一样,缺乏理论依据,药物的研发基本依赖经验,配制药物缺乏定量标准,充斥大量模糊的、描述性的语言,药物药效不稳定,缺少对于副作用的准确描述。而所谓的秘制药,简直就相当于如今中成药的翻版,真正起作用的是西药部分,但是却误导性的告诉你,西药只是缓解症状,真正治好病症的是中药成分。

中医几千年来的核心理论是五行阴阳平衡,从来没有变过,但是五行和阴阳论逃不出迷信的影子,而中医除了自限性的疾病外,基本治不了什么大病。从逻辑的角度看,如果一套理论的基本假设就有问题,那么从基本假设推导出来的结论基本都有问题,这就是为什么我也赞成中医本身的理论部分基本没有任何价值。此外,根据剃刀法则,一套完整的逻辑体系,只需要少量的基本假设,就应该能够得到普适性的结论,然而中医除了基本的阴阳之外,又提出了虚火之类的概念,看上去就像是在地心论之外,为了解释观测与实际的不同,又强行加上了很多本轮的概念。

但是,有一点例外:中药。因为它是直接用于治疗患者的手段,所以它的作用会直接经受患者的检验。我十分赞成,应当对中药进行一次全面的梳理和总结,应用双盲实验,对药物的有效性进行评价;对于那些有效的药物,使用生化技术对有效成分进行分析和提纯,这不仅是对中医本身的一次再发展,也一次能够帮助人类更深刻认识人体与生命的机理的再发现之旅。

一如柳树皮与阿司匹林,中药中有太多的“阿司匹林”有待发现。我希望,已经”闭关锁国“太久的中药,愿意在科学的帮助重新认识自己,绽放光彩。

Android使用Google Analytics v4黑屏

一开始不黑的,后来不知道怎么回事就频繁导致应用黑屏,无响应。网上一搜,发现个这个:

https://productforums.google.com/forum/#!category-topic/analytics/report-bugs/RAgDNYFk6jo

GA as bundled in 6.5.87 is blocking at:
GoogleAnalytics.getInstance(context)
causing ANRs.

Google的回复是

This issue should be fixed in the latest version of Play Services now.

实际上呢?毛都没有,SDK Manager里的最新版就是6.5.87。

Stackoverflow上有人用反编译分析了一下:http://stackoverflow.com/questions/27447805/random-black-screen-when-launching-android-app-on-device

结果是Google的代码有问题,造成了死锁。解决办法是从AndroidManifest文件中移除那个指定tracker xml的meta项。

Google在这种问题上犯错、被人report还不修复,我也不知道说什么好了。


更新一下,今天又发现一个问题,Google的License Check在5.0下会导致应用崩溃,为什么自己的库都不测试好就发出去了呢。。。

https://code.google.com/p/android/issues/detail?id=78505

折腾

折腾了一天,差不多终于搞定了:把Blog从SAE上迁移到单独的VPS上。

迁移的原因很简单,因为SAE给人的一种深深的不靠谱感:Nginx常年报502错误,上传文件经常出错。出错的原因大致有两个,一个是SAE本身稳定性一般,这点我可是深有感受,什么SVN传不了文件,502错误等等乱七八糟的问题遇到的绝对不少;另一个原因是WordPress本身不是为这种“云环境”而设计的,所以现在SAE上跑的WordPress都是之前某人的一个移植版,而作者自从某日从新浪跳槽到淘宝之后就再也没有更新过这个WordPress。除此之外什么Session错乱、安装插件主题麻烦之类的就不提了,完了还有国内云空间的通病:需要备案。总而言之,SAE对我来说唯一的好处就是不要钱(我是中级开发者,所以每个月都有送一些资源),但是看到现在单独架一个VPS来放博客的价格也不算高,于是就下定决心离开SAE。

在Low End Box上看了许久之后,选了这个VPS:http://lowendbox.com/blog/hostus-10year-768mb-and-18quarter-6gb-ovz-in-three-us-locations/ 。原因无它:便宜,可以看下这个配置:

768MB

  • 768MB RAM
  • 768MB vSwap
  • 1 vCPU core
  • 20GB HDD space
  • 2048GB transfer
  • 1Gbps uplink
  • 1x IPv4
  • IPv6
  • OpenVZ/SolusVM
  • $10/year

768的内存,20G的HDD和2T的流量,要啥自行车?供应商HostUs在Low End Box上的评价很不错,不过这个供应商的VPS国人似乎用的很少,可能是因为没有在LA或者是SF的机房的缘故?HostUs西部的机房在拉斯维加斯,物理距离上当然不如LA或者是SF来的近,但是也并没有远多少。从Ping的结果上来看,从香港过去平均的Ping在185左右。我在搬瓦工的LA机房有个用来做SS的VPS,ping平均在160左右,个人觉得已经很不错了,毕竟中美之间半个地球,只算光速来回一趟都得130多。

配置LEMP

用Paypal付了钱,大约几个小时候就开通了。首先ssh进去看了一下系统,64位的CentOS 6.5,果断重装改成32位的,添加一个新的用户用于平时使用。在Ubuntu下常用的sudo在CentOS上需要额外安装才能使用,对应的apt-get也变成了yum,另外还要用visudo手工修改sudo的配置文件,把新用户加进去。

Nginx的正确读法是engine-x,但我之前一直念作”恩ginx“,不过似乎和我一样读错的人不在少数。比如Linux+Nginx+Mysql+PHP的集成环境,在国内一般被称作LNMP,而在国外一般称作LEMP。

Digital Ocean上有篇介绍LNMP搭建的文章,相当的详细和完整,我也基本上按照这篇教程的内容来搭建环境,在此贴上:

https://www.digitalocean.com/community/tutorials/how-to-install-linux-nginx-mysql-php-lemp-stack-on-centos-6

额外两点注明一下:

  1. 这篇教程在安装php-fpm和php-mysql的时候用了–enablerepo=remi参数来指定使用一个叫做Remi的repo来安装,如果不用这个repo用默认的话会出现依赖错误,原因是默认repo里的组件版本还比较低,无法支持php 5.4。另外最好再从这个repo里安装一个php-xml的组件,不然WordPress里的从XML导入的功能将会无法使用。
  2. 几个配置文件的位置:
    1. nginx: 全局在/etc/nginx/nginx.conf,site specific的在/etc/nginx/conf.d/default.conf
    2. php: /etc/php.ini
    3. /etc/php-fpm.d/www.conf
  3. 在这篇教程里,php-fpm的运行组和用户被改成了nginx:nginx,也就是说php和nginx现在运行在同一个名为nginx的用户中,这对于后面更改权限非常重要。

配置WordPress

关于如何配置WordPress,依然可以看Digital Ocean的教程,依然非常详细而具体:

https://www.digitalocean.com/community/tutorials/how-to-install-wordpress-on-centos-6–2

不过,要愉快的运行WordPress,方便的安装插件和主题,这篇文章有一点没有提到,那就是更改html目录及文件的所有者,所以简单说说这一部分的最佳做法:

  1. 配置好MySQL,下载好WordPress,解压并放在html目录中,没什么好说的
  2. 更改html目录下文件的所有者和权限,对于LEMP中用户和权限的讲解,这篇文章写的详细而具体,个人觉得很不错:http://www.ilanni.com/?p=7438。在这里,因为我们之前已经指定了,让php运行在nginx用户下, 那么现在我们只要把html目录下的文件的所有者和组都设置成nginx,php就能够读写这下面的文件。
  3. 浏览器访问index.php进行安装。
  4. 要能够直接安装插件和主题,除了要配好权限,还需要配置一下WordPress的文件读写方式:在wp-config.php中加入一行:
    define(‘FS_METHOD’, ‘direct’);
    来让WordPress使用直接读写文件的方法修改目录内容。

这样WordPress的安装基本就搞定了。当然我还修改了一下其它的参数:

  1. PHP的最长运行时间,之前在SAE上只有30秒,运行点复杂的操作就超时,既然是在自己的VPS上,果断改成300秒,爽歪歪!
  2. 最大上传文件大小,在SAE上受限于Storage的配置,最大只有10M,现在果断改大!修改的地方有三处:第一是php.ini的最大附件大小,第二是php.ini的最大post body size,第三是nginx的最大body size。
  3. 导入之前的文件,我用的是XML方式导出。先在SAE的WP控制面板里把文章用XML导出,然后在新的WordPress中安装WP导入插件,然后导入XML。值得注意的是,如果之前没有安装php-xml模块的话,这里导入之后不会有任何反应,实际上是产生了一个http 500的错误,只要安装好php-xml模块就好。

优化

首先肯定是先换个主题,然后装上插件。我主要装个这么几个:reCaptcha,用来防止垃圾评论;Google Analytics,用来统计网站数据;Better Search Replace,用来替换所有的链接。

接下来是配置cdn,因为CloudFlare据说被墙的厉害,所以我用的是Incapsula。用了之后发现在增加网站可达性上有一点用处,但是对于大陆这块的加速来看,效果不大。

总结

有人云:生命在于折腾。真是一点没错,上面的这些内容,对于熟悉的人来说,可能一个小时不用就搞定了,我却折腾了整整一天。为了下次折腾能快一点,我又花了半个上午的时间写下这篇文章。

最后来看看360的测速结果:

这是Nginx的默认页:

 

Capture

这是首页的访问速度(无cdn):

index.php

这是一个277k的静态图片的访问速度(无cdn):

277k

主页(有cdn):

cdn_index

277k文件,有cdn:

cdn-227k

怎么感觉CDN是负优化?

先这样,改天再折腾吧。也许等哪天有钱了,直接上Linode,大概就不用折腾了吧。

Fragment’s savedInstanceState is always null.

First of all, only fragment killed by system will call onSaveInstanceState() function because of reasons like OOM. Thus, fragment killed by activity’s finish() will not call onSaveInstanceState(). In this situation, it’s better to preserve the state in onPause().

Secondly, in onSaveInstanceState(), one must call super.onSaveInstanceState() at the end of the implemented function.

Thirdly, the fragment should have an TAG or ID associated with it. The best practice is to declare tag in xml or when dynamically adding fragment, use the add() function with tag argument.