返回文章列表

文章

Elixir in Action - 2

Stateful server processes

目录
  1. Stateful server processes
  2. 省略....
  3. 省略....
  4. 📝3、Keeping a process state

Stateful server processes#

## 📝1、Server processes 服务器进程(Server processes)是指运行时间很长(或永远运行)且能处理各种请求(消息)的进程的非正式名称。简单来说Server processes是个形容词性的描述,在elixir中并不是一个特定的概念,它其实就是一个无限循环的进程,当然在elixir(其他函数式编程语言也一样)中,它就是一个无限的递归(endless recursion)。 通常我们最基础的Server processes代码结构可能是如下形式: ```elixir def module DatabaseServer do def start do spawn(&loop/0) end

defp loop do # 定义私有函数 reveive do # handle message ... end loop() # call itself end ... end

`start/0` 是所谓的接口函数,客户端使用它来启动服务器进程。调用 start/0 时,它会生成运行 loop/0 函数的进程。此函数为进程的无限循环提供动力。该函数等待消息,处理消息,然后调用自身,确保进程永不停止。
这样的实现使该进程成为服务器。进程不是主动运行某些计算,而是大部分时间处于空闲状态,等待消息(请求)到达。值得注意的是,此循环不占用大量 CPU。<span discussion-urls="discussion://1ce5c571-bb7d-8063-b502-cbe77988b38a/1ce5c571-bb7d-8018-ba8b-f5645f9fe82a/1ce5c571-bb7d-8017-8b42-001c7b110359">等待消息会使进程处于挂起状态,不会浪费 CPU 周期。</span>
请注意,此模块中的函数在不同的进程中运行。函数start/0由客户端调用,并在客户端进程中运行。私有函数loop/0在服务器进程中运行。同一模块的不同函数在不同的进程中运行非常正常,模块和进程之间没有特殊关系。模块只是一些函数的集合,这些函数可以在任何进程中调用。
在实现服务器进程时,通常将其所有代码放在一个模块中是合理的。此模块的函数通常分为两类:接口和实现。接口函数是公共的,在调用者进程中执行。它们隐藏了进程创建和通信协议的细节。实现函数通常是私有的,在服务器进程中运行。
下面让我们看一下loop/0函数的完整实现
```elixir
defmodule DatabaseServer do
  def start do
    spawn(&loop/0)
  end

  defp loop do
    receive do
      {:run_query, caller, query_def} ->
        query_result = run_query(query_def)
        send(caller, {:query_result, result})
    end
    loop()
  end

  defp run_query(query_def) do
    # Simulate a database query execution
    Process.sleep(1000) # Simulate delay
    "#{query_def} result"
  end

end