HarmonyOS APP开发---“股动力“实时行情App,需要用到这个库

HarmonyOS APP开发---"股动力"实时行情App,需要用到这个库

想做一个股票行情 App,K 线、分时、盘口数据要实时推送?REST 轮询延迟高又费流量,WebSocket 又缺强类型契约------@ohos/grpc 的双向流式 RPC 才是正解。
📦 仓库地址:https://gitcode.com/CPF-ApplicationTPC/ohos_grpc_node | 安装:ohpm install @ohos/grpc


写在前面

"股动力"的核心难点是"实时性"。股票行情每秒可能产生几十条 tick,用户打开个股详情页,期望看到的是毫秒级刷新的分时线和盘口。

传统方案的问题:

  • REST 轮询:每秒请求一次,延迟最高 1 秒,流量浪费严重
  • WebSocket:能推送,但没有强类型契约,前后端字段对不上全靠口口相传
  • HTTP/1.1 长连接:单连接不能多路复用,并发请求互相阻塞

gRPC 基于 HTTP/2,天然支持流式通信 + Protobuf 强类型。服务端持续推 tick,客户端持续发订阅,单连接多路复用------这就是"股动力"选它的原因。

这篇文章聊什么

  1. Unary RPC------拉取股票基本信息(一次性请求)
  2. Server Streaming------服务端持续推送实时 tick
  3. 双向流------客户端发订阅,服务端推行情

#mermaid-svg-55sxZ1mWubHcDOMd{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-55sxZ1mWubHcDOMd .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-55sxZ1mWubHcDOMd .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-55sxZ1mWubHcDOMd .error-icon{fill:#552222;}#mermaid-svg-55sxZ1mWubHcDOMd .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-55sxZ1mWubHcDOMd .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-55sxZ1mWubHcDOMd .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-55sxZ1mWubHcDOMd .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-55sxZ1mWubHcDOMd .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-55sxZ1mWubHcDOMd .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-55sxZ1mWubHcDOMd .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-55sxZ1mWubHcDOMd .marker{fill:#333333;stroke:#333333;}#mermaid-svg-55sxZ1mWubHcDOMd .marker.cross{stroke:#333333;}#mermaid-svg-55sxZ1mWubHcDOMd svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-55sxZ1mWubHcDOMd p{margin:0;}#mermaid-svg-55sxZ1mWubHcDOMd .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-55sxZ1mWubHcDOMd .cluster-label text{fill:#333;}#mermaid-svg-55sxZ1mWubHcDOMd .cluster-label span{color:#333;}#mermaid-svg-55sxZ1mWubHcDOMd .cluster-label span p{background-color:transparent;}#mermaid-svg-55sxZ1mWubHcDOMd .label text,#mermaid-svg-55sxZ1mWubHcDOMd span{fill:#333;color:#333;}#mermaid-svg-55sxZ1mWubHcDOMd .node rect,#mermaid-svg-55sxZ1mWubHcDOMd .node circle,#mermaid-svg-55sxZ1mWubHcDOMd .node ellipse,#mermaid-svg-55sxZ1mWubHcDOMd .node polygon,#mermaid-svg-55sxZ1mWubHcDOMd .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-55sxZ1mWubHcDOMd .rough-node .label text,#mermaid-svg-55sxZ1mWubHcDOMd .node .label text,#mermaid-svg-55sxZ1mWubHcDOMd .image-shape .label,#mermaid-svg-55sxZ1mWubHcDOMd .icon-shape .label{text-anchor:middle;}#mermaid-svg-55sxZ1mWubHcDOMd .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-55sxZ1mWubHcDOMd .rough-node .label,#mermaid-svg-55sxZ1mWubHcDOMd .node .label,#mermaid-svg-55sxZ1mWubHcDOMd .image-shape .label,#mermaid-svg-55sxZ1mWubHcDOMd .icon-shape .label{text-align:center;}#mermaid-svg-55sxZ1mWubHcDOMd .node.clickable{cursor:pointer;}#mermaid-svg-55sxZ1mWubHcDOMd .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-55sxZ1mWubHcDOMd .arrowheadPath{fill:#333333;}#mermaid-svg-55sxZ1mWubHcDOMd .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-55sxZ1mWubHcDOMd .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-55sxZ1mWubHcDOMd .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-55sxZ1mWubHcDOMd .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-55sxZ1mWubHcDOMd .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-55sxZ1mWubHcDOMd .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-55sxZ1mWubHcDOMd .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-55sxZ1mWubHcDOMd .cluster text{fill:#333;}#mermaid-svg-55sxZ1mWubHcDOMd .cluster span{color:#333;}#mermaid-svg-55sxZ1mWubHcDOMd div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-55sxZ1mWubHcDOMd .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-55sxZ1mWubHcDOMd rect.text{fill:none;stroke-width:0;}#mermaid-svg-55sxZ1mWubHcDOMd .icon-shape,#mermaid-svg-55sxZ1mWubHcDOMd .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-55sxZ1mWubHcDOMd .icon-shape p,#mermaid-svg-55sxZ1mWubHcDOMd .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-55sxZ1mWubHcDOMd .icon-shape .label rect,#mermaid-svg-55sxZ1mWubHcDOMd .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-55sxZ1mWubHcDOMd .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-55sxZ1mWubHcDOMd .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-55sxZ1mWubHcDOMd :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是

打开个股页
Unary: 拉基本信息
Server Stream: 订阅 tick
服务端持续推送
渲染 K 线/分时
切换股票?
Bidi: 发新订阅


