damien.h

Compile cmemcache on Gentoo

I needed to install cmemcache on a Gentoo box in order to enable Django to work with memcached. But when I tried to compile the cmemcache code, I got such error messages:

‘CmemcacheObject’ has no member named ‘mc_ctxt’

I’m surprised Google didn’t give me many answers. But I came across this post which was very useful. So in the end, here’s how I got cmemcache compiled and installed on Gentoo.

cd ~/code
sudo emerge libmemcache
wget http://gijsbert.org/downloads/cmemcache/libmemcache-1.4.0.rc2.patch
wget http://gijsbert.org/downloads/cmemcache/cmemcache-0.95.tar.bz2
# the patch was made using a folder called reference
mkdir reference
cd reference
tar xjvf ../libmemcache-1.4.0.rc2.tar.bz2
cd ..
patch -p0 < libmemcache-1.4.0.rc2.patch
cd reference/libmemcache-1.4.0.rc2
./configure && make
sudo make install
cd ../../
tar xjvf cmemcache-0.95.tar.bz2
cd cmemcache-0.95
sudo python setup.py install

code_swarm Python

今天又看到了code_swarm的Python视频,不禁贴出来共赏。外加code_swarm Eclipse作为Bonus。


code_swarm – Python from Michael Ogawa on Vimeo.


code_swarm – Eclipse (short ver.) from Michael Ogawa on Vimeo.

如何在Django+Nginx fcgi方式下不间断服务地部署新代码

极品座驾“上线以来,用户访问量一直运行在高位,上周末创下了单日pv 139万的记录。在这样的情况下,保持服务不间断是最重要的事情。目前我们支撑这样访问量的架构,是使用Nginx作为web服务前端,用fcgi方式运行django的python进程,再和前端Nginx连接起来。fcgi模式下,python进程把字节码装入内存,来提供最佳的执行速度。但是这样带来的问题就是更新了python代码以后,服务器没法动态装入新代码,而是需要杀掉现有fcgi进程然后spawn新进程才能达到更新代码的目的。虽然重启django fcgi进程的速度很快,但是不可避免的会导致用户服务的中断,在访问量大的情况下更是很危险的方式。为了达到不中断服务的目的,我们采用了这样的方法:

  1. 更新python代码
  2. 在另一个端口spawn一组新的fcgi进程
  3. 更改Nginx配置,把proxy_pass转发端口指向新fcgi进程的端口
  4. 动态重载Nginx配置
  5. 过一段时间等到原fcgi端口不再有未完成的用户请求,再把原端口上的进程全部杀掉

由于Nginx可以在运行状态下不间断的重载配置改动,所以在重载配置以后所有的访问请求都被转发到新的fcgi端口了。而在用户操作频繁的时候,访问请求从原fcgi端口被转到新端口也只需要很短的时间(可以借助netstat命令来观察)。这样一来,就可以实现在不影响用户操作的情况下不间断的切换到新代码了。

用Python+Django+Google App Engine开发SNS应用(一):校内和PyXn

大家好!我是Marsbug团队的Damien。今天起,我会在本blog陆续发表一系列关于Python, Django, Google App Engine以及SNS应用开发的文章。

SNS应用可以说是web2.0时代mashup概念的一个非常成功的例子。从Facebook F8平台开始,SNS应用经过1年的发展已经深入人心。而在F8开放一年之际,国内的SNS领域也开始了一场开放平台大战,这也是我们开发者一展身手的好机会。今天,让我先从开发校内应用谈起吧。

开发技术的选择

目前Marsbug已经在校内Manyou51.com上开发了多款应用。我们使用的技术,主要包括Python+Django+Google App Engine,以及RoR+Heroku。在服务器方面,我们选择的都是新兴的云计算服务,是因为它们非常适合我们团队的需要:从零成本起步,按需付费,即使访问量上去了,也不必过多操心性能问题。

那么,怎么使用Google App Engine开发校内应用呢?

首先,GAE目前只支持Python作为开发语言,所以我选择了Python+Django来开发应用。本质上来讲,SNS应用的开发和网站开发没有本质区别。最大的不同在于SNS应用的Mashup性质:需要调用SNS平台的API接口来完成一些交互功能。

校内平台官方提供的是Java API开发包,并没有Python开发包。为此,我在PyFacebook基础上为校内平台定制了PyXn开发包,提供和PyFacebook一致的使用方式,维持了良好的可扩展性和轻量封装的理念,也已经经过了我们多款应用的实战检验。PyXn的代码可以从Google Code上得到:http://pyxn.googlecode.com 请直接checkout svn最新版,目前没有提供打包下载。

Django+PyXn的使用

PyXn对校内API调用进行了轻量封装,对Django和GAE做了特别支持。所以,使用PyXn在Django+GAE上进行开发是一件很轻松的事。由于PyXn的GAE支持对开发者是透明的,本文就以Django+PyXn的组合作为例子。GAE的开发细节留待下一篇文章说明。

