初探 Watermill 构建 Golang 事件驱动程序,SSE 进行 HTTP 服务器推送

简介: 初探 Watermill 构建 Golang 事件驱动程序,SSE 进行 HTTP 服务器推送

使用 SSE(Server-Sent Events) 进行 HTTP 服务器推送

这个示例是一个类似 twitter 的 web 应用程序,使用 Server-Sent Events 来支持实时刷新。


微信图片_20220610233344.gif


运行


docker-compose up


然后, 浏览 http://localhost:8080

您可以添加自己的帖子或点击按钮获得随机生成的帖子。

无论哪种方式,feeds 列表和 feed 中的帖子都应该是最新的。尝试使用第二个浏览器窗口查看更新。


它是如何工作的



  • 可以创建和更新帖子。
  • 帖子可以包含标签。
  • 每个标签都有自己的 feed,其中包含来自该标签的所有帖子。
  • 所有的帖子都存储在 MySQL 中。这就是写模型。
  • 所有 feed 都异步更新并存储在 MongoDB 中。这是读模型。


为什么要使用单独的写和读模型?


对于这个示例应用程序,使用多语言持久性(两个数据库引擎)当然有些过头了。我们这样做是为了展示这个技术,以及如何很容易地将它应用到 Watermill。

专用的读模型对于具有高读/写比率的应用程序是一种有用的模式。所有写操作都被原子地应用到写模型(在我们的例子中是 MySQL)。事件处理程序异步更新读模型(我们使用 Mongo)。


读取模型中的数据可以按原样使用。也可以独立于写模型进行扩展。

请记住,要使用此模式,应用程序中必须接受最终的一致性。而且,在大多数用例中,您可能不需要使用它。务实!


微信图片_20220610233412.jpg

image.gif

SSE Router


SSERouter 来自 watermill-http。当创建一个新的路由器时,你需要传递一个上游订阅者。来自该订阅服务器的消息将触发通过 HTTP 推送更新。

在本例中,我们使用 NATS 作为 Pub/Sub,但这可以是 Watermill 支持的任何 Pub/Sub。


sseRouter, err := watermillHTTP.NewSSERouter(
    watermillHTTP.SSERouterConfig{
        UpstreamSubscriber: router.Subscriber,
        ErrorHandler:       watermillHTTP.DefaultErrorHandler,
    },
    router.Logger,
)


Stream Adapters(流适配器)


要使用 SSERouter,你需要准备一个带有两个方法的 StreamAdapter

GetResponse 类似于标准的 HTTP 处理程序。修改现有的处理程序来匹配这个签名应该非常容易。


Validate 是一个额外的方法,它告诉我们是否应该为特定的 Message 推送更新。


type StreamAdapter interface {
  // GetResponse returns the response to be sent back to client.
  // Any errors that occur should be handled and written to `w`, returning false as `ok`.
  GetResponse(w http.ResponseWriter, r *http.Request) (response interface{}, ok bool)
  // Validate validates if the incoming message should be handled by this handler.
  // Typically this involves checking some kind of model ID.
  Validate(r *http.Request, msg *message.Message) (ok bool)
}



Validate 示例如下所示。它检查消息是否来自与用户通过 HTTP 请求发送的相同的 post ID。


func (p postStreamAdapter) Validate(r *http.Request, msg *message.Message) (ok bool) {
  postUpdated := PostUpdated{}
  err := json.Unmarshal(msg.Payload, &postUpdated)
  if err != nil {
    return false
  }
  postID := chi.URLParam(r, "id")
  return postUpdated.OriginalPost.ID == postID
}


如果你想为每条消息触发一个更新,你可以简单地返回 true


func (f allFeedsStreamAdapter) Validate(r *http.Request, msg *message.Message) (ok bool) {
  return true
}


在开始 SSERouter 之前,您需要添加带有特定主题的处理程序。 AddHandler 返回一个可以在任何路由库中使用的标准 HTTP 处理程序。


postHandler := sseRouter.AddHandler(PostUpdatedTopic, postStream)
// ...
r.Get("/posts/{id}", postHandler)


Event handlers(事件处理程序)


