Jiggy 用javascript编写iphone原生程序

Jiggy是一套运行环境,可以用javascript来编写iphone程序.
它通过使用Jigglins将iphone的sdk封装到javascript对象.这样开发者可以用javascript编写程序,界面则和native
的iphone程序一样. Jiggy应用程序运行时会启动一个内部的webserver,通过javascript解释器产生相应的界面.
有意思的是,它的提供了一个基于browser的IDE, 在桌面浏览器中完成开发和调试. (首先在iphone上启动它的运行环境,然后通过你台式机浏览器访问iphone)

个人感觉,这东西非常有前景,极大降低了开发iphone程序的难度,就像当年的vb一样.
由于可以将一些底层的东西用Object-C编写并封装为jiggylins,然后由javascript来调用,可以实现很多不可能的任务.
比如 SpoofApp ,这个东西是基于jiggy的,可以实现伪装电话号码, 来电录音,甚至伪装和改变你的声音,比如男声变女声.
很多是要通过底层操作通讯模块的.

下图是在我的iphone上运行jiggy环境,通过我leopard上的safari进行开发

jiggy.png

开始Sphinx的小白鼠实验

Sphinx,又是一个俄罗斯人的杰作, 据说性能远超于Lucene的开源全文检索. 年初的时候曾经关注过,不过由于误认为对中文支持不理想,放弃了. 现在发现,国内的CoreSeek公布了基于Sphinx的中文检索方案. 可以开始尝试了,
和Lucene不同的是,Sphinx都有Python,PHP,Perl的API方案, 这下省事了. 不用像Lucene一样, 需要用PJB或者ICE来整合了.

准备开始试验…

Nginx实践 使用memcached模块加速PHP应用程序

Memcached,就不多说了,地球人都知道.
Nginx有一个memcached_module,可以直接从后端的memached服务器中读取内容,
直接输出.

通过这个模块,可以极大的提升动态页面的访问速度.

我的实践中, 曾经用这个模块快速的解决了由于代码造成的一些瓶颈问题.

memcached可以通过upstream来从多台memcached服务器中读取,也可以支持热备份.

下面是我的完整例子

upstream memcached {
server 192.168.8.11:11211;
server 192.168.8.10:11211;
}

server {
listen 80;
server_name t.night9.cn;
limit_conn one 10;
charset utf-8;
access_log /logs/web/t.log main;
root /www/app/web;
default_type text/html;
index app;
location = / {
set $memcached_key $host$uri;
default_type text/html;
memcached_pass memcached;
error_page 404 = /missing;
}
location /missing {
internal;
rewrite ^/missing$ /app/site/blog last;
}
include php_app.conf;
}

在这个例子中, nginx首先从memcached中读取(缓存的key可以用memcached_key来设置.),
如果命中,则直接输出内容,注意,需要设置default_type ,否则可能不能正常显示.
如果没有命中,memcached_module会返回404,因此可以用 error_page 404来转发到后端的应用程序,
本例中是先转发到/missing ,而/missing则重写到实际的后端应用地址中.

Nginx只负责从memcached中读取内容,但不负责设置.因此,需要你的应用程序自行将相应的页面缓存
设置到memcached中.

在我的部署中, 我是通过设置一个PAGE_CACHE_ID给php的fastcgi:
(在fastcgi_params中加入):

fastcgi_param PAGE_CACHE_ID $memcached_key;

php程序一旦检测到这个环境变量,
那么会自动将当前页面的内容设置到memcached缓存中,由于是在php框架中自动作的,所以可以随时切换,不需要修改.

缺点:

很多事情都不是那么完美, 对于nginx的这个module,其最大的问题就是不支持压缩,
因此,在使用php的memcache函数设置缓存时,必须取消压缩,否则将无法正确输出.

这样带来的一个小问题就是:
由于一般页面至少数k以上,这样对于内存的消耗是比较大.

因此, 在这个module支持压缩之前, 可以考虑备选方案:
使用独立的FASTCGI服务器来替换memcache模块.

通过CPAN模块,实现起来非常简单!

奇怪的gxip?

早上刚要出门,收到短信告知几个服务器均无法访问.
检查了一下,发现都是乱码! 明显是压缩文档的内容直接输出了.
服务器上的文档都是未压缩的, 很诡异阿.
要着急走,没有仔细看,用Safari的”网络时间线”,发现,服务器的response中赫然
出现Content-Encoding:gxip ?
明显应该是gzip,怎么会变成gxip呢? 难怪浏览器无法正确识别了.
于是,简单的禁用了相关服务器的gzip压缩, 页面就正常了.

