go gorilla

Singhania AdityaSinghania Aditya

Follow跟随

Aug 31 8月31

gopher leaving everyone awestruck with it’s magic of go-routines and go-channels
gopher让所有人感到震撼的go-routines和go-channels

构建浏览器推送通知服务-使用Golang中的gorilla / websocket库进行低级设计 (Building a Browser Push Notification Service - The Low Level Design using the gorilla/websocket library in Golang)

This is a follow up article in the series ‘Building a Browser Push Notification Service’, you can find the previous article that talks about the basics of websocket connection and push notifications here.

这是“构建浏览器推送通知服务”系列中的后续文章,您可以在 此处 找到有关Websocket连接和推送通知的基础的上一篇文章

Case in Point : So this is what we’re going to do, we have a notification message ‘Hello, Alexander Hamilton!’ that we have to send to our target client named Alexander(’s browser client). For completeness sake, let’s assume this person has a laptop, a tablet and a desktop. He has our website ‘thefoundingfathers.com’ opened on a browser tab in all of these three devices. Going to this website would also create a websocket connection with our server. So, as soon as our websocket service receives any notification for our target ‘Alexander’, we are to send the notification forward to all these three browser tabs (three connections).

案例: 这就是我们要做的,我们收到一条 通知 消息:“ 您好,亚历山大·汉密尔顿! 我们必须将其发送到 名为 Alexander (浏览器客户端)的 目标客户 端。 为了完整起见,我们假设此人有一台笔记本电脑,一台平板电脑和一台台式机。 在所有这三种设备的浏览器选项卡上打开了 我们的网站“ thefoundingfathers.com ”。 转到该网站还将与我们的服务器建立一个websocket连接。 因此,一旦我们的websocket服务收到有关目标“ 亚历山大 ”的 任何通知 ,我们便会将 通知 转发给所有这 三个浏览器选项卡(三个连接)

In this article, we’ll try to see what the low level design of the websocket server could look like, with the gorilla/websocket library (lets not fry our brains with the scenarios of having multiple websocket servers, yet, and first solve how it would work with a single websocket server). We’ll rely immensely on two essential resources provided by the go language — the go-routines and the go-channels.

在本文中,我们将尝试通过gorilla / websocket库来了解websocket服务器的低级设计是什么样的(但不要让我们为拥有多个websocket服务器的场景而烦恼,首先要解决如何它可以与单个websocket服务器一起使用)。 我们将极大地依赖于go语言提供的两个基本资源-go 例程go-channels

What are go-routines and go-channels, you ask? Well, the golang language is known to have greatly eased the work of having a multithreaded architecture, both for the developer and also from the resource utilization angle (memory and CPU usage). It has provided two things to help this cause, the go-routines, which are the methods that can run concurrently with other methods, basically given a fancy name and a makeover. These can be thought of very light weight threads (~2kb). And the go-channels, which are the communication wires between these go-routines. So essentially, if you want to run something concurrently? Simply create a new go-routine (which is super cheap and easy). Now, you want to communicate between these go-routines? Avoid sharing the memory or the variables between these routines, you’ll probably end up frustrated, trying to resolve issues that come with concurrency (race conditions etc.). Instead, pass this variable over something like the communication wire, to the intended go-routines, and this communication wire is go-channels (in-built in go), which passes all the tests of concurrency. This is inline with the language’s philosophy that says “Don’t communicate by sharing the memory, share the memory by communicating”. The channels are like having a queue to communicate between two services, just that this one’s going to reside in your memory, and will help you to communicate between your threads.

您问什么是例行程序和通道? 嗯,众所周知,golang语言极大地简化了开发人员和资源利用率(内存和CPU使用率)方面具有多线程体系结构的工作。 它提供了两点帮助解决该问题的方法: go-routines ,它们是可以与其他方法并发运行的方法,基本上给定了一个奇特的名称和一个改头换面。 可以认为这些线程的线程很轻(〜2kb)。 以及go通道,它们是这些go例程之间的通信线。 因此,从本质上讲,是否要同时运行某些内容? 只需创建一个新的go例程 (超级便宜又容易)。 现在,您想在这些例程之间进行通信吗? 避免在这些例程之间共享内存或变量,您可能最终会受挫,试图解决并发(竞争条件等)带来的问题。 相反,将该变量通过诸如通信线路之类的东西传递到所需的go例程,并且此通信线路为go通道 (内置在go中),它通过了所有并发性测试。 这与该语言的哲学相一致,即“不要通过共享内存进行通信,而应通过通信来共享内存”。 这些通道就像在两个服务之间进行通信的队列一样,只是该队列将驻留在您的内存中,并且将帮助您在线程之间进行通信。

