了解Erlang中通用服务器实现中消息的工作流程

凯龙

以下代码来自“ Programming Erlang,第二版”。这是一个如何在Erlang中实现通用服务器的示例。

-module(server1).
-export([start/2, rpc/2]).

start(Name, Mod) -> 
  register(Name, spawn(fun() -> loop(Name, Mod, Mod:init()) end)).

rpc(Name, Request) ->
  Name ! {self(), Request},
    receive
      {Name, Response} -> Response
    end.

loop(Name, Mod, State) ->
  receive
    {From, Request} ->
      {Response, State1} = Mod:handle(Request, State),
        From ! {Name, Response},
        loop(Name, Mod, State1)
  end.

-module(name_server).
-export([init/0, add/2, find/1, handle/2]).
-import(server1, [rpc/2]).

%% client routines
add(Name, Place) -> rpc(name_server, {add, Name, Place}).
find(Name)       -> rpc(name_server, {find, Name}).

%% callback routines
init() -> dict:new().
handle({add, Name, Place}, Dict) -> {ok, dict:store(Name, Place, Dict)};
handle({find, Name}, Dict)       -> {dict:find(Name, Dict), Dict}.


server1:start(name_server, name_server).
name_server:add(joe, "at home").
name_server:find(joe).

我非常努力地理解消息的工作流程。您是否可以在执行以下功能期间帮助我了解此服务器实现的工作流程:server1:start,name_server:add和name_server:find?

帕斯卡

本示例介绍了Erlang中使用的行为概念。它说明了如何分两部分构建服务器:

第一部分是模块server1,其中仅包含可被任何服务器使用的通用功能。它的作用是维护一些可用的信息(状态变量),并准备好响应某些请求。这是gen_server行为的功能,具有更多功能。

第二部分是模块name_server。这描述了特定服务器的作用。它为服务器的用户和内部功能(回调)实现了接口,这些接口描述了针对每个特定用户请求的操作。

让我们遵循3个shell命令(请参见最后的图):

server1:start(名称服务器,名称服务器)。用户调用通用服务器的启动例程,给出2条信息(带有保存值),他要启动的服务器的名称以及包含回调的模块的名称。有了这个通用的启动例程

1 /调用name_server的init例程以获取服务器状态Mod:init(),您可以看到通用部分不知道它将保留哪种信息;状态由name_server:init / 0例程(第一个回调函数)创建。这是一本空字典dict:new()

