我已浏览Mochiweb code,但未找到任何状态变量的迹象。
Mochiweb中是否存在类似于gen_server的State变量的内容?
我需要在服务器上存储少量与状态相关的服务器端(不是与会话相关的)数据,我不想为此使用ETS或Mnesia。
答案 0 :(得分:1)
我认为你对gen_server状态有些误解。
首先,让我简要解释一下mochiweb的工作原理。
Mochiweb不会为每个客户端生成gen_server进程。相反,它只是使用proc_lib:spawn/3
生成一个新进程并创建一个参数化模块,它基本上是一个以下类型的元组:
{mochiweb_request, #Port<0.623>, get, "/users", {1, 1}, []}
是
{mochiweb_request, Socket, Method, RawPath, HTTPVersion, Headers}
此元组用作函数的参数,该函数作为循环参数传递给mochiweb_http:start/1
。因此,当调用此“循环”函数时,它将如下所示:
handle_request(Req) ->
%% The pattern matching below just shows what Req really is
{mochiweb_request, _, _, _, _, _} = Req,
...
现在,解释gen_server状态。
基本上,gen_server是一个具有大致以下结构的过程。当然,IRL它更复杂,但这应该给你一般的想法:
init(Options)
State = ...
loop(Module, State).
loop(Module, State)
NewState = receive
{call, Msg, From} -> Module:handle_call(Msg, From, State)
{cast, Msg} -> Module:handle_cast(Msg, State)
Info -> Module:handle_info(Info, State)
end,
loop(Module, NewState).
因此,状态只是一个参数,您可以拖动所有函数调用并在循环内部进行更改。如果你的进程是gen_server,它实际上并不重要,它没有它的生命周期。在以下示例中,术语[1, 2, 3]
也是一个状态:
a() ->
b([1, 2, 3], now()).
b(State, Timestamp) ->
Result = do_something(Timestamp)
c(State, Result).
c(State, Payload) ->
exit({State, Payload}).
现在,回到mochiweb。
如果你需要创建自己的状态,你可以添加一个额外的函数参数:
handle_request(Req) ->
User = Req:get(path),
UserData = load_user_data(User),
handle_request(Req, UserData).
handle_request(Req, UserData) ->
...
现在UserData也是一个州。您可以循环此过程,或让它立即响应并结束 - 但只要您将其作为参数传递,就不会丢失UserData。
最后,如果你真的想让这个过程成为gen_server(在大多数情况下这是非常不合理的),你可以使用gen_server:enter_loop / 3函数来使你当前的进程成为gen_server。此函数的第三个参数将是您的状态,它将存储在已启动的gen_server中。