刚回来, 为了复查这个问题,将gzip重新打开, 竟然没有重现错误!
google一下,发现也有类似的现象,但是都没有解决方案,也是莫名就好了.

由于现象出现的比较突然, 大概是早上4点多出现的.
而且是若干个服务器同时出现,也是同时好.
想了想,这几个服务器类似的地方就是都有广告,而广告服务器也在这期间down了.

初步怀疑广告输出的内容导致了nginx的相关错误(mod_gzip溢出?)
或者是HTTP劫持造成的(将gzip替换为gxip)?

将广告服务器nginx和php升级, 目前无法重现相关错误,无法做出更清晰的判断.

不知道有没有人有过相似的经历?

Nginx实践1 利用proxy_store实现高效的静态文件分布缓存服务器

曾经写过是否要放弃使用varnish/squid, 经过几天的实验,终于找到一种比较理想的解决方案:
直接使用proxy模块的proxy_store来实现分布mirror.

首先说说我的需求:

1. 我需要将一些静态文件从应用服务器剥离, 负载到其他的节点.
2. 这些文件主要是静态Html和图片,包括缩略图. 这些文件一旦创建,更新的频率很少.
3. 在某些时候需要手动立即从各个分布节点删除或更新某些文件
4. 尽可能减少应用服务器的请求, 进而减少内网的流量

之前,我分别使用了squid和varnish.
最初用的squid,还凑合.不过,squid在高负载下会出现停滞甚至crash或者是空白页.
于是换成varnish.
varnish也是老毛病,偶尔也会crash.

二者的共同点,就是当cache快满的时候,效率会急剧下降, 同时,对主服务器的请求甚至都
阻塞了整个内网.

要解决这个情况,varnish需要手动重启, squid则需要清除整个缓存目录.

对于varnish, 由于是纯内存的加速,因此,无法将cache设置太大,否则用上swap, 基本上是几倍的速度下降,
而且很容易就段违例了. 于是,当bots访问网站的时段, 就是噩梦产生的时候, 由于爬虫遍历太多的文件,
造成缓存很快溢出,于是频繁的invalid,此时,内网的带宽占用能达到100m以上….

可能有人说,为什么不用NFS. NFS的问题主要是锁的问题. 很容易造成死锁, 只有硬件重启才能解决.

为了脱离这个噩梦,我决定试验nginx的proxy_store. 如果使用Lighty,倒是非常简单,因为有mod_cache,配合lua,
会很灵活. 不过nginx的proxy_store并非是一个cache,因为它不具备expires, 新的cache模块仍在开发中.
不过经过仔细考量, 我惊喜的发现,其实这正是我想要的, 因为在我的需求中,绝大多数的文件都是不过期的,因而也无必要
去和后端服务器验证是否过期.

配置其实并不太复杂,但是过程有些曲折, 基本的思路是:
nginx首先检查本地是否有请求的文件,如果有直接送出,没有则从后端请求,并将结果存储在本地.

第一个方案,是基于error_page来实现的:

upstream backend{
server 192.168.8.10:80;
}
server {
listen 80;
access_log /logs/cache.log main;
server_name blog.night9.cn www.night9.cn night9.cn;
proxy_temp_path /cache/temp;
root /cache/$host;
location / {
index index.shtml;
error_page 404 = /fetch$uri;
}
ssi on;
location /fetch {
internal;
proxy_pass http://backend;
proxy_store on;
proxy_store_access user:rw group:rw all:rw;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Via "s9/nginx";
alias /cache/$host;
}
#对于请求目录的情况下要特殊对待
location ~ /$ {
index index.shtml;
error_page 403 404 = @fetch;
}
location @fetch {
internal;
proxy_pass http://backend;
proxy_store /cache/$host${uri}index.shtml;
proxy_store_access user:rw group:rw all:rw;
proxy_set_header Host $host;
proxy_set_header Via "s9/nginx";
proxy_set_header X-Real-IP $remote_addr;
}
}

这个方案对于普通的情况下,基本满足.

缓存是做到了,但是如何实现更新呢?
其实很简单,只要将指定url的从本地cache目录删除即可.
因为proxy_store会按照实际请求的url地址建立相应的目录结构.

于是,我写了一个fastcgi, 只要将需要清楚的url传递给它,从cache目录中删除.
其实可以用perl_module实现,但是考虑到独立fastcgi服务更为稳定,还是和以前的统计一样,
用perl的CGI::Fast模块实现, 替换了10几行代码就搞定了.

事情本来就该告一段,不过,由于主服务器上使用了SSI, 新的问题就来了:
我们希望SSI的解析是在子节点上进行,而不是在主服务器上进行, 这样我们可以独立更新相应
区块的文件即可, 否则就需要清除所有的shtml文件,这是比较可怕的.

