Saturday, August 28, 2010

轻松实现可伸缩性,容错性,和负 载平衡的大规模多人在线系统

本文以我的OpenPoker项目为例介绍另一种构建大规模多人在线系统的方案。OpenPoker是一个大型多人扑克网游,内建支持了容错能力,负载平衡和无限制的规模大小。OpenPoker的源代码遵循GPL协议可以从我的网站下载,大约包含一万行代码,有三分之一是用来测试的。

在Openpoker最终版出台之前,我花了很大精力设计参考,尝试过Delphi, Python, C#,C/C++还有Scheme。我甚至还用Common Lisp完成了一个可运行的Poker引擎。虽然我花了9个多月研究设计,最终代码编写却只用了6个星期,这最后的高效率要归功于选择了Erlang作为编写平台。

根据比较,老版本的OpenPoker需要4~5个人的小组9个月时间完成。原班人马还另外完成了一个Windows版的客户端,就算把这个开发时间的一半(1个半月)算进去,也比预期的18个月少得多,就当今游戏开发的客观环境,如此可观的时间节省不可小看!

Facebook后台技术探秘




今天我们一起来了解Facebook背后的软件,看看作为当今世界上访问量最大的网站之一,Facebook是如何保证5亿用户的系统一直稳定可靠的运行。

Facebook的扩展性挑战

在我们讨论细节之前,这里有一些Facebook已经做的软件规模:

  • Facebook有570000000000每月页面浏览量 (据Google Ad Planner)

  • Facebook的照片量比其他所有图片网站加起来还多(包括Flickr等网站)

  • 每个月超过30亿张照片被上传

  • Facebook的系统服务每秒处理120万张照片,这不包括CDN服务中处理的照片

  • 每月超过25亿条的内容 (状态更新,评论等)被共享

  • Facebook有超过30,000服务器(这个数字是去年的)


Poppen.de网站架构

在了解过世界最大的PHP站点,Facebook的后台技术后,今天我们来了解一个百万级PHP站点的网站架构:Poppen.de。Poppen.de是德国的一个社交网站,相对Facebook、Flickr来说是一个很小的网站,但它有一个很好的架构,融合了很多技术,如 Nigix、MySql、CouchDB、Erlang、Memcached、RabbitMQ、PHP、Graphite、Red5以及Tsung。

Poppen.de目前有200万注册用户数、2万并发用户数、每天20万条私有消息、每天25万登录次数。而项目团队有11个开发人员,两个设计,两个系统管理员。该站点的商业模式采用免费增值模式,用户可以使用搜索用户、给好友发送消息、上载图片和视频等功能。

如果用户想享受不受限制发送消息和上载图片,那么就得根据需要支付不同类型的会员服务,视频聊天及网站其他服务也采用同样的策略。

Friday, August 27, 2010

Jay Chou

