返回首页

SPA 中的 SSE 通知:无需轮询的实时

本文描述了基于 SSE 和 Mercure 的 SPA 中异步通知的架构。与 CDC 集成以跟踪 DB 变更,重用 OpenAPI schemas 进行类型定义。为开发者提供的代码示例和图表。

SPA 中的 SSE 推送通知:架构和代码
Advertisement 728x90

利用SSE与Mercure实现SPA异步数据更新

前端应用需要持续的数据更新以反映后端变化。标准API调用仅能捕获响应时刻的状态,但后端会持续处理事件:如账户充值、内容审核、客服回复等。为此,我们采用基于SSE的推送机制,并与现有OpenAPI规范集成。

该系统结合了拉取方式(定期请求)与推送方式(实时通知)。SSE通过HTTP/2提供单向事件流,相比轮询能显著降低负载。

异步通知的应用场景

异步通知在业务流程中至关重要:

Google AdInline article slot
  • 余额充值:显示当前状态以便即时购买。
  • 内容审核:审核后更新状态。
  • 客服回复:即时通知新工单。

在典型场景中,用户(如广告主或承包商)会跟踪请求计数器:需要操作的数量、未读评论、投放检查等。这些数据可通过API端点/rest/User/info(操作ID:getInfo)获取。

/rest/User/info:
  get:
    tags:
      - User
    summary: 返回当前用户信息
    operationId: getInfo
    responses:
      200:
        description: 当前用户信息
        content:
          application/json:
            schema:
              type: object
              properties:
                id:
                  type: integer
                  format: int32
                  minimum: 0
                locale:
                  type: string
                  enum: [ru, en]
                login:
                  type: string
                  minimum: 3
                  maximum: 320
                seoCounters:
                  $ref: '#/components/schemas/SeoCounters'

SeoCounters模式定义了结构:

SeoCounters:
  type: object
  properties:
    nofRequests:
      type: integer
      format: int32
      minimum: 0
    nofLinksStatusNeedApprove:
      type: integer
      format: int32
      minimum: 0
    nofLinksWithUnreadComments:
      type: integer
      format: int32
      minimum: 0
    nofChanges:
      type: integer
      format: int32
      minimum: 0
    nofPlacementCheck:
      type: integer
      format: int32
      minimum: 0

集成CDC与数据平台

user_counters表中的变更通过CDC(变更数据捕获)进行跟踪。修改流被发送到数据平台——一个企业级ETL系统。从那里,事件通过SSE枢纽推送到用户界面。

Google AdInline article slot

架构采用六边形模型:OpenAPI规范自动生成REST适配器和TypeScript类型。对于前端,类型如下所示:

/* 由orval生成 */
export interface SeoCounters {
  nofRequests?: number;
  nofLinksStatusNeedApprove?: number;
  nofLinksWithUnreadComments?: number;
  nofChanges?: number;
  nofPlacementCheck?: number;
}

export type GetInfo200 = {
  id: number;
  locale: 'ru' | 'en';
  login: string;
  seoCounters?: SeoCounters;
};

这些类型被复用于处理SSE事件,确保类型安全。

在应用中实现SSE

SSE(服务器发送事件)是服务器推送的标准,由浏览器支持。EventSource连接到端点:

Google AdInline article slot
const evtSource = new EventSource('/sse-endpoint', {
  withCredentials: true,
});

evtSource.onmessage = (event) => {
  const data = JSON.parse(event.data);
  // 使用类型化数据更新存储
  updateSeoCounters(data.seoCounters);
};

对于授权、主题和扩展,我们使用Mercure——一个基于SSE的开源枢纽。该枢纽通过REST接受带有JWT的发布,并向订阅者广播。

发布示例:

curl -d 'topic=https://example.com/books/1' \
     -d 'data={"foo": "updated value"}' \
     -H 'Authorization: Bearer <JWT>' \
     -X POST https://hub/.well-known/mercure

JWT定义了主题的发布/订阅权限。Mercure作为容器部署,带有外部数据库,并与CDC流集成。

该方法的优势

  • 模式复用:OpenAPI结构在拉取和推送中复用,无需重复。
  • 实时性:变更即时反映,无需轮询。
  • 可扩展性:Mercure枢纽分发负载。

监控的关键计数器列表:

  • nofRequests —— 操作请求。
  • nofLinksStatusNeedApprove —— 待批准链接。
  • nofLinksWithUnreadComments —— 未读评论。
  • nofPlacementCheck —— 投放检查。

关键要点

  • SSE与Mercure提供类型化推送通知,无需WebSocket开销。
  • CDC实时捕获数据库变更以用于ETL流程。
  • 从OpenAPI自动生成TypeScript类型确保数据一致性。
  • 该方法适用于高负载系统,支持数千用户。
  • Mercure中的JWT管理通知主题的访问权限。

— Editorial Team

Advertisement 728x90

继续阅读