集成uWSGI和Erlang¶
警告
自1.9.20起,Erlang支持已经不能用了。新方案正在开发中。
uWSGI服务器可以作为一个Erlang C-Node,并且和Erlang节点交换数据以及进行RPC。
构建¶
首先,你需要 ei
库和头文件。在官方的Erlang包中可以找到它们。如果你在Debian/Ubuntu之上,那么安装
erlang-dev
包。可以嵌入Erlang支持,或者将其当成一个插件进行构建。要嵌入,则添加 erlang
和 pyerl
插件到你的构建配置文件中。
embedded_plugins = python, ping, nagios, rpc, fastrouter, http, ugreen, erlang, pyerl
或者将其作为插件构建
python uwsgiconfig --plugin plugins/erlang
python uwsgiconfig --plugin plugins/pyerl
Erlang插件将允许uWSGI成为一个Erlang C-Node。 pyerl
插件将添加Erlang函数到Python插件中。
激活Erlang支持¶
你只需要设置两个选项来在你的启用Erlang的uWSGI构建中启用Erlang支持。 erlang
选项设置了你的uWSGI服务器的Erlang节点名。它可以以简单或扩展格式指定:
nodename@ip
nodename@address
nodename
erlang-cookie
选项为内部节点通信设置cookie。如果你不指定它,那么会从~/.erlang.cookie
文件获取这个值。
要运行带启用Erlang的uWSGI:
uwsgi --socket :3031 --erlang [email protected] --erlang-cookie UUWSGIUWSGIU -p 2
一个简单的RPC hello world例子¶
定义一个新的Erlang模块,它只导出一个简单的函数。
-module(uwsgitest). -export([hello/0]). hello() -> 'hello world !'.
启动
erl
shell,指定节点名和(最终) (eventually) cookie:erl -name [email protected]
编译uwsgitest Erlang模块
c(uwsgitest). {ok,uwsgitest}
... 然后试着运行
hello
函数:uwsgitest:hello(). 'hello world !'
不错 - 现在,我们的Erlang模块就能用了,我们准备好RPC了!返回你的uWSGI服务器机器,然后定义一个新的WSGI模块 —— 让我们称之为
erhello.py
.
import uwsgi
def application(env, start_response):
testnode = uwsgi.erlang_connect("[email protected]")
start_response('200 OK', [('Content-Type', 'text/plain')])
yield uwsgi.erlang_rpc(testnode, "uwsgitest", "hello", [])
uwsgi.erlang_close(testnode)
或者快速方式
import uwsgi
def application(env, start_response):
start_response('200 OK', [('Content-Type', 'text/plain')])
yield uwsgi.erlang_rpc("[email protected]", "uwsgitest", "hello", [])
现在,使用这个新的模块启动uWSGI服务器:
uwsgi --socket :3031 --erlang [email protected] --erlang-cookie UUWSGIUWSGIU -p 2 -w erhello
在你的浏览器中访问启用了uWSGI的web服务器,你应该会看到你的Erlang RPC调用的输出。
Python-Erlang映射¶
uWSGI服务器试着根据下面这张表将Erlang类型转换成Python对象。
Python | Erlang | 注意 |
---|---|---|
str | binary | |
unicode | atom | 受内部atom大小限制 |
int/long | int | |
list | list | |
tuple | tuple | |
3-tuple | pid |
发送消息给Erlang节点¶
Erlang的最强大的特性之一是节点间消息传递系统。uWSGI也可以与Erlang节点进行通信。让我们定义一个新的Erlang模块,它简单回显任何我们发送给它的东西。
-module(uwsgiecho).
-export([start/0, loop/0, echo/1]).
echo(Message) ->
{i_am_echo , Message}.
loop() ->
receive
Message1 ->
io:format("received a message~n"),
{ useless, '[email protected]' } ! echo(Message1)
end,
loop().
start() ->
register(echoer, spawn(uwsgiecho, loop, [])).
记得用Erlang register
函数注册你的进程。使用pid来标志进程是有问题的。现在,你可以用
uwsgi.erlang_send_message()
来发送消息。
uwsgi.erlang_send_message(node, "echoer", "Hello echo server !!!" )
第二个参数是注册进程名。如果你不指定名字,那么传递一个Python的3元素元组会被解析为一个Pid。如果你的Erlang服务器返回消息给你的请求,那么你可以用
uwsgi.erlang_recv_message()
来接收它们。记住,即使Erlang需要一个进程名/pid来发送消息,但是它们将被uWSGI所忽略。
接收Erlang消息¶
有时,你想直接从一个Erlang节点发送消息给uWSGI服务器。要接收Erlang消息,你必须在你的Python代码中注册”Erlang进程”。
import uwsgi
def erman(arg):
print "received an erlang message:", arg
uwsgi.erlang_register_process("myprocess", erman)
现在,在Erlang中,你可发送消息给你注册的”myprocess”进程了:
{ myprocess, '[email protected]' } ! "Hello".
RPC¶
你可以直接从Erlang调用uWSGI uWSGI RPC栈 函数。
rpc:call('[email protected]', useless, myfunction, []).
这将会调用一个配置为Erlang节点的uWSGI服务器上的”myfunction” uWSGI RPC函数。
连接持久化¶
在高负载站点上,为每一个Erlang交互打开和关闭连接是很过分的。在你的应用初始化过程中用
uwsgi.erlang_connect()
打开一个连接,并让文件描述符保持。
Mnesia又如何?¶
当你需要一个高可用性站点的时候,我们建议你使用 Mnesia 。构建一个Erlang模块来公开所有你需要的数据库交互,并且使用
uwsgi.erlang_rpc()
来与之交互。
我可以在uWSGI之上运行 EWGI 应用吗?¶
现在,是不行的。最好的方式是开发一个插件,并且为EWGI应用分配一个特殊的modifier。
那在此之前,你可以在Python代码中封装即将到来的请求为EWGI形式,并使用 uwsgi.erlang_rpc()
来调用你的Erlang应用。