OTP代表开放电信平台 ; 因此发生在历史上,因为该平台是为满足需求和爱立信的资金而创建的 。 但是,从原则上讲,此名称的功能含义与普通手机中的苹果一样多。
这组作者说, OTP的主要区别特征是容错能力。 没有多线程,没有参与者模型,没有丰富的模式匹配功能,甚至没有透明的集群,也没有热代码升级。 容错能力。
表面安装的Erlang虚拟机的结构非常简单:有一堆带有独立内存的“进程”(不是系统进程,Erlang进程),可以交换消息。 仅此而已。 这是乔·阿姆斯特朗(Joe Armstrong)所说的:
在我的博客中,我认为流程应该表现得很像人。 人们拥有私人记忆,并通过消息传递来交换数据。
- 为什么我不喜欢共享内存
OTP中的消息传递非常简单:一个进程可以同步或异步地向另一个(或一组其他进程)发送一条消息。 但是为此,您需要知道向谁发送这些消息。 即,发送者是交换管理器。 但是,如果我们只想发送广播并使所有感兴趣的进程订阅此消息怎么办?
是的,这是常规的PubSub,但是在OTP中是开箱即用的,它没有实现。 好吧,没关系,我们在一小时之内就把所有的砖块都屈服了。 让我们开始吧。
实施方案
基本上, Elixir包括一个Registry
模块,可以用作pubsub的支架 。 编写一点点本地代码,将所有参与者(每个人的主管)都整洁的看待就可以了。 唯一的问题是Registry
本地的,并且不知道如何群集。 也就是说,在分布式环境(分布式节点)中,这种功能将无法使用。
Phoenix.PubSub
我们来说Phoenix.PubSub
,有一个Phoenix.PubSub
的分布式实现,它带有两个现成的实现: Phoenix.PubSub.PG2
和Phoenix.PubSub.Redis
。 好吧, Redis
显然是我们链中的一个额外链接,但是PG2
是在pg2
进程的Erlang组之上工作的。 而且,但是,如果没有样板也不会。
因此,我们拥有在应用程序中建立便捷的PubSub订阅的所有功能。 是时候打开文本编辑器了吗? “不是真的。” 我不喜欢在项目之间复制代码,并且我可以隔离到库中的所有内容都被隔离以供重用。
环保
因此, Envío
包装诞生了。 如您所知,既然chat不值得一分钱,我们将从使用示例开始。
本地通讯→ Registry
defmodule MyApp.Sub do use Envio.Subscriber, channels: [{MyApp.Pub, :main}] def handle_envio(message, state) do
通常,仅此而已。 仍然需要MyApp.Sub
我们的主管树中,并且此过程将开始接收使用MyApp.Pub
函数发送的所有消息,该消息也不会重载代码。
defmodule MyApp.Pub do use Envio.Publisher, channel: :main def publish(channel, what), do: broadcast(channel, what) def publish(what), do: broadcast(what)
分布式新闻通讯→ PG2
对于由许多节点组成的分布式系统,此方法将不起作用。 我们需要能够订阅来自其他节点的消息,并且Registry
在这里不是助手。 但是有实现相同behaviour
PG2
。
defmodule Pg2Sucker do use Envio.Subscriber, channels: ["main"], manager: :phoenix_pub_sub def handle_envio(message, state) do {:noreply, state} = super(message, state) IO.inspect({message, state}, label: "Received") {:noreply, state} end end
与上面的独立代码的唯一区别是manager: :phoenix_pub_sub
我们传递给use Envio.Subscriber
(并use Envio.Publisher
)以基于:pg2
而不是本地Registry
构建模块的:pg2
。 现在,使用此Publisher
服务器发送的消息将在群集中的所有节点上可用。
申请书
Envío
支持所谓的后端 。 Envio.Slack
随Envio.Slack
一起Envio.Slack
,它使您可以简化向Slack
发送消息的过程。 该应用程序所需的全部操作-向config/prod.exs
配置的通道发送消息config/prod.exs
将完成Envío
。 这是一个示例配置:
config :envio, :backends, %{ Envio.Slack => %{ {MyApp.Pub, :slack} => [ hook_url: {:system, "SLACK_ENVIO_HOOK_URL"} ] } }
现在,通过调用MyApp.Pub.publish(:slack, %{foo: :bar})
发送的所有消息都将以精美的Slack格式传递到相应的通道。 为了停止向Slack发送消息,只需停止Envio.Slack
进程。 在测试中可以找到更多示例(例如IO
的日志)。
我为什么要钉十字架,自己尝试。
def deps do [ {:envio, "~> 0.8"} ] end
良好的沟通!