Cowboy 用户指南 (二) - Erlang and the Web

Erlang 和 Web

Erlang是编写Web应用程序的理想平台。它的特性完全符合现代Web应用程序的需求。

Web是并发的

当你只访问一个网站时是几乎没有并发性的。打开几个连接,并通过这些连接发送请求。然后web页面就会显示在您的屏幕上。您的浏览器将只打开4或8个连接到服务器,取决于您的设置。

这不是很多。但是想想看。您不是同时访问服务器的唯一用户。在同一时间,可能有成百上千甚至数百万的连接连接到同一台服务器。

即使在今天,生产中使用的许多系统都没有解决C10K问题(1万个并发连接)。而那些成功的人正在努力进入下一个阶段,C100K,而且离它还很远。

同时,Erlang处理数百万个连接是没有问题的。在编写本文时,有一些用Erlang编写的应用服务器,在实际生产应用程序中,在一台服务器上可以处理超过200万个连接,而且还有空闲的内存和CPU!

Web是并发的,而Erlang是一种专为并发而设计的语言,因此它与之完美匹配。

当然,各种平台的规模需要超过几百万个连接。这就是Erlang内置分发机制的作用所在。如果一个服务器不够,可以添加更多的服务器!Erlang允许您使用相同的代码与本地进程或集群其他部分的进程通信,这意味着您可以在需要时快速扩展。

Web拥有庞大的用户基础,而Erlang平台被设计成可以在分布式环境下工作,因此它是一个完美的匹配。

或者是吗?当然,你可以用你最喜欢的语言找到解决方案来处理这么多并发连接……但所有这些解决方案都将在未来几年解体。为什么?首先,因为服务器并没有变得更强大,而是获得了更多的内核和内存。只有当您的应用程序能够正确地使用它们时,这才有用,而Erlang与这一领域中的任何东西都相差甚远。其次,今天你的电脑和手机都在线,明天你的手表、护目镜、自行车、汽车、冰箱和其他大量的设备也将连接到互联网上的各种应用程序。

只有Erlang准备好应对即将到来的问题。

Web是软实时的

硬实时系统有一个刚性的、不可改变的时间限制,它不允许任何超出时限的错误。超时错误会带来损害甚至导致系统失败、或者导致系统不能实现它的预期目标。软实时系统的时限是一个柔性灵活的,它可以容忍偶然的超时错误。失败造成的后果并不严重,仅仅是轻微的降低了系统的吞吐量。

Web是软实时的,因为花更长的时间执行一个操作会被视为服务质量差。

Erlang是一个软实时系统。它总是公平地运行进程,一次运行一点,一段时间后切换到另一个进程,防止单个进程从所有其他进程窃取资源。这意味着Erlang可以保证稳定的低延迟操作。

Erlang提供了软实时Web所需要的保证。

Web是异步的

很久以前,Web是同步的,因为HTTP是同步的。您启动了一个请求,然后等待响应。不了。这一切都始于开始使用XmlHttpRequest。它允许客户机对服务器执行异步调用。

然后Websocket出现了,它允许服务器和客户端完全异步地向另一个端点发送数据。数据包含在帧中,不需要响应。

Erlang进程的工作原理相同。它们相互发送消息中包含的数据,然后在不需要响应的情况下继续运行。它们的大部分时间都处于不活跃状态,等待新消息,当收到消息时,Erlang VM将愉快地激活它们。

因此,很容易想象Erlang擅长接收Websocket帧,这些帧可能会在不可预测的时间进入,将数据传递给始终准备好等待新消息的负责进程,并通过激活系统所需的部分来执行所需的操作。

最近的Web技术,比如Websocket,还有HTTP/2.0,都是完全异步的协议。请求和响应的概念当然是保留的,但是客户机或浏览器可以在两者之间发送任何东西,响应也可以以完全不同的顺序接收。

Erlang本质上是异步的,而且由于多年来在VM中完成的伟大工程,Erlang在这方面非常出色。它很自然地擅长处理异步Web。

Web无处不在

网络已经成为我们生活中非常重要的一部分。我们每时每刻都是联系在一起的,用手机、用电脑、在卫生间用平板电脑打发时间……这不会慢下来,家里或我们身上的每一个设备都会连接上。

所有这些设备总是连接在一起的。而且,有这么多的选择可以让你访问你所寻找的内容,当问题出现时,用户往往不会逗留在那里。今天的用户希望他们的应用程序总是可用的,如果有太多的问题,他们就继续前进。

尽管如此,当开发人员选择一个用于构建web应用程序的产品时,他们唯一关心的似乎是“它快吗?”,他们四处寻找合成基准,以显示在只有少量并发连接的情况下,哪一个发送“Hello world”最快。在很长一段时间内,Web基准测试并不能代表现实,而且随着时间的推移,它正在变得越来越遥不可及。

开发者真正应该问自己的是“我能在不受干扰的情况下为所有用户提供服务吗?”他们可以抱最好的希望,也可以使用Erlang。

Erlang是为容错而构建的。当用任何其他语言编写代码时,您必须检查所有的返回值并相应地采取行动,以避免任何不可预见的问题。如果你幸运的话,你不会错过任何重要的事情。在编写Erlang代码时,您可以只检查成功条件并忽略所有错误。如果发生错误,Erlang进程就会崩溃,然后由一个名为supervisor的特殊进程重新启动。