2 /产生一个调用通用服务器循环的新进程,其中包含3个信息(服务器名称,回调模块和初始服务器状态)spawn(fun() -> loop(Name, Mod, Mod:init())对于表单的消息{本身刚刚开始循环和等待在}接收块。

3 /用名称name_server注册新进程register(Name, spawn(fun() -> loop(Name, Mod, Mod:init()) end))

4 /返回外壳。

此时,与外壳程序并行的是一个名为name_server的新运行进程,它正在运行并等待请求。请注意,通常此步骤不是由用户执行,而是由应用程序执行。这就是为什么在回调模块中没有接口可以执行此操作的原因,并且在通用服务器中直接调用了start函数。

name_server:add(joe,“在家”)。用户在服务器中添加信息,调用name_server的add函数。此接口在此处隐藏了调用服务器的机制,它在客户端进程中运行。

1 / add函数使用两个参数调用服务器的rpc例程rpc(name_server, {add, Name, Place}):回调模块和请求本身{add, Name, Place}rpc例程仍在客户端进程中执行,

2 /它为服务器构建一条消息,其中包含2条信息:客户端进程的pid(在此为外壳)和请求本身,然后将其发送到指定的服务器: Name ! {self(), Request},

3 /客户端等待响应。记住,我们让服务器在循环例程中等待消息。

4 /发送的消息与{From, Request}服务器的预期格式匹配,因此服务器进入消息处理。首先,它使用两个参数回调name_server模块:request和current state Mod:handle(Request, State)目的是拥有通用服务器代码,因此它不知道如何处理请求。在name_server:handle / 2函数中,完成了正确的操作。通过模式匹配,该子句handle({add, Name, Place}, Dict) -> {ok, dict:store(Name, Place, Dict)};被调用,并且创建了一个新的字典,用于存储键/值对的Name / Place(此处为joe /“在家”)。新的字典将以元组{ok,NewDict}中的响应返回。

5 /现在,通用服务器可以构建答案并将其返回给客户端From ! {Name, Response},,并以新状态重新进入循环,loop(Name, Mod, State1)并等待下一个请求。

6 /等待接收块的客户端收到消息{Name,Response},然后可以提取Response并将其返回给Shell,在这里就可以了。

name_server:find(joe)。用户希望从服务器获取信息。该过程与以前完全相同,这是通用服务器的兴趣所在。无论请求是什么,它都执行相同的工作。当您研究gen_server的行为时,您会看到有几种对服务器的访问,例如调用,强制转换,信息...因此,如果我们看一下此请求的流程:

1 /使用回调模块和请求调用rpc rpc(name_server, {find, Name}).

2 /使用客户端pid和请求向服务器发送消息

3 /等待答案

4 /服务器接收到该消息,并使用请求回调name_server,Mod:handle(Request, State),它从句柄获取响应,该句柄handle({find, Name}, Dict) -> {dict:find(Name, Dict), Dict}.返回字典搜索的结果和字典本身。

5 /服务器构建答案并将其发送给客户端,From ! {Name, Response},并以相同状态重新进入循环,等待下一个请求。

6 /等待接收块的客户端收到消息{Name,Response},然后可以提取Response并将其返回给Shell,现在它是joe所在的位置:“在家”。

下图显示了不同的消息交换:

前面描述的3个步骤的顺序图

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

RADIUS服务器工作流程

来自分类Dev

可能的拉取请求工作流程,将分支合并到主服务器中

来自分类Dev

Git生产和开发服务器工作流程

来自分类Dev

Erlang中的并发及其适当的工作流程

来自分类Dev

了解Powershell工作流程中的功能范围

来自分类Dev

使用Intellij中的Maven了解正确的工作流程

来自分类Dev

在GitHub动作工作流程中通过yml安装两个Neo4j服务器(在不同的端口上运行)

来自分类Dev

在工作流程中调用工作流程

来自分类Dev

使用Vagrant和Git将应用程序从开发部署到生产服务器的通用或高效工作流程是什么?

来自分类Dev

SoA /微服务架构的通用工作流程?

来自分类Dev

SoA /微服务架构的通用工作流程?

来自分类Dev

本地/分段/生产服务器堆栈+ Git的最佳工作流程

来自分类Dev

如何使用PhpStorm设置多用户单开发服务器工作流程

来自分类Dev

从YouTrack服务器手动删除工作流程

来自分类Dev

如何使用PhpStorm设置多用户单开发服务器工作流程

来自分类Dev

从YouTrack服务器手动删除工作流程

来自分类Dev

服务器如何发送消息 SSE 在多个服务器实例环境中工作

来自分类Dev

MVC:工作流在已部署的服务器中不起作用

来自分类Dev

WebStorm中的ReactJS工作流程

来自分类Dev

在TargetProcess中实施关系工作流程

来自分类Dev

AppleScript在Automator中循环工作流程

来自分类Dev

在JavaFX中构建某种工作流程

来自分类Dev

.netcore中的用户秘密工作流程?

来自分类Dev

SE在Emacs中的OAuth工作流程

来自分类Dev

Camel vs BPM中的工作流程

来自分类Dev

使用“轨道中的工作流程宝石”

来自分类Dev

在工作流程中托管StateMachine元素

来自分类Dev

在Powershell工作流程中解析XML

来自分类Dev

在Powershell工作流程中声明数组

Related 相关文章

  1. 1

    RADIUS服务器工作流程

  2. 2

    可能的拉取请求工作流程,将分支合并到主服务器中

  3. 3

    Git生产和开发服务器工作流程

  4. 4

    Erlang中的并发及其适当的工作流程

  5. 5

    了解Powershell工作流程中的功能范围

  6. 6

    使用Intellij中的Maven了解正确的工作流程

  7. 7

    在GitHub动作工作流程中通过yml安装两个Neo4j服务器(在不同的端口上运行)

  8. 8

    在工作流程中调用工作流程

  9. 9

    使用Vagrant和Git将应用程序从开发部署到生产服务器的通用或高效工作流程是什么?

  10. 10

    SoA /微服务架构的通用工作流程?

  11. 11

    SoA /微服务架构的通用工作流程?

  12. 12

    本地/分段/生产服务器堆栈+ Git的最佳工作流程

  13. 13

    如何使用PhpStorm设置多用户单开发服务器工作流程

  14. 14

    从YouTrack服务器手动删除工作流程

  15. 15

    如何使用PhpStorm设置多用户单开发服务器工作流程

  16. 16

    从YouTrack服务器手动删除工作流程

  17. 17

    服务器如何发送消息 SSE 在多个服务器实例环境中工作

  18. 18

    MVC:工作流在已部署的服务器中不起作用

  19. 19

    WebStorm中的ReactJS工作流程

  20. 20

    在TargetProcess中实施关系工作流程

  21. 21

    AppleScript在Automator中循环工作流程

  22. 22

    在JavaFX中构建某种工作流程

  23. 23

    .netcore中的用户秘密工作流程?

  24. 24

    SE在Emacs中的OAuth工作流程

  25. 25

    Camel vs BPM中的工作流程

  26. 26

    使用“轨道中的工作流程宝石”

  27. 27

    在工作流程中托管StateMachine元素

  28. 28

    在Powershell工作流程中解析XML

  29. 29

    在Powershell工作流程中声明数组

热门标签

归档