【问题标题】:Extracting Microservices in Phoenix app : Genserver在 Phoenix 应用程序中提取微服务:Genserver
【发布时间】:2016-03-31 05:45:08
【问题描述】:

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

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

【问题讨论】:

    标签: elixir phoenix-framework


    【解决方案1】:

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

    例如,假设我有一个作为 GenServer 实现的 UserService 模块,具有 5 个操作:createshowindexupdatedelete。让我们进一步假设我将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}) 来使用show 子句。主要收获是,即使只定义了几个“函数”,您也可以根据需要定义该函数的任意多个子句,并且模式匹配将分派到正确的子句。

    【讨论】:

      【解决方案2】:

      您的问题让我有些困惑,但我认为您对 GenServer 的了解并不正确。

      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 可以根据需要包含任意数量的这些函数子句。您通常还会将这些消息标记原子保留为实现细节,并创建公共 API 函数来包装您对 GenServer.call 的调用。

      【讨论】:

        猜你喜欢
        • 2018-07-30
        • 2021-07-26
        • 2019-05-26
        • 2021-12-05
        • 2022-12-07
        • 2017-07-03
        • 1970-01-01
        • 2020-03-02
        • 2019-05-15
        相关资源
        最近更新 更多