首先,建立一个新的Django site

django-admin.py startproject mysite

然后,建立一个app

django-admin.py startapp myapp

把PyXn文件包整个复制到django site根目录下面,和django app目录同级。也就是:

mysite
>myapp
>pyxn
manage.py
settings.py
urls.py

在settings.py里,配置好PyXn需要的参数

MIDDLEWARE_CLASSES = [
    ...
    'pyxn.djangoxn.XiaoneiMiddleware',
    ...
]
XIAONEI_API_KEY = 'api_key'
XIAONEI_SECRET_KEY = 'api_secret'
XIAONEI_APP_NAME = 'my_app'
XIAONEI_CALLBACK_PATH = "/xn/" #相对于url根的callback_path

这样,就能开始利用PyXn进行校内应用开发了。注意到我们添加了PyXn提供的’pyxn.djangoxn.XiaoneiMiddleware’,这个Middleware的作用是再每个request中自动加入一个pyxn.Xiaonei的实例,调用校内API就是通过直接调用这个Xiaonei实例中定义的函数来做的。同时,djangoxn模块里还提供了require_add()这个decorator,对于对应于一个XNML页面的view函数,需要用require_add()来修饰,从而得到一个直接可用的xiaonei实例。看下面这个例子。

import pyxn.djangoxn as xn
from django.utils import simplejson

@xn.require_add()
def foo(request):
    xn = request.xiaonei
    #make api calls now
    friends = xn.friends.getFriends()
    xn.profile.setXNML(profile='some xnml')
    xn.feed.publishTemplatizedAction(template_id='1', title_data=simplejson.dumps({'foo':'bar'}))

在上面这段代码中,@xn.require_add()这步decorator操作实际上做的事情是检查request里从校内服务器传过来的参数,如果必须的用户登录信息都存在,那么就自动建立一个完整的xiaonei实例;否则,自动重定向到app安装页面,要求用户安装后才能访问这个页面。

调用校内API的时候需要在POST数据里提供一些必须的app和用户数据,包括预定义的api_key, api_secret,以及从request里得到的session_key,uid。而xn.require_add()这步检查做的事情就是把这些必须的参数填入新建的Xiaonei实例,而通过xiaonei实例调用api的时候会自动把必须的参数封装整理到POST数据里。也就是说,只有一个定义了必须参数值的xiaonei实例才能成功调用api,而xn.require_add()对于需要调用api的view函数是必须的。

以上的例子适用于XNML页面对应的view函数,因为用于重定向到安装页面的方法实际上是返回<xn:redirect>给校内服务器。在开发校内应用的时候,还经常会需要用到iframe页面,比较多的情况是xnml页面上嵌入iframe页面。iframe页面[email protected]_add来修饰了,而是通过xiaonei.check_session()函数来显式的检查request参数,并自动构造一个xiaonei实例,并填入调用api必须的参数。实际上,xn.require_add()这个decorator也是通过check_session()函数来从构造完整的Xiaonei实例的。我们在iframe的情形下,只不过是不需要redirect这一步,而是直接check_session()就行了。

def iframe_view(request):
    xn = request.xiaonei
    xn.check_session(request)
    #make api calls now
    friends = xn.friends.getFriends()

你可能会问,那么这种情况下,用户没有安装就访问这个页面的时候怎么把用户重定向到安装地址呢?这就可以通过给包含着这个iframe的xnml页面对应的view加上xn.require_add()这个decorator就行了。(不推荐纯iframe形式的app)

小提示

所有校内API的调用,都是通过Xiaonei类的实例进行的。而调用格式完全可以参照校内api的定义来推测。比如,friends.getFriends()这个api,就是用xiaonei.friends.getFriends()。而api需要的参数,也按照api定义的类型来提供。

推荐大家略读一下pyxn.__init__.py的代码,从114行开始定义的METHODS dict就能方便的看出具体api调用函数的格式。例如这个定义:

'feed': {
        'publishTemplatizedAction': [
            ('template_id', int, []),
            ('title_data', json, ['optional']),
            ('body_data', json, ['optional']),
            ('resource_id', int, ['optional']),
        ],
    },

这就是定义了xiaonei.feed.publishTemplatizedAction这个api方法。其中,template_id参数是必填的,类型是int,其余都是可选参数,类型分别是json和int。具体调用例子请参考上文实例。

总结

好了,在Django环境下使用PyXn今天就介绍到这里。下次会详细谈一下我们是如何在Google App Engine上,运用Django+PyXn这套工具来开发应用的。

Browse Happy logo

My tweets

2016年五月
« 八    
 1
2345678
9101112131415
16171819202122
23242526272829
3031  

分类目录

Articles

Fancy Stats