但是,Nginx对于SSI的subrequest无法使用error_page来重定向.(不确定是否是bug,不过如果允许
的确容易造成死循环).

于是,一个更为简单的方案就诞生了:

set $index 'index.shtml';
set $store_file $request_filename;
if ($uri ~ /$ ){
set $store_file $request_filename$index;
rewrite (.*) $1index.shtml last;
}
location / {
index index.shtml;
proxy_store on;
proxy_temp_path /cache/temp;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Via "s9/nginx";
proxy_store_access user:rw group:rw all:rw;
if ( !-e $store_file ) {
proxy_pass http://backend;
}
}

Wow! 更为简单.
应该感谢Nginx的Rewrite模块, 这点也是我用Nginx替换Lighttpd的一个主要原因.

好了,我可以忘掉varnish,squid了.

如果有兴趣的人想使用, 请一定注意:
这个方案对静态文件更为有效,如果要加速动态请求,还是要用varnish

说道加速, 利用Memcached和nginx配合可以迅速提升访问动态页面的速度,
有时间再说.

后记:
写这个东西源自 Fenng提到的Nginx 的推广问题
分享一下我使用Nginx的体验

“我们在一起”全球华人设计师抗震救灾公益海报设计活动

     2008 年5月12日,就在大地颤抖的瞬间,多少生命埋葬在了废墟之下,多少亲人在这黑色一分钟内永远的失散,多少曾经的美丽就此逝去…面对着瞬间被夷为平地的废墟,面对着惊恐无错的双眼,面对着废墟下一具具已经变得僵冷的身躯,面对着年过半百的老人默默留下的眼泪…..面对突如其来的灾难,人们无从选择,人们措手不及,人们惊惶失恐…在废墟下,多少同胞为了一线生机还在与“ 生不如死的折磨”抗争,多少父母守望在废墟前等待传来他们子女的消息,多少孩子变为孤儿,哭得痛不欲生…
    
     此时,解放军们正在废墟里为了灾民生还的一丝希望而奋力营救;各地医疗机构、医护人员正在为了每一位伤员而全力治疗;全世界所有关注此次灾害的企业、机构、百姓都在尽全力捐钱、捐物、献血,用爱的力量去创造奇迹,用爱的力量建起新的家园。
    
     全中国所有的设计师、广告人、创意人都愿意用尽自己的微薄力量为所有苦难中的同胞兄弟呐喊,用自己的创作产生最深广而浓厚的影响!没有什么比我们的心更暖,没有什么比我们的爱更浓,这也许是我们除了捐血、捐钱之外最有效的救助了。
    
    全球所有设计师、所有广告人、所有创意人、所有与之相关的同仁们,只要你有抗震救援的激情,只要你有一点点冲动,都加入到我们的队伍中来,创作出最能表现我们情绪和思想的海报作品,用最直接的感情、用最大的力度去影响所有的人!这就是我们在这一时刻所有的价值体现!
    
     在此,我们倡议所有具有思想和激情的同胞们团结起来,发挥我们的力量,向全球的人们传达出我们所有的人都与受灾的人们在一起,不弃不离,让我们用爱的创意感动每一个人!
    
    中国红十字基金会 北京工业设计促进会 视觉中国网站

这些作品都是由国内顶尖的设计师满怀爱心创作的,而且可以无偿使用.
希望更多的媒体能够转载这些海报和作品,让这些作品在灾区发挥作用.

更多的作品,可以看官方网站:

“我们在一起”全球华人设计师抗震救灾公益海报设计活动官方网站

部分作品:

14点28分默哀3分钟

今天下午2点28分
一起沉痛悼念汶川大地震中遇难的兄弟姐妹!

风雨之后就是阳光.
祝福我的祖国,我的同胞们!

varnish or squid ?

上varnish已经有一段时间了. 虽然其性能确实不错, 不过, 稳定性还是欠佳.
我现在用的是trunk版本, 其正式版经常在高负载的时候crash. 虽然这个问题
在其mailinglist中也不少人提出,但是似乎没有特别明确的解决方案, 根据某些人的
只言片语,似乎在trunk中能够解决. 我更新到trunk,虽然crash的机会少了,但是仍时有
发生,最后,我的解决方案是用monit来监控和重启(虽然varnish自身号称有autorestart
的功能,但是在我的情况里没有用,重试几次就彻底歇了).

速度是快了,不过如果缓存满了,那么就性能是急剧下降的. 对于后端的访问次数增加很多,
这种情况下,各种不道德的爬虫就是灾难了.
因此,有必要监控你的cache是否已经满了, 如果满了,最后就重启一下.
不要指望它的过期和自动交换了, 会死的很难看的.