Okay, got the terms, now how does the low level design look like? Well it would look something like this.

好了,有了术语,现在低层设计是什么样的? 好吧,看起来像这样。

The go-routines and the channels — Here in this architecture, the different boxes denote the different types of worker pools that will run in our server. The worker pools are basically like the different departments in a company. Like how the department employs an employee to get the job done, each worker pool may employ 1 or more workers (go-routines) to get the job done. These company departments need to constantly communicate with each other to achieve the larger company objective. Likewise, the arrows between these workers denote the communication wires layed out for the workers to talk to each other (or the go-channels), which collectively achieve the objective of delivering the notification to our targets. The pool of workers will try to make some request to some other pool to take care of the next part of the processing, and these requests will be sent over the channels. Let us have a look at the different types of worker pools and their jobs.

例程和通道 -在此体系结构中,不同的框表示将在我们的服务器中运行的工作池的不同类型。 工人池基本上就像公司中的不同部门。 就像部门如何雇用员工来完成工作一样,每个工人池可以雇用1个或多个工人(例行程序)来完成工作。 这些公司部门需要不断相互沟通以实现更大的公司目标。 同样,这些工作人员之间的箭头表示铺设的通讯线,供工作人员彼此交谈(或通向通道),共同实现了将通知传递给我们的目标的目的。 工作池将尝试向其他池发出一些请求,以处理下一部分处理,这些请求将通过通道发送。 让我们看一下不同类型的工人池及其工作。

  1. Source (connection upgrade request) worker pool (HTTP server)— This worker pool processes the incoming connection upgrade requests. It will look at the targetID, the request fields and the headers, and decide if the request is worthy of a websocket upgrade (based on the origin of the request, the authentication credentials, etc.). It will accordingly approve or reject the request.

    源(连接升级请求)工作池 (HTTP服务器) —该工作池处理传入的连接升级请求。 它将查看targetID,请求字段和标头,并确定请求是否值得进行websocket升级(基于请求的来源,身份验证凭据等)。 它将相应地批准或拒绝该请求。

    Rejecting the request would simply mean passing back a non OK status as an HTTP response.

    拒绝该请求仅意味着将不正常的状态作为HTTP响应传回。

    While approving the request would mean three things

    批准请求意味着三件事

    a.

    一个。

    Sending an HTTP OK status in the response.

    在响应中发送HTTP OK状态

    b.

    b。

    Forwarding the connection object to the ‘Hub pool’ of workers, this is what we will call a registration request to the hub. More on this in Hub pool section.

    将连接对象转发到worker的“集线器池” ,这就是我们称为集线器的注册请求 。 有关更多信息,请参见“集线器池”部分。

    c.

    C。

    Starting two go-routines (a read pump go-routine and a write-pump go-routine), for handling the reads and writes for this connection. More on this in the read pump / write pump worker pool section.

    启动两个执行例程 (读泵执行例程和写泵执行例程),用于处理此连接的读写操作。 有关更多信息,请参见读泵/写泵工作人员池部分。

    Starting two go-routines (a read pump go-routine and a write-pump go-routine), for handling the reads and writes for this connection. More on this in the read pump / write pump worker pool section.The ‘source (connection upgrade request) worker pool’ can have any number of go-routines running based on the incoming connection-upgrade-requests traffic.For our case in point, the person Alexander sent a connection upgrade request tagged with the target ‘Alexander’ as soon as he opened our website on any of the deivces. This worker then forwarded these connection registration requests to the hub pool. It would also start a read pump and a write pump, against each one of these connection requests.

    启动两个执行例程 (读泵执行例程和写泵执行例程),用于处理此连接的读写操作。 有关更多信息,请参见读泵/写泵工作人员池部分。 “源(连接升级请求)工作程序池”可以根据传入的连接升级请求流量运行任意数量的go例程。就我们而言,亚历山大一人发送了一个标有目标“亚历山大(Alexander)一旦在任何设备上打开我们的网站。 然后,该工作人员将这些连接注册请求转发到集线器池。 还将针对这些连接请求中的每一个启动读取泵和写入泵。

  2. Source (notification request) worker pool (HTTP / GRPC or Queue worker) — This worker pool sources the notification requests. These requests will be tagged with the targetID (the intended receiver). This pool will simply forward all the valid notification requests to the ‘Hub pool’ for further processing.

    源(通知请求)工作程序池(HTTP / GRPC或队列工作程序) —该工作程序池发出通知请求。 这些请求将使用targetID(目标接收者)进行标记。 该池将简单地将所有有效的通知请求转发到“集线器池”以进行进一步处理。

    Source (notification request) worker pool (HTTP / GRPC or Queue worker) — This worker pool sources the notification requests. These requests will be tagged with the targetID (the intended receiver). This pool will simply forward all the valid notification requests to the ‘Hub pool’ for further processing.The ‘source (notification request) pool’ can have any number of go-routines based on the incoming notifications-traffic.For our case in point, this worker received a notification ‘Hello, Alexander Hamilton!’ tagged against the target ‘Alexander’. This worker then forwaded the notification request to the hub pool.

    源(通知请求)工作程序池(HTTP / GRPC或队列工作程序) —该工作程序池发出通知请求。 这些请求将使用targetID(目标接收者)进行标记。 该池将简单地将所有有效的通知请求转发到“集线器池”以进行进一步处理。 根据传入的通知流量,“源(通知请求)池”可以具有任意数量的go例程。就我们而言,该工作人员收到了一个通知“你好,亚历山大·汉密尔顿!”。 被标记为目标“亚历山大”。 然后,该工作人员将通知请求转发给集线器池。

  3. The Hub pool — This worker pool, as you might have seen is the most critical component in the architecture. This stores all the current active connections (active connections meaning, a connection that had been upgraded to a websocket and has not been closed yet) in a map[targetID]connections. All the notifications are to be sent over this connection object. The hub takes care of three things.

    集线器池 -您可能已经看到,该工作池是体系结构中最关键的组件。 它将所有当前的活动连接(活动连接,即已升级到websocket且尚未关闭的连接 )存储在map [targetID] connections中 。 所有通知都将通过此连接对象发送。 集线器负责三件事。

    a. For a connection

    一个。 对于连接

    registration request, store the new connection in the map against the given targetID.

    注册请求,并根据给定的targetID将新连接存储在地图中。

    b. For a connection

    b。 对于连接

    deregistration request, remove the connection from the map. (Who sends this, you ask? Well, it may originate mostly from the read pump or the write pump. More on this in the relevant sections.) Additionally, this will also send a close-go-routine-request to the read and the write pump go-routines that run for this connection.

    取消注册请求,从地图上删除连接。 ( 您问这是谁发送的 ?好吧,它可能主要来自读取泵或写入泵。有关部分中的更多内容。)此外,这还将向读取和发送一个常规例程请求为此连接运行的写泵例程。

    c. For a

    C。 为一个

    notification request, it will search the map and get the active connections stored against that targetID, and forward the request to all the write pumps running for those connections. If it does not have any active connection against the targetID, it can simply discard the notification.

    通知请求,它将搜索该映射并获取针对该targetID存储的活动连接,并将该请求转发给为这些连接运行的所有写泵。 如果它没有针对targetID的任何活动连接,则可以简单地丢弃该通知。

    So, overall, if you see, this pool takes care of any and all read / write operations on the map.

    因此,总的来说,如果您看到的话,该池将负责地图上的所有读/写操作。

    Unfortunately, the Hub pool will only have a single worker go-routine., since the map in golang does not support concurrent operations inherently.For the case in point, the connection registration requests would end up populating the connections in the map, as [Alexander]three-connections. Additionally, when the notification request comes to this hub, it would figure that there are three connections against the target ‘Alexander’ and would would forward the request to all of these three connections’ write pumps.

    不幸的是,集线器池只有一个工作程序,因为golang中的地图本身并不支持并发操作。对于这种情况,连接注册请求最终将填充到地图中的连接中,例如[亚历山大]三联。 另外,当通知请求到达此集线器时,它将确定目标“ Alexander”有三个连接,并将请求转发到这三个连接的所有写泵。

  4. The Read pump — This go-routine will be created one per connection immediately after the connection upgrade request is approved. This routine will continuouly keep polling over the connection object, to check if there’s data sent over the connection by the target client (if you remember the earlier article, we’d seen that websockets enables a duplex communication). It will then forward the received notification to the appropriate processor. Additionally, as soon as this pump gets some error while reading over the connection, this will send a deregistration request for this connection to the hub routine.

    读取泵—在连接升级请求获得批准后,将立即为每个连接创建一个例程。 该例程将继续对连接对象进行轮询,以检查目标客户端是否通过连接发送了数据(如果您还记得之前的文章 ,我们已经看到websockets启用了双工通信)。 然后它将转发收到的通知到适当的处理器。 此外,一旦该泵在读取连接时出现一些错误,就会将针对该连接的注销请求发送到集线器例程。

    The Read pump — This go-routine will be created one per connection immediately after the connection upgrade request is approved. This routine will continuouly keep polling over the connection object, to check if there’s data sent over the connection by the target client (if you remember the earlier article, we’d seen that websockets enables a duplex communication). It will then forward the received notification to the appropriate processor. Additionally, as soon as this pump gets some error while reading over the connection, this will send a deregistration request for this connection to the hub routine.The read pump go-routine, as we’ve discussed, runs one per active connection.

    读取泵—在连接升级请求获得批准后,将立即为每个连接创建一个例程。 该例程将继续对连接对象进行轮询,以检查目标客户端是否通过连接发送了数据(如果您还记得之前的文章 ,我们已经看到websockets启用了双工通信)。 然后它将转发收到的通知到适当的处理器。 此外,一旦该泵在读取连接时出现一些错误,就会将针对该连接的注销请求发送到集线器例程。 正如我们所讨论的,读泵执行例程在每个活动连接中运行一个例程。

  5. The Write pump — The write pump will also be created one per connection, which handles the work of the last mile delivery of the notification through the connection. The notifications forwarded by the hub are, in this routine, written to the connection buffer by this pump. Here also, as we’d seen in the read-pump, as soon as it gets some error while pushing over the connection, it will send a deregistration request for this connection to the hub routine.

    写入泵 —每个连接还将创建一个写入泵 ,该泵将处理通过该连接进行的最后一英里通知的工作。 在此例程中,集线器转发的通知将通过此泵写入连接缓冲区。 同样在这里,正如我们在读取泵中看到的那样,一旦在推送连接时遇到一些错误,它将向该中心例程发送对此连接的注销请求。

    The Write pump — The write pump will also be created one per connection, which handles the work of the last mile delivery of the notification through the connection. The notifications forwarded by the hub are, in this routine, written to the connection buffer by this pump. Here also, as we’d seen in the read-pump, as soon as it gets some error while pushing over the connection, it will send a deregistration request for this connection to the hub routine.The write pump go-routine, runs one per active connection.For our case in point, the write pump against each of the three connections would receive the notification ‘Hello, Alexander Hamilton!’ and they would simply write this over the connection that they’re running for.

    写入泵 —每个连接还将创建一个写入泵 ,该泵将处理通过该连接进行的最后一英里通知的工作。 在此例程中,集线器转发的通知将通过此泵写入连接缓冲区。 同样在这里,正如我们在读取泵中看到的那样,一旦在推送连接时遇到一些错误,它将向该中心例程发送对此连接的注销请求。 写泵例程在每个活动连接上运行一个例程。就我们的情况而言,针对这三个连接的写泵将收到通知“ Hello,Alexander Hamilton!”。 他们只需将其写在正在运行的连接上。