因此,Erlang开发人员不必担心未处理的错误,而可以专注于处理应该给用户一些反馈的错误,让系统来处理其余的事情。这也有一个好处,即允许他们编写更少的代码,并让他们可以在晚上睡觉。

Erlang面向容错的设计是使它成为无处不在、始终可用的Web的最佳选择的第一步。

第二部分是Erlang的内置发行版。分布式是构建容错系统的关键部分,因为它允许您处理更大的故障,如整个服务器故障,甚至整个数据中心故障。

容错和分布式在今天很重要,在未来的Web中也将是至关重要的。Erlang已经准备好了。

学习 Erlang

如果您是Erlang的新手,您可能需要阅读一两本书来开始学习。这就是我作为《Cowboy》作者的建议。

《The Erlanger Playbook》是我目前正在编写的一本电子书,它涵盖了从代码到文档到测试Erlang应用程序的许多不同主题。它还有一个Erlang部分,直接介绍了构建模块和模式,而不是语法等细节。

你很可能作为一个完全的初学者阅读它,但你需要一本伴侣书来充分利用它。从Nine Nines website够买。

《Programming Erlang》

这本书出自Erlang的创始人之一Joe Armstrong之手。它很好地解释了Erlang是什么以及为什么会这样。它是对该语言和平台的很好的介绍。

这本书是关于Erlang编程的,还有一章是关于Cowboy的。

《Learn You Some Erlang for Great Good》

LYSE是一本更完整的书,涵盖了Erlang的许多方面,同时也提供了故事和幽默。请注意:它相当冗长。它有一个免费的在线版本,一个更精致的纸质版和电子书版本。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单的使用erlangcowboy框架编写的websocket聊天室代码示例。 ```erlang %% 定义路由和处理函数 -module(chat_router). -behaviour(cowboy_router). -export([init/3]). -export([routes/2]). init(_Transport, _Req, _Opts) -> {ok, [], undefined}. routes(_Req, _State) -> {[ {'_', [ {"/websocket", cowboy_websocket_handler, [ {callback, chat_handler}, {origin, "*"} ]} ]} ], _Req, _State}. %% 定义websocket处理函数 -module(chat_handler). -behaviour(cowboy_websocket_handler). -export([init/3]). -export([websocket_init/3]). -export([websocket_handle/3]). -export([websocket_info/3]). -export([websocket_terminate/3]). init(_TransportName, Req, _Opts) -> {ok, Req, undefined}. websocket_init(_TransportName, Req, _Opts) -> {cowboy_websocket, Req, undefined}. websocket_handle({text, Message}, Req, _State) -> %% 处理收到的文本消息 cowboy_websocket:broadcast(Message, Req), {ok, Req, undefined}; websocket_handle(_Data, Req, _State) -> {ok, Req, undefined}. websocket_info({join, _Pid, _Ref}, Req, _State) -> %% 处理新用户加入聊天室 cowboy_websocket:broadcast("New user joined", Req), {ok, Req, undefined}; websocket_info({leave, _Pid, _Ref}, Req, _State) -> %% 处理用户离开聊天室 cowboy_websocket:broadcast("User left", Req), {ok, Req, undefined}; websocket_info(_Info, Req, _State) -> {ok, Req, undefined}. websocket_terminate(_Reason, Req, _State) -> {ok, Req, undefined}. ``` 以上代码定义了一个路由模块`chat_router`,其中`routes/2`函数指定了处理`/websocket`路径的`cowboy_websocket_handler`处理函数,并将其回调函数指定为`chat_handler`。`chat_handler`模块中的`websocket_handle/3`函数用于处理接收到的文本消息,并使用`cowboy_websocket:broadcast/2`函数将消息广播给所有连接的客户端。`websocket_info/3`函数用于处理新用户加入和离开聊天室的事件,同样使用`cowboy_websocket:broadcast/2`函数将事件广播给所有连接的客户端。 您可以将以上代码保存为`chat.erl`文件,并使用cowboy框架启动websocket服务器,例如: ```erlang %% 启动websocket服务器 -module(chat). -behaviour(application). -export([start/2, stop/1]). start(_Type, _Args) -> Dispatch = cowboy_router:compile([ {'_', [{"/websocket", chat_handler, []}]} ]), {ok, _} = cowboy:start_clear(http, [{port, 8080}], #{env => #{dispatch => Dispatch}}), chat_sup:start_link(). stop(_State) -> ok. ``` 以上代码定义了一个应用模块`chat`,其中`start/2`函数启动了一个cowboy服务器,监听8080端口,并将路由配置为处理`/websocket`路径,使用`chat_handler`处理函数。您可以将以上代码保存为`chat_app.erl`文件,并使用`rebar3`编译和启动应用程序: ```sh $ rebar3 compile $ rebar3 shell ``` 在erlang shell中,您可以使用以下命令连接到websocket服务器并发送消息: ```erlang %% 连接到websocket服务器 1> {ok, Conn} = websocket:connect("ws://localhost:8080/websocket"). {ok,{websocket,#Port<0.7>,<0.198.0>}} %% 发送消息 2> websocket:send_text(Conn, "Hello, World!"). ok ``` 在另一个erlang shell中,您可以使用以下命令连接到相同的websocket服务器并接收消息: ```erlang %% 连接到websocket服务器 1> {ok, Conn} = websocket:connect("ws://localhost:8080/websocket"). {ok,{websocket,#Port<0.7>,<0.203.0>}} %% 接收消息 2> websocket:recv_text(Conn). "New user joined" 3> websocket:recv_text(Conn). "Hello, World!" ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值