Wiki我選擇了用Python的MoinMoin,一定程度上受CPYUG社區 ZoomQuiet 大媽的推薦影響,首次試用感覺非常impresive,所以就定了。再加上 GraphViz 工具的支持,實在的強大。
在vps上服務,肯定是無視apache的,內存有限。之前架設過用來上Twitter奶瓶腿,是Nginx + php-cgi的方案,nginx是必須的。
Python跟web前端的架構方式有太多選擇了,五花八門,MoinMoin的發行包里面都提供了moin.cgi
moin.scgi
moin.ajp
moin.fcgi
moin.wsgi
等多種啟動方式。MoinMoin里面全部通過內置的flup作為中間件提供這些接口,目前我僅嘗試使用了fastcgi和wsgi。
雖然解壓了moin的源碼包就可以直接運行里面的wikiserver.py
來本地訪問了,但在服務器上通常是由nginx/lighttpd等服務來綜合轉發。php的話是通過spawn-fcgi
啟動一些php-cgi的進程,服務器接受到動態的請求就通過本地socket跟php-cgi通訊,返回的結果展現回給客戶。php-cgi是使用FastCGI協議的。
MoinMoin 源碼當中wiki/server/moin.fcgi
就是一個類似php-cgi功能的fastcgi服務,類似地可以使用spawn-fcgi
來啟動moin.fcgi,作為后端的處理進程。
Running MoinMoin Wiki with Nginx via FastCGI and Flup該文章很形象解釋了fastcgi的角色,以及提供了一段很方便的服務腳本來啟動spawn-fcgi
。
Client ----> Nginx Web Frontend -----------+ | fastcgi_pass \|/ +-------------------------+ moin.fcgi | spawn-fcgi-moin.socket | spawn-fcgi ---------------> | or | | localhost:port | +-------------------------+
但是文章當中的nginx配置不完整,而且復雜了,這是我的配置:
server { listen 80; ## listen for ipv4 server_name wiki.apt-blog.net; access_log /var/log/nginx/wiki.apt-blog.net.access.log; error_log /var/log/nginx/wiki.apt-blog.net.error_log; location / { include fastcgi_params; fastcgi_param PATH_INFO $fastcgi_script_name; fastcgi_param SCRIPT_NAME /; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; if (!-f $request_filename) { fastcgi_pass unix:/var/run/spawn-fcgi-moin.socket; } } }
當然那文章中的配置有考慮對靜態文件直接由nginx服務,不通過flup這一層,有一定優化,這里省去了這些。其實增多一個/moin_static193
(據版本號不同而不同)的location即可,可參考后面使用uwsgi做服務時候的配置。
文章還提到wikiconfig.py
里面一個fix_script_name
變量,是1.9版本新加入的,需要xxx.com/wiki這樣訪問的童鞋就不用像以前版本那樣要在nginx配置里面寫一大堆東西了。
Fastcgi就這么多,不算太復雜。Fastcgi雖然很流行,但弊端不少,首先是速度,在一臺虛擬機上測試,用ab居然跑出每秒20個請求的速度……雖然平均下來還是有5、60次,但真的,唉。php-cgi還支持產生多個工作進程以并行和均衡請求,提高效率,fastcgi似乎就沒這樣的東西了。
剛好這天observer專欄雜記寫了一篇配置Nginx+uwsgi更方便地部署python應用,當中也提到fcgi
和 mod_python
的各種不便,然后介紹了uwgi
,高性能、多應用。
uwgi充當了python解析器的角色,使用wsgi的接口和Python程序交互,這個過程中做了優化,和上層nginx之間則設計了更加輕量的協議。nginx0.8.40以后官方默認帶了uwgi的協議模塊,所以使用很方便。
uwgi的文檔有些簡略,但是重點都是在wiki/Example里面了。 MoinMoin在uwgi的配置在其中一句帶過:
/usr/bin/uwsgi -s /tmp/moin.sock --wsgi-file wiki/server/moin.wsgi -M -p 4
uwgi的-w參數是把某個py文件作為module,import使用,但是wsgi文件不被認識,所以新版里面多了這么個--wsgi-file
參數。但是如果是多站點呢!
nginx配置的虛擬主機里面的uwsgi_param UWSGI_SCRIPT
參數會讓uwgi按模塊導入名稱,相當于命令行里面的-w
,但是moinmoin的moin.wsgi文件,不是py結尾,只能用--wsgi-file
參數。掃了一圈uwgi的wiki/Example和RunOnNginx,都沒提到這個問題,倒是在這里提到在舊版的uwgi當中沒有--wsgi-file
參數,需要把wsgi文件改名成py結尾來導入,好吧,確實那樣成功了。
至于性能,一開始我發現uwgi占的內存也不少,一個worker時候就占了20M多的內存,所以沒開更多的工作進程;Fastcgi也差不多,然后用Apache Benchmark測試,好像兩者區別不大。于是看了下fcgi vs. gunicorn vs. uWSGI的測評,才發現uwgi要開多個worker進程才有性能!于是開了8個,性能出來了,秒請求馬上就上千! 顯然是uwgi打開了多個進程,充分利用了機器的CPU,還做了均衡請求。
最后,我的Wiki使用uwgi后的nginx配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | server { server_name wiki.apt-blog.net; access_log /var/log/nginx/wiki.apt-blog.net.access.log; error_log /var/log/nginx/wiki.apt-blog.net.error_log; location / { include uwsgi_params; #uwsgi_pass 127.0.0.1:9096; uwsgi_pass unix:///tmp/uswgi.sock; uwsgi_param UWSGI_PYHOME /usr/local/lib/moinmoin; uwsgi_param UWSGI_CHDIR /var/local/wiki-moinmoin/server; uwsgi_param UWSGI_SCRIPT moin_wsgi; } location /moin_static193/ { alias /usr/local/lib/moinmoin/lib/python2.6/site-packages/MoinMoin/web/static/htdocs/; } } |
完整配置指南:
#安裝 sudo -s add-apt-repository ppa:nginx/stable add-apt-repository ppa:uwsgi/release apt-get update apt-get install nginx uwsgi-python python-virtualenv #組件配置 cat >/etc/uwsgi-python/apps-enabled/uwsgi.xml << EOF <uwsgi> <limit-as>256</limit-as> <processes>6</processes> <memory-report/> <vhost/> <no-site/> </uwsgi> EOF cat >/etc/nginx/sites-enabled/moinmoin << EOF server { listen 80; access_log /var/log/nginx/wiki.access_log; error_log /var/log/nginx/wiki.error_log; client_max_body_size 64; server_name wiki.mydomian.com; location / { include uwsgi_params; uwsgi_pass unix:///var/run/uwsgi-python/uwsgi/socket; uwsgi_param UWSGI_PYHOME /var/www/moinmoin/python-home/; uwsgi_param UWSGI_CHDIR /var/www/moinmoin/; uwsgi_param UWSGI_SCRIPT moin_wsgi; uwsgi_param UWSGI_SCHEME $scheme; uwsgi_param REMOTE_USER $remote_user; } } EOF #Python環境預備 mkdir /var/www/moinmoin virtualenv /var/www/moinmoin/python-home cd /tmp wget http://static.moinmo.in/files/moin-1.9.3.tar.gz tar xvfz moin-1.9.3.tar.gz source /var/www/moinmoin/python-env/bin/activate cd /tmp/moin-1.9.3 python setup.py install deactivate #MoinMoin環境 cp -r /tmp/moin-1.9.3/wiki /var/www/moinmoin cd /var/www/moinmoin/wiki cp config/wikiconfig.py wikiconfig.py cp server/moin.wsgi moin_wsgi.py sed -i '/# a2)/isys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))' #可選 rm -rf config server #重啟 /etc/init.d/nginx restart /etc/init.d/uwsgi-python restart