Now, for all of these requests that the workers have to make to each other, channels are extensively used. As in the diagram, the channels used are-1. Hub Connection Registration Request Channel2. Hub Connection De-Registration Request Channel3. Hub Write Notification Channel4. Write Pump Write Notification Channel (1 per connection)5. (optional) Read Pump Received Notification Channel

现在,对于工人必须彼此提出的所有这些要求,渠道被广泛使用。 如图所示,使用的通道为-1。 集线器连接注册请求通道2。 集线器连接注销请求通道3。 集线器写入通知频道4。 写泵写通知通道(每个连接1个)5。 (可选)读取泵接收通知通道

Now that we understand the internal design of our websocket server, another interesting challenge worth looking at is the horizontal scaling of websocket server. On a high level, if you’ve worked with API servers you’ll know it’s easy to scale them since they’re all stateless. But here, all of our servers hold some state (the active connections). And if at all we want to have multiple servers, we’ll have to handle-1. Forwarding the notifications to only and all of those servers which have an active connection with that target that the notification is intended for.2. Route the new websocket connection request to the websocket server, based on some advanced logic rather than just round robin, so that the number of active connections are evenly distributed among the servers.More about this in the following article.

现在我们了解了websocket服务器的内部设计,另一个值得关注的挑战是websocket服务器的水平扩展。 从较高的角度来看,如果您使用过API服务器,您会知道扩展它们很容易,因为它们都是无状态的。 但是在这里,我们所有的服务器都拥有某种状态(活动连接)。 如果我们要拥有多个服务器,则必须处理1。 仅将通知转发给与该通知旨在发送给该目标的所有活动连接的所有服务器。 根据一些高级逻辑,而不只是轮循机制,将新的websocket连接请求路由到websocket服务器,从而使活动连接的数量均匀地分布在服务器之间。