10年前就听Jay Chou,从第一张倒现在的专辑,每张必听,不过还算不上他的fans,不太喜欢他的摇滚风,R&B或者中国风还不错啦。特别是中国风,听起来就有种纯情歌的味道,虽然都是那种凄美的感觉,不过也好,给人很多遐想,也许方文山和Jay Chou就是那种人吧 :(

中国风里必备的二胡也许正适合这样的意境,难道二胡是贫苦劳动人民的智慧结晶?总是那么婉约凄美。总之,失恋必听。心情不好也可以听,可以以毒攻毒。

中国风里还有什么?当然还有一段若即若离的故事,虽然总有些不着边际,但是现代人总还是喜欢把自己放进那些故事,让自己和某某某成为故事的以部分,纵然是配角,但还是显得那么铭心刻骨,痛彻心扉。

中国风有种时光倒流的感觉,就是在那种感觉里,才能让彼此在自己的想像里任意放纵,是喜是悲,只不过是随着旋律转换罢了。明知道是想像,却还是不能自拔。也好,给自己一个说法,让流逝的月岁变成了只不过是一场幻境,一场戏。戏如人生、人生如戏。下一场戏于是也又要上演了。

Saturday, August 21, 2010

How to get current controller name and action name in Yii

To get current controller name/id inside your controller, or view
[cc lang='php']$controllerId = Yii::app()->controller->id;
//or
$controllerId = $this->getId();[/cc]
To get current action name/id being executed, if you are inside [cci]beforeAction()[/cci] or [cci]afterAction()[/cci], use the received CAction argument
[cc lang='php']
//inside beforeAction or afterAction
public function beforeAction($action)
{
$actionId = $action->id;
...
[/cc]
or just elsewhere inside your controller

[cc lang='php']$actionId = $this->getAction()->getId();[/cc]

Friday, August 20, 2010

Oracle的redo和undo区别

写的次序:

redo → undo → datafile
insert一条记录时, 表跟undo的信息都会放进 redo 中, 在commit 或之前, redo 的信息会放进硬盘上. 故障时, redo 便可恢复那些已经commit 了的数据.

redo → 每次操作都先记录到redo日志中,当出现实例故障(像断电),导致数据未能更新到数据文件,则数据库重启时须redo,重新把数据更新到数据文件
undo → 记录更改前的一份copy,但你系统rollback时,把这份copy重新覆盖到原来的数据

redo → 记录所有操作,用于恢复(redo records all the database transaction used for recovery)
undo → 记录所有的前印象,用于回滚(undo is used to store uncommited data infor used for rollback)

redo → 已递交的事务,实例恢复时要写到数据文件去的
undo → 未递交的事务.

Tuesday, August 17, 2010

在svn中设置mime

[cc lang="bash"]svn propset 'svn:mime-type' 'text/html' *.html
svn propset 'svn:mime-type' 'text/css' *.css[/cc]

极速 Twisted Web 60秒(6): 定制返回代码

[cc lang="python"]from twisted.web.server import Site
from twisted.web.resource import Resource
from twisted.internet import reactor

class PaymentRequired(Resource):
def render_GET(self, request):
request.setResponseCode(402)
return "Please swipe your credit card."

root = Resource()
root.putChild("buy", PaymentRequired())
factory = Site(root)
reactor.listenTCP(8880, factory)
reactor.run() [/cc]

Thursday, August 12, 2010

CACHE CONTROL WITH HTACCESS

[cc lang="apache"]
# Cache Control with .htaccess EXPIRES BY TYPE
# from http://forum.powweb.com/showthread.php?t=62786

### turn on the Expires engine
ExpiresActive On

### expires after a month in the client's cache
ExpiresByType image/gif A2592000
ExpiresByType image/png A2592000
ExpiresByType image/jpg A2592000
ExpiresByType image/x-icon A2592000
ExpiresByType application/pdf A2592000
ExpiresByType application/x-javascript A2592000
ExpiresByType text/plain A2592000

### expires after 4.8 hours
ExpiresByType text/css A17200

# Please note that the "A" before the numbers above stands for Access.
# This means that the stopwatch starts when a client accesses the file.
# You can also use "M" for modified.

# TIME CHEAT SHEET
# 300 5 MIN
# 600 10 MIN
# 900 15 MIN
# 1800 30 MIN
# 2700 45 MIN
#
# 3600 1 HR
# 7200 2 HR
# 10800 3 HR
# 14400 4 HR
# 18000 5 HR
# 36000 10 HR
# 39600 11 HR
# 43200 12 HR
# 46800 13 HR
# 50400 14 HR
# 54000 15 HR
# 86400 24 HR
#
# 86400 1 DAY
# 172800 2 DAY
# 259200 3 DAY
# 345600 4 DAY
# 432000 5 DAY
# 518400 6 DAY
# 604800 7 DAY
#
# 604800 1 WEEK
# 1209600 2 WEEK
# 1814400 3 WEEK
# 2419200 4 WEEK
#
# 2419200 1 MONTH (FEBRUARY)
# 2505600 1 MONTH (FEBRUARY LEAP YEAR)
# 2592000 1 MONTH (APRIL, JUNE, SEPTEMBER, NOVEMBER)
# 2678400 1 MONTH (JANUARY, MARCH, MAY, JULY, AUGUST, OCTOBER, DECEMBER)
# 31536000 12 MONTH[/cc]
[cc lang="apache"]

Header set Expires "Thu, 15 Apr 2010 20:00:00 GMT"
[/cc]

音乐需要social吗

音乐是用来听得,没错,从黑胶唱片到数码光碟,从电台DJ到Youtube,时代在发展,音乐得传播也在改变,唯一不变得是聆听。用Walkman得时候在聆听,交换音乐的方式是朋友和同学之间交换卡带和音乐,面对面得方式让我们可以更直接,更生动的对喜爱得音乐进行交流。用Ipod得时代我们依然在聆听,但是我们用网路交换,再也没有面对面的热情和欣喜。所以,我们加入社区得元素吧,让更多的人来填补感情空缺。于是last.fm来了。然后呢,电台VJ得位置被Youtube取代。聆听少了,social多了。

Wednesday, August 11, 2010

极速 Twisted Web 60秒(5): 错误句柄

[cc lang="python"]
from twisted.web.server import Site
from twisted.web.resource import Resource
from twisted.internet import reactor
from twisted.web.error import NoResource

from calendar import calendar

class YearPage(Resource):
def __init__(self, year):
Resource.__init__(self)
self.year = year

def render_GET(self, request):
return "
%s
" % (calendar(self.year),)

class Calendar(Resource):
def getChild(self, name, request):
try:
year = int(name)
except ValueError:
return NoResource()
else:
return YearPage(year)

root = Calendar()
factory = Site(root)
reactor.listenTCP(8880, factory)
reactor.run()
[/cc]

ubuntu下MySQL服务器更改目录后问题

[cc lang="text"]
100811 18:42:06 InnoDB: Operating system error number 13 in a file operation.
InnoDB: The error means mysqld does not have the access rights to
InnoDB: the directory.
InnoDB: File name ./ibdata1
InnoDB: File operation call: 'open'.
InnoDB: Cannot continue operation.
[/cc]
修改下面文件中得权限列表可解决问题。
[cc lang="text"]/etc/apparmor.d/usr.sbin.mysqld[/cc]
[cc lang="text"]/web/data/mysql/ r,
/web/data/mysql/** rwk,[/cc]

通过与Java的比较,迅速掌握Groovy

Groovy和Java的相同点有:
0+, 3+, 4+, 6+, 8+, 10+, 12+, 13, 14, 15, 18+, 19+, 20+, 21, 22, 23, 28+, 29+, 30+, 31+, 32+
+表示Groovy不但涵盖了Java的语法,而且还有增强部分

Groovy和Java的不 同 点有:
1, 2, 5, 7, 9, 11, 16, 17, 24, 25, 26, 27,33

Groovy轻松入门—搭建Groovy开发环境

Groovy既然是Java帝国的王储,当然少不了Java的支持。

先安装JDK(推荐版本为1.5及1.5以上,当然1.4也可以)

然后设置Java的环境变量:

  1. 设置环境变量[cci lang='text']java_home[/cci](设置环境变量[cci lang='text']XXX_home[/cci]的一个好处是只要修改XXX_home的值,与之相关的[cci lang='text']%XXX_home%\bin[/cci]等的值都相应改变,这样就能做到‘一处修改,处处修改’)右击‘我的电脑’-> ‘属性’ ->‘高级’-> ‘环境变量’-> 点击‘新建’(用户变量与系统变量均可,挑一便是)-> 输入‘变量名’为java_home -> 输入‘变量值’为JDK的所在目录(默认安装位置为[cci lang='text']C:\Program Files\Java\jdk1.6.0[/cci],我装的是JDK6.0)-> 点击‘确定’-> 环境变量[cci lang='text']java_home[/cci]设置成功

  2. 设置环境变量path环境变量java_home设置好之后,我们开始设置环境变量path前面的步骤与‘设置环境变量[cci lang='text']java_home[/cci]’相同,到点击‘新建’按钮时,选择新建用户变量(因为系统变量path已经存在,如果追加在长串已存在的path值后面,比较凌乱) -> 输入‘变量名’为path -> 输入‘变量值’为“[cci lang='text']%java_home%\bin;[/cci]” 不包括双引号“”

  3. 设置环境变量classpath环境变量path设置好之后,我们开始设置环境变量classpath前面的步骤与‘设置环境变量java_home’相同,到点击‘新建’按钮时,选择新建系统变量(我的个人习惯,你也可以选择新建用户变量)-> 输入‘变量名’为classpath -> 输入‘变量值’为“[cci lang='text'].;%java_home%\lib;[/cci]”不包括双引号“”,注意不要漏了最前面的小圆点.如果你已经安装了JDK,并设置好了Java环境变量,请跳过上述过程,直接安装GDK(只需3步)(如果您下载的是Groovy安装版Download Windows-Installer: Binary Release http://groovy.codehaus.org/Download,请将安装过程中出现的选项都打上勾,以下4,5,6步骤可以跳过)

  4. 下载GDK (http://dist.codehaus.org/groovy/distributions/groovy-1.0.zip)并将下载的groovy-1.0.zip文件解压到指定位置(我的位置是[cci lang='text']D:\D\MY_DEV\groovy[/cci]),

  5. 设置环境变量[cci lang='text']GROOVY_HOME[/cci]步骤与“设置环境变量java_home”类似,到 输入‘变量名’时,输入‘GROOVY_HOME’-> 输入‘变量值’为你解压指定位置(我的变量值为[cci lang='text']D:\D\MY_DEV\groovy[/cci]),需要注意一点,解压目录如[cci lang='text']D:\D\MY_DEV\groovy[/cci]中不可有空格,比如[cci lang='text']D:\D\MY DEV\groovy[/cci]

  6. 将[cci lang='text']GROOVY_HOME[/cci]目录下的bin追加到环境变量path中步骤与“设置环境变量path”类似,找到你设置的path,然后将“[cci lang='text']%GROOVY_HOME%\bin[/cci]”追加到path值(按上述过程,你现在的path为“[cci lang='text']%java_home%\bin;[/cci]”) 之后,你的path值为“[cci lang='text']%java_home%\bin;%GROOVY_HOME%\bin[/cci]” ,注意用英文分号;分开,不要有空白字符如空格,Tab等


Java帝国的王储—Groovy !

让我们来回顾一下主流语言的发展历程:机器语言(由01组成)  汇编语言 → ... → C语言 → C++ → Java → ?

不知道大家有没有发现在语言发展过程中,存在这么一个规律:能成为未来主流语言的,必与当前主流语言属同一‘语系’,换句话说,由王子继承王位。

在C语言之前,似乎还处于‘春秋战国’,各种编程语言混战,于20世纪70年代,C语言成为‘秦始皇’,各种软件甚至操作系统也改用C语言编写。但可惜C语言是面向过程的,程序代码一多,逻辑流程就容易混乱,再加上全局变量和可运算指针的添乱,使程序员调试程序万般辛苦。

Tuesday, August 10, 2010

How to Repair a Crashed MySQL Table

Today, I had a server crash when the /var partition filled up while reindexing. I attempted to clear out extra log files and such but df was still showing greater than 100% utilization. Checking /var/db/mysql showed I had one table that was taking up too much space. du -d 1 -h is a very useful command when tracking down the largest folder usage on partition.
Jul 21 07:39:06 plab2catsg01 kernel: pid 36500 (mysqld), uid 88 inumber 329992 o
n /var: filesystem full
Jul 21 07:39:22 plab2catsg01 kernel: pid 36500 (mysqld), uid 88 inumber 353413 o
n /var: filesystem full
Jul 21 07:39:23 plab2catsg01 kernel: pid 36500 (mysqld), uid 88 inumber 353288 o
n /var: filesystem full

I attempted to stop MySQL by executing /usr/local/etc/rc.d/mysql-server stop and unfortunately, it kept looping while trying to stop the process. I was eventually forced to reboot the server.



On reboot, I thought all was well but then I found the Eventum application I use wasn't showing support emails. I checked the MySQL log files:


plab2catsg01# tail -f plab2catsg01.ten-net.net.err
...
090721 9:15:54 [ERROR] /usr/local/libexec/mysqld: Table './eventum/eventum_mail
_queue' is marked as crashed and last (automatic?) repair failed
090721 9:15:54 [ERROR] /usr/local/libexec/mysqld: Table './eventum/eventum_mail
_queue' is marked as crashed and last (automatic?) repair failed
090721 9:15:55 [ERROR] /usr/local/libexec/mysqld: Table './eventum/eventum_mail
_queue' is marked as crashed and last (automatic?) repair failed
090721 9:15:55 [ERROR] /usr/local/libexec/mysqld: Table './eventum/eventum_mail
_queue' is marked as crashed and last (automatic?) repair failed
...

Use MySQL Regexp Sample

[cc lang="mysql"]DELETE FROM `google_data` WHERE site_id=4 AND url REGEXP '\.php\\?matchid=[0-9]+$'[/cc]

森林“板房”

Monday, August 9, 2010

苹果

以前总觉得苹果的 macbook pro 非常好,觉得matetext是那么Cool。以致于自己都想买一台,可是当自己做为Linux的9年用户得时候,觉得macbook并不是那么神通广大。然而Iphone,也不是那么炫。不是还有Android吗?放弃封闭的,投奔开放吧。

极速 Twisted Web 60秒(4): 动态URL处理

[cc lang="python"]
from twisted.web.server import Site
from twisted.web.resource import Resource
from twisted.internet import reactor

from calendar import calendar

class YearPage(Resource):
def __init__(self, year):
Resource.__init__(self)
self.year = year

def render_GET(self, request):
return "
%s
" % (calendar(self.year),)

class Calendar(Resource):
def getChild(self, name, request):
return YearPage(int(name))

root = Calendar()
factory = Site(root)
reactor.listenTCP(8880, factory)
reactor.run()
[/cc]

Friday, August 6, 2010

极速 Twisted Web 60秒(3): 静态URL处理

[cc lang="python"]
from twisted.web.server import Site
from twisted.web.resource import Resource
from twisted.internet import reactor
from twisted.web.static import File

root = Resource()
root.putChild("foo", File("/tmp"))
root.putChild("bar", File("/lost+found"))
root.putChild("baz", File("/opt"))

factory = Site(root)
reactor.listenTCP(8880, factory)
reactor.run()
[/cc]

沢尻エリカ

沢尻エリカの美しき官能の世界が表現された特集がNumero TOKYO 9月号(7/28発売)に掲載。

テーマはズバリ「露出」と「絡み」。

企画段階から沢尻エリカ本人が携わり、クリエーションへのこだわりが感じられる内容に。沢尻エリカはこのために体を作り上げ、撮影に挑んだそう。今の心情を語ったロングインタビューも衝撃的。

在Linux中把前台程序放到后台运行


  • 方法一:先通过 [cci lang='text' line_numbers='false']ctrl-z[/cci] 把程序放到后台,再通过 [cci lang='text' line_numbers='false']bg %[/cci] 提交命令到后台,最后使用 [cci lang='text' line_numbers='false']disown -h %[/cci]。现在就可以退出终端,程序依然还在运行。

  • 方法二:使用screen和retty[cc lang='bash' line_numbers='false']$ screen -S my_process
    $ retty $(pgrep my_process)
    /redraw[/cc]

Thursday, August 5, 2010

极速 Twisted Web 60秒(2): 生成动态页面

[cc lang="python"]
from twisted.internet import reactor
from twisted.web.server import Site
from twisted.web.resource import Resource
import time

class ClockPage(Resource):
isLeaf = True
def render_GET(self, request):
return "%s" % (time.ctime(),)

resource = ClockPage()
factory = Site(resource)
reactor.listenTCP(8880, factory)
reactor.run()
[/cc]

Tuesday, August 3, 2010

极速 Twisted Web 60秒(1): 访问静态目录文件

[cc lang='python' ]
from twisted.web.server import Site
from twisted.web.static import File
from twisted.internet import reactor

resource = File('/tmp')
factory = Site(resource)
reactor.listenTCP(8888, factory)
reactor.run()
[/cc]