为什么德国政党为什么要将他们的会议推迟一小时。
菲尼克斯LiveView是毫无疑问,近年来最伟大的Web发展局。在这篇文章中,我将探索如何使用LiveView创建世界的FirstProduction部署之一 - 以及如何造成很多难题试图改善它的麻烦。
如果您已经熟悉LiveView,请随时跳到跟进段落。对于其他人来说,这是关于WhatliveView的快速解释是:
LiveView是Elixir Phoenix Web Framework的一部分,允许您构建交互式应用程序而无需编写您的Ownfront-End JavaScript.it通过保留服务器上的应用程序状态。当修改状态发生变化时,它会通过WebSocket自动向用户推出更新。与此同时,它还可以向服务器发送用户事件(例如asbutton clicks或表单)。所有这些都是自动的,无需担心前端JavaScript。
对于我而言,LiveView在开发Web应用程序时意味着无与伦比的速度。更多的是,我发现在Elixir中写作所有代码真的减少了通常来自JavaScript的javascript的媒体放宽。因此,Ruby和PhP社区突出了他们自己的刺激,刺激射程和Livewire的旋转并不奇怪。
2019年夏天,LiveView仍处于早期阶段。克里斯·麦凯登早些时候宣布了几个月的伊斯坦宣布,第一个版本刚刚在8月份发布。在捷克州布拉格的LiveViewat Elixirconf欧盟看到克里斯的主题演讲,我很高兴能给它拍摄。
该活动最终取得了巨大的成功,这可能是世界上的首先存在的产品之一。
幸运的是,将这项新技术的机会刚刚提出:刚刚曾正式注册成立的伏欧罗巴,跨国和泛欧洲前进的党,他们正在寻找他们的第一个大会。随着其成员遍布欧洲人大陆,从一开始就与Volt的DNA的一部分在线。这就是为什么它很快就法达成了第一个公约将作为混合事件持有。一些成员在保加利亚索非亚聚集在一起 - 但是甚至更大的数字将在家中遵循除边,以数字方式参与。
所以,在黑客的短短两三周之后,伏特的在线装配工具,斯萨克,出生。它允许公约椅与参与者分享消息和投票,以及参与选票。工具的架构相当简单:
索菲亚的活动最终成功了世界上最令人难以置信的世界之一的成功!
作为Covid-19大流行袭击,全球各地的其他政党都遭到了完全重新思考他们的党的惯例.many缔约方以前没有在线大会的经验,并令人留下来即兴即兴即兴即兴兴。但伏特有螺旋状,而本地章节欧洲已经为自己的装配而开始。
一切都很棒 - 除了一个问题之外:党一直在增长,因此这些活动中的参与者数量也在不断增长。
随着参与者数量的越来越多,优化应用程序架构所必需的是。第一迭代的频繁轮询间隔最终突出了T3a.2xlarge AWS EC2实例的所有八个速度核心。这不是一个主要问题,因为erlang虚拟带有自己的机器的机器可确保应用程序在这些条件下仍然顺利运行。但是,它不再是未来的未来。
因此,我决定从持续轮询到PUB /子模型。这也很容易与Elixir和Phoenix有用:Phoenix易于使用的易于使用的PubsubModule。
参与者而不是定期查询事件状态,而是将与Live_Event /:ID和Live_Event /:ID /:参与者_ID Topicson括起来,他们将收到有关整个事件的消息以及他们自己的状态。此外,管理员用户将订阅Live_Event /:ID / Admin主题,它们会收到其他信息,例如对Participants列表的更新。
def mount(_params,%{id},套接字)执行套接字.connected? do phoenix .pubsub .subscribe(mypubsub," live_event /#{id}")结束#... {:确定,套接字}结束def handle_info({:votes_updated,votes},socket)do { :Noreply,Advist(:选票,投票)结束
我当地的测试进展顺利,一切都急剧快速。 CPU使用似乎大大减少了。成功!接下来,我部署了更新的平台,以便在荷兰组织一对小型本地事件的伏特。那也没有搭便道。
所以一切似乎都很好,我有信心使用新版本的更大的活动:一个三天的公约与投票和近3,000个符合条件的成员藏。它将与服务器愉快地嗡嗡作响,沿着卓越的CPU使用水平顺利进行。或者我想。
德国的全国伏特公约被设定为5月28日星期五开始,16:00在Cest.i急切地观看管理员面板,因为数百名参与者正在登录平台。
但是在短短两分钟之后:502 - Bad Gateway:应用程序已经崩溃了。我检查了日志 - 并且可以找到崩溃的明显原因。所以我重新启动了服务器,这次在HTOP上观看资源使用。它被似乎是一个火车难题:一旦服务器再次上升,RAM用法立即攀爬,攀登......直到不可避免的内记忆崩溃。
幸运的是,我能够回到旧版本,新的邀请链接软,而且只有一个小时的延迟,为期三天的会议最终开始。
它没有花费我太长了,无法弄清楚,从投票中转移到Pub / Subis,这导致了过度的记忆消耗。
每当用户登录到平台时,Genserver将向所有管理用户播放更新的参与者的ACOMPLETE列表:
然后,LiveView控制器进程将收到这些消息,设置@participants分配并呈现更新的视图:
我的理论是这样的:每秒发生数十种更新,每秒都会加入“公约”,消息在LiveView管理控制器的过程中堆积在LiveView管理控制器的进程中的过程中比他们的表现更快。在Online上使用多个管理员用户,这将迅速引导Tocessive Memory消耗,填充我的所有32 GB的实例,最终导致内存崩溃。
为了测试这个理论,我在我的DEV机器上设置了一个事件,打开了一个管理面板,开始了广播参与者列表的5,000个更新。我的笔记本电脑坠毁,理论已经证实!
我第一次解决问题的尝试是在LiveView控制器进程级别尝试处理传入的消息传单。为此,我暂停了每次尝试的@participants,每次都会分配:参与者_updated消息hit.instead我尝试设置在HTML Templateand中未使用的不同分配,从而导致重新渲染的延迟。然后,我希望LiveView Processto偶尔检查是否已修改此其他分配,如果是的话,alsoupdate @particapers。
这似乎工作正常。我播放了5,000个更新和笔记本电脑。但是,当我试图在浏览器中使用管理面板时,我注意到标签已冻结。事实证明:即使在HTML模板中注意到分配,LiveView仍将发送(空)更新到Browser。凭借数以千计的更新同时进入,既不是Firefoxnor Chromium都没有机会。
此外,这种解决方案仍然随着LiveViewController进程的收件箱填充的固有风险。
最终,我解决了另一个解决方案:限制了Genserver级别的广播频率。而不是通过广播参与者列表,而是发生了更改,而是实现了一个最多一次常见的机制。
这可以通过在Genserver ProcessAT中调用的函数来实现给定间隔:
1000 True Def Init(州)do schedule_process_particants()#... {:确定,状态}结束真defp schedule_process_particants()do process .send_after(self(),:process_particants,)结束true def handle_info(:process_participants,state) do schedule_process_participants(){:noreply,process_particants(州)}结束defp process_participants(state =%{true})do phoenix .pubsub .brocectast(mypubsub," live_event /#{state .id} / admin" ,:参与者_Updated)%{State | false}结束defp process_particants(州),状态
由于参与者列表不再包含在每个广播中,因此当发生更新时,TheliveView控制器进程现在提取它:
在LiveView中使用Assign / 3始终通过WebSocket进行更新,即使进行了张平
我会继续使用这个诸如此类的应用程序吗?绝对是!即使这是一个例子,如果你不小心,LiveView是一种惊人的技术,我们将无法在没有它的政治决策过程中包括成员。
如果您有任何疑问或者如果您好奇,菲尼克斯和LiveView如何才能使您的组织能够,请告诉我!