在Phoenix app:Genserver中提取微服务

时间:2016-03-01 15:02:59

标签: elixir phoenix-framework

我正在阅读this文章,了解如何从现有的凤凰应用程序中提取微服务。作者重构了一个凤凰app控制器,并将其中一个方法移动到Genserver,之后他将Genserver移动到一个单独的应用程序中,并在主项目中添加了一个依赖项。

但是我在这里有点困惑,因为GenServer只允许你有两个服务器回调(即句柄调用和句柄转换)。但是,如果我想要一个功能作为微服务移出,我们最终会创建与该服务中涉及的端点一样多的Genserver,因为单个genserver将允许一个/两个方法调用。 genserver是提取服务的理想方法吗?

2 个答案:

答案 0 :(得分:7)

GenServer有3个主要回调:handle_casthandle_callhandle_info。这些函数中的每一个都可以有多个子句,每个子句都实现一个特定的功能。

例如,我们假设我有一个UserService模块实现为GenServer,有5个操作:createshowindex,{{ 1}}和update。让我们进一步假设我实现delete作为异步操作(所以使用delete),其余作为同步操作(使用handle_cast)。

handle_call

客户端模块可以调用def handle_call({:create, user_data}, _from, state) do new_user = User.create(user_data) // (However you create a user) {:reply, new_user, state} end def handle_call(:index, _from, state) do users = User.all {:reply, users, state} end def handle_call({:update, user_changes}, _from, state) do updated_user = User.update(user_changes) {:reply, updated_user, state} end def handle_call({:show, user_id}, _from, state) do user = User.get(user_id) {:reply, user, state} end def handle_cast({:delete, user_id}, state) do User.delete(user_id) {:no_reply, state) end 来使用user = GenServer.call(pid, {:show, user_id})子句。主要的内容是即使只有少数功能"定义后,您可以根据需要定义该函数的多个子句,模式匹配将调度到正确的子句。

答案 1 :(得分:4)

我对您的问题感到有些困惑,但我不认为您已经准确了解了GenServers。

2个回调handle_callhandle_cast用于接收通过GenServer.callGenServer.cast功能发送的消息。还有handle_info可以接收发送到GenServer进程的任何非OTP消息。

呼叫用于阻止响应的同步消息。我猜这就是你想要的微服务。 (Cast用于异步消息。)

单个GenServer实施可以接收通过call发送的任意数量的消息。

handle_call callback需要3个参数。第一个是它正在处理的消息。通常,该消息是带标记的元组,这意味着它的第一个项目标识了它是哪种类型的消息。您可以处理多个不同的消息并使用模式匹配在GenServer中执行正确的函数子句,如下所示:

def handle_call({:message_one, foo}, _from, state)
    # create some_response from foo or modify state here
    {:reply, some_respone, state}
end
def handle_call({:message_two, bar}, _from, state)
    # create some_response from bar or modify state here 
    {:reply, some_response, state}
end
def handle_call({:message_three, buzz}, _from, state)
    # create some_response from buzz or modify state here
    {:reply, some_response, state}
end

您的GenServer可以根据需要拥有尽可能多的这些功能条款。您通常还会将这些消息标记原子保留为实现细节,并创建将您的调用包装到GenServer.call的公共API函数。