从折腾 Gentoo 中的 gnome 3 所想到的……
TeX 与 Pinpoint 的结合

运行在 nginx 与 uwsgi 之上的 moinmoin

Garfileo posted @ 2011年4月24日 13:50 in Linux 的世界 with tags gentoo moinmoin nginx uWSGI , 18257 阅读

这篇文章主要是面向 Gentoo Linux 用户,其他 Linux 发行版用户只能慎重参考。之所以这样讲,是因为如果对于 nginx 与 uwsgi 不熟悉,很容易被各个发行版对它们自作主张的部署搞的头昏,主要问题出在系统的初始化脚本方面 [1]、缺乏足够的耐心以及对陌生知识的恐惧等方面。

准备

安装以下工具:

$ emerge -pv www-servers/nginx
$ emerge -pv www-servers/uwsgi
$ emerge -pv dev-python/virtualenv

nginx 是一个 http 服务器,与 apache、lighttpd、Microsoft IIS 等属于同类产品,对它的一些描述可参考 [2]。

uwsgi 是与 http 服务器与 python 应用程序之间进行数据交换的程序。

virtualenv 工具可将你系统所安装的 python 程序抽离出来,放在一个特定的目录下,供 python 应用程序(例如本文所讲的 moinmoin)使用。这样即便系统中更换了 python 版本,也不会对已部署的 python 应用产生负面影响。

完成上述软件包的安装后,下载 moinmoin 软件包(目前最新版本是 1.9.3):

$ cd /tmp
$ wget http://static.moinmo.in/files/moin-1.9.3.tar.gz
$ tar zxvf moin-1.9.3.tar.gz
$ cd moin-1.9.3
$ wget http://garfileo.is-programmer.com/user_files/garfileo/File/templates.py.patch
$ patch -p1 < templates.py.patch

上述的补丁来源于 http://hg.moinmo.in/moin/1.9/diff/a4a7f275b7b3/MoinMoin/support/werkzeug/templates.py,是 moinmoin 面向 python 2.7 的兼容补丁。之所以打这个补丁,是因为在 gentoo 系统中,如果在 /etc/make.conf 中开启了 ~x86 之类的关键字,那么活动的 python 版本是 2.7。

安装 moinmoin

######### 为了方便,切换为 root 用户
$ sudo -s

######## 构建 python 的隔离环境
# mkdir -p /var/www/moinmoin
# virtualenv /var/www/moinmoin/python-env

######## 激活 python 隔离环境,并将 moinmoin 安装至其中
# cd /tmp/moin-1.9.3
# source /var/www/moinmoin/python-env/bin/activate
# python setup.py install

######## 将 moinmoin 的实例安装至 /var/www/moinmoin/wiki 目录
# cp -r ./wiki /var/www/moinmoin
# cd /var/www/moinmoin/wiki
# cp config/wikiconfig.py ./
# cp server/moin.wsgi ./

######## 关闭 python 隔离环境
# deactivate

######## 退出 root 用户环境
# exit

完成上述步骤之后,可以发现,拜 virtualenv 工具所赐,所有与 moinmoin 相关的文件均被安装至 /var/www/moinmoin/python-env/share/moin 与 /var/www/moinmoin/python-env/lib/python2.7/site-packages/MoinMoin 目录,而原本它们默认是被安装至 /usr/share/moin 与 /usr/lib/python2.7/site-packages/MoinMoin 目录。

uwsgi 出错试验

uwsgi 实际上也是一个 http 服务器,只不过它只面向 python 网络应用程序。在本文中,uwsgi 所扮演的的角色是后端 http 服务器,nginx 扮演的角色是前端 http 服务器,而 moinmoin 是客户端应用程序。 moinmoin 用户从网页浏览器中发出请求,nginx 服务器收到请求后,会通过它的 uwsgi 模块将用户的请求转发给 uwsgi 服务器。

虽然 uwsgi 也是 http 服务器,但是却不能直接使用它部署 python web 应用程序,否则会出错。我们可以做一个试验,亲身体验一下出错。如果你对试验不感兴趣可以忽略这一节。

$ sudo -s
# cd /var/www/moinmoin/wiki
# mv moin.wsgi moin_wsgi.py
# mkdir -p /etc/uwsgi
# cat > /etc/uwsgi/uwsgi.xml << EOF
<uwsgi> 
<socket>127.0.0.1:8000</socket> 
<pythonpath>/var/www/moinmoin/python-env/lib/python2.7/site-packages</pythonpath>
<pythonpath>/var/www/moinmoin/wiki</pythonpath>
<module>moin_wsgi</module>
</uwsgi>
EOF