实际上,以前用squid的时候也遇到这个问题. varnish由于是纯内存的web加速的cache,
因此如果超出了,就要用swap. 这时候,和squid一样,都是光屁股,没啥起色.

其实,对我来说,squid似乎更为合适,因为我不希望使用一个纯内存的cache服务器,因为,
我实际上要的是一个mirror,呵呵.

varnish/squid的purge方法都不太适合我的情况. varnish支持正则批量清楚一批url,不过
必须使用客户端,而且,我至今也不清楚如果不同host相同的url下如何区分?

其实,作mirror,从应用程序角度看,也很好实施:异步复制更新的文件到各个mirro节点去,
还是用perl,可以轻松搞定. 这样,就是直接nginx了.

一个更好的想法是,干脆使用perbal得了. 为什么? 因为我需要根据一些逻辑,能够有选择的清除
cache. perlbal可以写plugin,当主服务器发生变化,只需要删除本地缓存的文件即可.
其他的时候,文件从不过期. perlbal前面可以挂上nginx.

最后,也可以考虑使用nginx的proxy_store,然后用perl来删除store文件?
然后,又想到,其实squidclient也可以实现….
晕了
…..

说到nginx,
nginx稳定版已经升到0.6.31了.
现在国内热捧lighty的人多,用nginx的少.
我二者都用过,还是觉得nginx让人放心.
至于性能,说实在,没发现和lighty有多大的差距.

想轻松,简单,可靠,还是用nginx

;-)

换个口味:Catalyst

Catalyst是Perl中的RoR和Django.
大概看了一下, 还是很有兴趣的:
Catalyst layout

现在对PHP有点疲劳了, 接下来想看看别的
上周上班路上温习了下Ruby,对于Ruby和RoR我是没啥实际经验,
Python现在也忘的差不多了,Django也就别碰了吧.
Perl这两天用的很爽,是不是试试Catalyst? Catalyst的plugin+CPAN还是强大的.

现在年纪大了,脑子也记不住东西了. Perl曾经用的那么熟,现在还得查Perldoc,好在Textmate的^H,帮了大忙.

而且, 有没有什么好的想法可以用Catalyst来小试一下呢?
公司的项目肯定是不行的,只能用自己的实验品来琢磨一下了.

statsd原型

Perl用起来就是爽,今天很快就完成了statsd的原型设计.
statsd分为2个worker,开始我是spawn了3个进程,其中一个用于worker子进程的管理.做完了觉得没有必要,通过shell可以很简单的作monitor.

cgi-worker:

顾名思义,以FastCGI Server的方式运行,通过unix socket和nginx通讯. cgi-worker的工作是收到request,存储到内部的
待处理队列中进行缓冲.
这部分使用了CGI::Fast和FCGI实现fastcgi接口. 开始有些小问题,CGI::Fast中BEGIN是通过监测几个ENV来确定是否是
独立模式的Request,我根据perldoc中例子作了几个测试,都运行一次就退出了,用lighty的spawn-fcgi则可以正确运行.
于是看了下spawn-fcgi的源码,也没有发现什么特殊的,于是重新看CGI::Fast的代码,找到原因.
我想自己定义ENV变量, 修改了一下:

$worker = 'worker.cgi';

initialize();

$SIG{'TERM'} = \&shutdown_cgi_worker;

my $path = $ENV{STATSD_CGI_SOCKET};
my $backlog = $ENV{STATSD_CGI_BACKLOG};

my $socket = FCGI::OpenSocket( $path, $backlog );
$CGI::Fast::Ext_Request = FCGI::Request( \*STDIN, \*STDOUT, \*STDERR,\%ENV, $socket,1);

info("$worker connect FCGI socket to: $path");

Queue则用BerkeleyDB实现, 还是比较简单的.

Sync-worker:
这部分用于读取queue中的数据,将其处理后,插入到后端mysql数据库中.
由于我将bdb tying到一个@db_queue,所以实现非常简单,bdb没有涉及到什么数据库的读写.

2个worker可以独立运行,相互不影响. 尤其是sync-worker,可以灵活掌握.
cgi-worker由于用fastcgi方式,运行效率还是很高的.

用webbench在我的mbp上作了简单测试,基本上维持在1700 rps 左右.
由于我的mbp的限制,实际运行效果应该能比这个高几倍才对.
不过即便如此,现在也足以.
至于扩展方式, 可以修改一下cgi-worker,加入process manage功能,或者更简单的,
多派生几个worker, 在nginx中用fastcgi的负载均衡来实现,nginx用起来真是太棒了.

Next Page »