第一步:安装

bash 复制代码
ohpm install @ohos/grpc

安装后需将仓库 protobufjs/index.d.ts 替换到 oh_modules 对应路径,确保 Protobuf 类型完整。


第二步:Unary RPC------拉取股票基本信息

打开个股页,先拉一次静态信息(名称、昨收、总股本等):

typescript 复制代码
import { grpc } from '@ohos/grpc'

const client = new grpc.Client('https://grpc.market-server.com', {
  credentials: grpc.credentials.createInsecure()
})

// Unary:一次请求,一次响应
client.makeUnaryRequest(
  '/stock.StockService/GetInfo',
  (req) => req.serializeBinary(),
  (buf) => StockInfo.deserializeBinary(buf),
  StockRequest.encode({ code: '600519' }).finish(),
  (err, response) => {
    if (err) { console.error(err); return }
    console.info(`${response.getName()} 昨收 ${response.getPreClose()}`)
    // 渲染基本信息
  }
)

Unary 模式和普通 HTTP 请求很像------一问一答。适合拉取不频繁变更的静态数据。


第三步:Server Streaming------持续接收实时 tick

订阅某只股票后,服务端持续推送 tick 数据:

typescript 复制代码
// Server Streaming:一次请求,持续接收
const stream = client.makeServerStreamRequest(
  '/stock.StockService/SubscribeTick',
  (req) => req.serializeBinary(),
  (buf) => Tick.deserializeBinary(buf),
  SubscribeRequest.encode({ code: '600519', level: 1 }).finish()
)

stream.on('data', (tick) => {
  // 每收到一个 tick,更新 K 线和盘口
  console.info(`价格 ${tick.getPrice()} 量 ${tick.getVolume()}`)
  updateChart(tick)
})

stream.on('end', () => {
  console.info('行情推送结束(收盘)')
})

stream.on('error', (err) => {
  console.error('行情异常: ' + err)
})

这就是 gRPC 流式的核心优势------一个请求建立流,服务端持续推,无需反复建连。比 REST 轮询省流量、低延迟,比 WebSocket 多了 Protobuf 强类型。


第四步:双向流------动态切换订阅

用户从 A 股切到 B 股,不需要断开重连,直接在同一个流里发新订阅:

typescript 复制代码
const bidiStream = client.makeBidiStreamRequest(
  '/stock.StockService/WatchMulti',
  serializer,
  deserializer,
  metadata
)

// 收到行情
bidiStream.on('data', (tick) => {
  updateChart(tick)
})

// 动态发订阅:先订阅 A,再切到 B
bidiStream.write(Subscribe.encode({ code: '600519' }).finish())

// 用户切换股票
setTimeout(() => {
  bidiStream.write(Subscribe.encode({ code: '000858' }).finish())
}, 5000)

// 取消订阅
bidiStream.write(Unsubscribe.encode({ code: '600519' }).finish())

双向流是 gRPC 最强大的模式------一个连接管多只股票的订阅/取消,互不干扰 。这在 REST 里要维护一堆连接状态,在 gRPC 里就是几行 write


为什么"股动力"选了 gRPC?

需求 REST 轮询 WebSocket gRPC
实时推送 ❌ 轮询延迟高 ✅ 可推送 ✅ 流式推送
强类型契约 ❌ JSON 无约束 ❌ 无 ✅ Protobuf
多路复用 ❌ 多连接 ⚠️ 单流 ✅ HTTP/2
动态订阅 ❌ 难管理 ⚠️ 手写协议 ✅ 双向流
跨语言 ✅ Go/Java/Python 互通

总结

"股动力"这个场景里,@ohos/grpc 解决了三件事:

  1. 静态信息------Unary RPC 一问一答,拉股票基本信息
  2. 实时行情------Server Streaming 持续推送 tick,毫秒级触达
  3. 动态订阅------双向流,切股票不断连,发个 write 就行

如果你也在做实时行情、在线协作、IoT 网关双向通信等场景,@ohos/grpc 的流式能力会让你彻底忘掉 REST 轮询的痛。

相关推荐
碧海银沙音频科技研究院3 小时前
ONNX 的全称Open Neural Network Exchange(开放神经网络交换格式)
人工智能·音视频·语音识别
小雨青年4 小时前
【HarmonyOS 7 沉浸光感深度实战】10 通用组件封装与现有项目接入
华为·harmonyos
YM52e4 小时前
蒙特卡洛模拟器:鸿蒙 Canvas 上的大数定律与中心极限定理实证
华为·harmonyos
IT小白杨4 小时前
短视频多账号运营环境管理指南:指纹浏览器与云手机技术解析
大数据·经验分享·web安全·智能手机·音视频·指纹浏览器
人工智能研究所4 小时前
正面硬刚 Seedance 2.5, 开源视频模型:LTX-2.5 用 6.8 秒生成 10 秒视频
人工智能·开源·音视频·文生视频·seedance·ltx-2.5
乐橙开放平台5 小时前
物业 SaaS 笔记:子账号 Policy 按通道隔离,At_ 管控面 / St_ 数据面治理 accessToken
后端·物联网·音视频
Dovis(誓平步青云)5 小时前
DevEco Studio 6.1.1 Windows 安装实录:从下载校验到首次启动
android·开发语言·数据库·人工智能·windows·harmonyos
2501_919749036 小时前
华为鸿蒙免费排班APP—小羊排班
华为·harmonyos·鸿蒙
pillowss7 小时前
如何去除视频背景:5 种可靠的方法
人工智能·音视频