# exit

上述步骤中,之所以要前往 /var/www/moinmoin/wiki 目录将 moin.wsgi 文件名改为 moin_wsgi.py,是因为 uwsgi 只能识别出扩展名为 .py 的文件,请认真观察 /etc/uwsgi/uwsgi.xml 文件。

然后,执行以下命令:

$ uwsgi -x /etc/uwsgi/uwsgi.xml

便可以开启 uwsgi 服务器的守护进程。

现在,打开网络浏览器,例如 firefox,在地址栏中输入”http://127.0.0.1:8000“并回车,这时网页中会显示“The connection was reset”……@#¥%……不要怪罪 G.F.W,这不是它的错!看看开启 uwsgi 守护进程的终端,应当可以看到类似下面的信息:

invalid request block size: 21573...skip

这表示,你在浏览器中提交的 http 请求被 uwsgi 给忽视了。如果你不断的刷新那个页面,终端中会不断涌出该信息。

虽然我们得到的是被重置的页面,但是这足以证明 uwsgi 是一个 http 服务器。

现在,试验做完了,还是将环境恢复为原来的样子吧!

# sudo -s
# cd /var/www/moinmoin/wiki
# mv moin_wsgi.py moin.wsgi
# rm /etc/uwsgi/uwsgi.xml
# exit

配置 nginx

uwsgi 需要 nginx 作为 http 服务器前端方可处理客户的 http 请求。下面来看如何配置 nginx,使之可将客户的请求转发给 uwsgi。

nginx 的配置文件在 /etc/nginx 目录,打开该目录中的 nginx.conf 文件,在其中的 “http” 部分添加以下代码:

#  moinmoin 虚拟主机配置
	server {
		listen 192.168.0.7;
		server_name localhost;

		access_log /var/log/nginx/wiki.access_log main;
		error_log /var/log/nginx/wiki.error_log info;

		location ^~ /wiki {
			include uwsgi_params;
			uwsgi_pass unix:///tmp/wiki.sock;
			uwsgi_param UWSGI_PYHOME /var/www/moinmoin/python-env/;
			uwsgi_param UWSGI_CHDIR /var/www/moinmoin/wiki/;
			uwsgi_param UWSGI_SCRIPT moin.wsgi;
			uwsgi_param SCRIPT_NAME /wiki;
			uwsgi_modifier1 30;
		}

		location ^~ /wiki/moin_static193/ {
			alias /var/www/moinmoin/python-env/lib/python2.7/site-packages/MoinMoin/web/static/htdocs/;
			add_header Cache-Control public;
			expires 1M;
		}
	}



包含上述代码的一份完整的 nginx.conf 文件可从这里获得。

注意:上述代码中的“192.168.0.7”是我的机器的局域网 IP,如果你要使用这份代码,那么应当将其替换为你的机器的 IP。

下面,大致分析一下上述代码的工作过程。

首先,“listen 192.168.0.7;”设置 nginx 服务器负责监听(网页浏览器)传入的“http://192.168.0.7”请求。请求信息会被写入 /var/log/nginx/wiki.access_log 文件,出错信息会被写入 /var/log/nginx/wiki.error_log 文件。如果你的 moinmoin 配置未能成功,那么认真查看 /var/log/nginx/wiki.error_log 文件也许能发现出错原因。