该示例使用 Watermill 进行所有异步通信,包括 SSE。

发布了以下事件:


  • PostCreated
  • 将 post 添加到贴子中包含标签的所有 feeds 中。
  • FeedUpdated
  • 将更新推送到当前访问 feed 页面的所有客户端。
  • PostUpdated
  • a) 对于现有标签,帖子内容将在标签中更新。
  • b) 如果添加了新的标签,文章将被添加到标签的 feed 中。
  • c) 如果标签已删除,则该帖子将从标签的 feed 中删除。
  • 将更新推送给所有当前访问 post 页面的客户端。
  • 使用帖子中存在的标签更新所有 feeds 中的帖子


前端 app


前端应用程序是使用 Vue.js 和 Bootstrap 构建的。

最有趣的部分是 EventSource 的使用。


this.es = new EventSource('/api/feeds/' + this.feed)
this.es.addEventListener('data', event => {
    let data = JSON.parse(event.data);
    this.posts_stream = data.posts;
}, false);


Refs


  • watermill.io
目录
打赏
0
0
0
0
26
分享
相关文章
服务器发送事件(SSE)在现代Web开发中的关键作用
服务器发送事件(SSE)是HTML5标准协议,用于服务器主动向客户端推送实时数据,适合单向通信场景。相比WebSocket,SSE更简洁高效,基于HTTP协议,具备自动重连、事件驱动等特性。常见应用场景包括实时通知、新闻推送、数据分析等。通过Apipost等工具可轻松调试SSE,助力开发者构建高效实时Web应用。示例中,电商平台利用SSE实现秒杀活动通知,显著减少延迟并简化架构。掌握SSE技术,能大幅提升用户体验与开发效率。
精通服务器推送事件(SSE)与 Python 和 Go 实现实时数据流 🚀
服务器推送事件(SSE)是HTML5规范的一部分,允许服务器通过HTTP向客户端实时推送更新。相比WebSocket,SSE更轻量、简单,适合单向通信场景,如实时股票更新或聊天消息。它基于HTTP协议,使用`EventSource` API实现客户端监听,支持自动重连和事件追踪。虽然存在单向通信与连接数限制,但其高效性使其成为许多轻量级实时应用的理想选择。文中提供了Python和Go语言的服务器实现示例,以及HTML/JavaScript的客户端代码,帮助开发者快速集成SSE功能,提升用户体验。
动态URL构建与HTTP请求的Kotlin实现
动态URL构建与HTTP请求的Kotlin实现
从零到一构建网络爬虫帝国:HTTP协议+Python requests库深度解析
【7月更文挑战第31天】在网络数据的海洋中,使用Python的`requests`库构建网络爬虫就像探索未知的航船。HTTP协议指导爬虫与服务器交流,收集信息。HTTP请求包括请求行、头和体,响应则含状态行、头和体。`requests`简化了发送各种HTTP请求的过程。
136 4
服务器支持HTTPS的时机和条件
【10月更文挑战第23天】服务器支持HTTPS的时机和条件
64 5
|
6月前
HAProxy的高级配置选项-配置haproxy支持https协议及服务器动态上下线
文章介绍了如何配置HAProxy以支持HTTPS协议和实现服务器的动态上下线。
274 8
从零到一构建网络爬虫帝国:HTTP协议+Python requests库深度解析
在网络数据的海洋中,网络爬虫遵循HTTP协议,穿梭于互联网各处,收集宝贵信息。本文将从零开始,使用Python的requests库,深入解析HTTP协议,助你构建自己的网络爬虫帝国。首先介绍HTTP协议基础,包括请求与响应结构;然后详细介绍requests库的安装与使用,演示如何发送GET和POST请求并处理响应;最后概述爬虫构建流程及挑战,帮助你逐步掌握核心技术,畅游数据海洋。
120 3
|
5月前
|
深入解析Python网络编程与Web开发:urllib、requests和http模块的功能、用法及在构建现代网络应用中的关键作用
深入解析Python网络编程与Web开发:urllib、requests和http模块的功能、用法及在构建现代网络应用中的关键作用
46 0