翻译自: https://medium.com/@singhania94/building-a-browser-push-notification-service-the-low-level-design-using-the-gorilla-websocket-aa8372f3e113

go gorilla


http://www.taodudu.cc/news/show-4675648.html

相关文章:

  • echarts-gl 初体验
  • Mapbox GL JS介绍及使用
  • mapbox-gl开发教程(一):搭建前端开发环境
  • (二)GL 简单绘制
  • MapboxGL系列(一)基础知识介绍
  • WebGL—gl_Position gl_FragCoord gl_PointCoord 区别
  • 【OpenGL】十八、OpenGL 绘制多边形 ( 绘制 GL_POLYGON 模式多边形 )
  • mapbox-gl开发:集成deck.gl
  • Kepler.gl
  • GL Studio 5 安装与体验
  • GL各个表结构总结
  • Unity画线之GL
  • GLAPI/glTexStorage2D
  • 解决找不到GL/gl.h的问题
  • 关于GL的介绍
  • (一)GL简介
  • Pinterest瀑布流+UDC
  • Pinterest 3.0 for iOS设计过程——升级iOS7设计思路详解
  • 通过Pinterest号召性用语分享图片
  • 仿pinterest实现瀑布流布局效果
  • 如何在WordPress中添加Pinterest“ Pin It”按钮(最终指南)
  • Notification Volume Control and Optimization System at Pinterest 小记
  • 如何使用砌体在WordPress中添加Pinterest样式发布网格
  • 如何在WordPress侧边栏小部件中显示最新的Pinterest引脚
  • UICollectionView 自定义布局教程: Pinterest
  • 出海营销指南:什么是Pinterest分析?
  • 只需10分钟,给你全世界!水经注全球三维离线GIS系统
  • 怎么能把Excel数据导入到这个水经注软件里?
  • 水经注能否下载行政区域的矢量文件?
  • ArcGIS如何加载水经注下载的图片?

go gorilla_使用gorilla websocket构建浏览器推送通知服务的低级设计相关推荐

  1. android自定义push通知_20个海外Web和App推送通知服务工具

    在App和网站中使用推送通知有不同的原因,并且在提高流量和与客户互动方面有很多好处.推送通知是一种交互式可点击消息,可将访问者直接引导至你的网站.它们可以帮助你以指数方式增加流量和参与率.因此,营销人 ...

  2. 20个海外Web和App推送通知服务工具(一)

    在App和网站中使用推送通知有不同的原因,并且在提高流量和与客户互动方面有很多好处.推送通知是一种交互式可点击消息,可将访问者直接引导至你的网站.它们可以帮助你以指数方式增加流量和参与率.因此,营销人 ...

  3. 推送通知服务【WP7学习札记之十三】

    为什么使用推送通知服务 Windows Phone执行模型决定只有一个第三方的应用程序可以在前台运行,应用程序不能再后台运行,不断的往Cloud拉数据.微软提供推送通知服务(Push Notifica ...

  4. 苹果推送通知服务(APNs)编程(转)详细步骤

    iPhone 对于应用程序在后台运行有诸多限制(除非你越狱).因此,当用户切换到其他程序后,原先的程序无法保持运行状态.对于那些需要保持持续连接状态的应用程序(比如社区网络应用),将不能收到实时的信息 ...

  5. wns服务器没有响应,如何使用 Windows 推送通知服务 (WNS) 进行验证(Windows 运行时应用)...

    如何使用 Windows 推送通知服务 (WNS) 进行验证(Windows 运行时应用) 12/11/2015 本文内容 [ 本文适用于编写 Windows 运行时应用的 Windows 8.x 和 ...

  6. 【苹果推送Imessage Apple】摘要Apple推送通知服务更新

    苹果基于bug原因,停用了服务器端的SSL3.0连接方式.目前只支持TLS连接. 1. 如果推送的时候deviceToken对应的机器在APNS服务器上是离线状态,苹果会保存推送信息"一段时 ...

  7. 手把手教你开发安卓推送通知服务(使用阿里云 emas)

    0 前言 0.1 痛点:安卓推送通知无统一标准 安卓是开源的手机操作系统,各大手机硬件厂商都会在它的基础上定制自己的操作系统. 在中国,用户因为各种原因无法使用 Google 官方服务框架,所以,在中 ...

  8. Windows Phone 7 不温不火学习之《推送通知服务》

    Windows Phone 中的 Microsoft Push Notification Service 向第三方开发人员提供了一个弹性,专注,而且持续的渠道,使得开发人员可以从Web Service ...

  9. Apple推送通知服务教程

    Apple推送通知服务教程 生成APP ID和SSL证书 登录iOS Provisioning Portal页面 首先,我们将要新建一个App ID. 每一个推送APP都需要一个唯一的对应的App I ...

最新文章

  1. java---面试题 丑数
  2. [java设计模式简记] 观察者模式(Observer-Pattern)
  3. 商城是用jsp还是php,建设网上购物网站使用JSP系统还是ASP系统
  4. Java虚拟机学习总结(1)——JVM内存模型
  5. python ^ 操作在两整数加法运算中的妙用
  6. rt1052 usb速率_rt1052 spi flash 读数据好慢
  7. opencv 多边形近似物体形状
  8. python 爬虫_python爬虫技术汇总
  9. 工程力学:绪论与其它
  10. c语言自学 中文,C语言自学《一》 ---- 初探C语言
  11. PHP如何获取当前域名
  12. IOS开发之逆向分析
  13. Mac 好用的 Android 模拟器整理(玩游戏、装应用、支持咸鱼、拼多多...)
  14. 关于vlan tag untag 标签 区别
  15. Threejs 中的后期处理
  16. BZOJ 1616: [Usaco2008 Mar]Cow Travelling游荡的奶牛 bfs
  17. c语言实现创建学生成绩表,实现插入、删除和统计等管理功能。
  18. 新媒体背景下大学生的志愿服务参与研究(lunwen+任务书)
  19. 论文阅读笔记——[MPN]: Multi-task Learning with Coarse Priors for Robust Part-aware Person Re-identification
  20. 【计算机图形学入门】笔记5:光栅化(三角形的离散化)

热门文章

  1. 用好搜索神器Everything,盘活你的文件
  2. 如何运营京东店铺 京东店铺运营注意事项有哪些
  3. 西江月 - 书到用时方恨少
  4. dplayer解析源码php调用,从demo分析ijk源码一:视频播放
  5. 围观手机游戏: 一场还没准备好的全民冲锋
  6. 淘汰RM与RMVB的原因
  7. [BIOS] thinkpad X220 BIOS设置详解
  8. 什么是 3A 游戏?
  9. netcore ajax上传,.netCore WebApi传输参变化
  10. 采用网闸隔离的内外网如何进行数据的即时交互?