然后,如果网页浏览器传入的请求是“192.168.0.2/wiki”,那么 nginx 会根据 "location ^~ /wiki" 代码段的设定主要进行以下处理:

  • 加载 /etc/nginx 目录中的“uwsgi_params.conf”文件;
  • 通过 /tmp/wiki.sock 文件与 uwsgi 服务器通信,这个 wiki.sock 文件所起得作用类似于进程管道;
  • 设置 python 运行环境,这里使用的是上文中 virtualenv 工具所构造的 python 目录,其中包含着 python 程序本身以及上文中所安装的 moinmoin 软件包;
  • 设置 uwsgi 服务器在相应 http 请求(http://192.168.0.7)之前,先进入 /var/www/moinmoin/wiki 目录,这个目录是前文中我们建立的 moinmoin 实例;
  • 设置 uwsgi 服务器要运行的 python 程序,即 moin.wsgi;
  • 设置 uwsgi 服务器所运行的 python 程序对应的 http 请求为 http://192.168.0.7/wiki

由于我对 nginx 与 uwsgi 的配置所知有限,上述理解可能会有所偏差,特别是有关 uwsgi 一些变量的含义的解释请以官方文档 [3] 为准。

事实上, "location ^~ /wiki" 代码段所做的工作大致等价于(因为没有设置 python 运行环境)以下命令:

$ uwsgi -s /tmp/wiki.sock --wsgi-file /var/www/moinmoin/wiki/moin.wsgi

配置 uwsgi

uwsgi 在 Gentoo 系统中没有获得 nginx 那样的待遇,写 uwsgi ebuild 的那位同学没有为其提供初始化脚本。如果希望直接在命令行中启动 uwsgi,那么只需使用以下命令即可:

$ sudo -u uginx uwsgi -x /etc/uwsgi/uwsgi.xml

当然,这需要在 /etc/uwsgi 目录中建立 uwsgi 的配置文件 uwsgi.xml,内容如下:

<uwsgi>
    <socket>/tmp/wiki.sock</socket>
    <limit-as>256</limit-as>
    <processes>6</processes>
    <memory-report/>
    <vhost/>
    <no-site/>
</uwsgi>

不过,按照文档 [1] 所述的 Gentoo 初始化脚本文件的框架,我们可以自行定义 uwsgi 启动脚本,内容如下:

#!/sbin/runscript

UWSGI_CONF="/etc/uwsgi/uwsgi.xml"
UWSGI_LOG="/var/log/uwsgi.log"
UWSGI_PID="/var/run/uwsgi.pid"
UWSGI_OPTS="-x $UWSGI_CONF -d $UWSGI_LOG --vacuum --pidfile $UWSGI_PID"

depend() {
    need net
    use nginx
}

start() {
    ebegin "Starting uwsgi server"
    start-stop-daemon --start --exec /usr/bin/uwsgi -- $UWSGI_OPTS
    eend $? "Failed to start uwsgi"
}

stop() {
    ebegin "Stopping uwsgi server"
    kill -HUP `pidof uwsgi` &> /dev/null
    sleep 3
    eend $? "Failed to stop uwsgi"
}

然后将其命名为“uwsgi”,置于 /etc/init.d 目录,并为其追加可执行权限:

$ sudo chmod +x /etc/init.d/uwsgi

测试 moinmoin 可否工作

使用以下命令开启 nginx 与 uwsgi 服务器:

$ sudo /etc/init.d/nginx start
$ sudo /etc/init.d/uwsgi start

如果想在开机时启动 nginx 与 uwsgi 服务器,可以:

$ sudo rc-update add nginx default
$ sudo rc-update add uwsgi default

然后,打开网页浏览器,输入“http://192.168.0.7/wiki”(再次申明:这里的 IP 是我机器的 IP,而你应当使用你在 /etc/nginx/nginx.conf 文件中所设置的 IP)并回车,也许你看到的是一个出错页面,出错信息如下:

uWSGI Error

wsgi application not found

出错的原因是因为是因为 uwsgi 只能识别出扩展名为 .py 的文件,而我们在 /etc/nginx/nginx.conf 文件中给出的脚本文件名是“moin.wsgi”,而 uwsgi 服务器获得这个文件名之后,它会到 /var/www/moinmoin/wiki 中查找有没有“moin.wsgi.py”的文件,而 /var/www/moinmoin/wiki 中只有 moin.wsgi 文件,所以 uwsgi 这个愚蠢的家伙便不知所措了。解决这个问题的办法如下:

$ cd /var/www/moinmoin/wiki
$ sudo mv moin.wsgi moin_wsgi.py
$ sudo sed -i s/moin.wsgi/moin_wsgi/g /etc/nginx/nginx.conf
$ sudo /etc/init.d/nginx restart

然后再刷新一下刚才的出错页面。现在应该可以看到 moinmoin wiki 的欢迎页面了。


 

参考文档

[1] Gentoo 系统初始化脚本知识

[2] Nginx 的中文维基

[3] uWSGI 变量的文档

转载时,希望不要链接文中图片,另外请保留本文原始出处:http://garfileo.is-programmer.com

sadfadsf 说:
2014年1月09日 18:44

invalid request block size: 21573...skip
浏览器直接访问而控制台出现这个信息的原因是你配置socket不是给你用浏览器http拿来交互用的。
而是给nginx之类的服务器信息交互的协议。


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter