HTTP 请求异步资源,后端阻塞等待怎么高效实现?
发布于 6 年前 作者 wiviwiv 4911 次浏览 来自 问答

需求

有一个 HTTP 接口 A,后端会执行一段异步任务 发一个 HTTP 请求到 B 站点,B 站点异步执行后 callback A 站点的 HTTP 接口。

我想客户端请求的时候阻塞一下 A <—> B 这个过程,让客户端使用 A 的时候基本无感,有没有什么比较好的处理方案?

现有方案

标记每一个请求,A 接口上轮询等待 B 接口的返回结果。有其他更好的事件流或者闭包处理方案吗? 伪代码

const POOL = {}
function sleep(timer = 100) {
  return new Promise(resolve => {
    setTimeout(resolve, timer)
  })
}

// 客户端请求的接口
async function handle(ctx) {
  const tid = Math.random().toString()
  await axios.post('xxx', { tid })
  POOL[tid] = null
  for (let i = 0; i <= 100; i++) {
    // 轮询 POOL 有没有返回值
    if (POOL[tid]) {
	   break
	}
    await sleep()
  }
  const res = POOL[tid]
  if (!res) {
    ctx.throw(500)
  }
  ctx.body = res
}

async function callback() {
  const { tid, payload } = ctx.request.body
  if (POOL[tid] !== undefined) {
    POOL[tid] = payload
  }
  ctx.body = 'ok'
}

8 回复

上websocket 完成后通知浏览器

@xcstream 需求是异步转同步,就相当于这一部分异步操作想要阻塞成类似sql的慢查询

上个消息队列或者redis的订阅发布机制不就行了吗。

没明白的是: 客户端使用 A 的时候基本无感 ? 异步 同步 一样需要有个等待过程的啊 (网络/IO 都是需要时间的)。

如果你是解决 轮询问题,那 weboscket 或者 http2 的push 功能可以解决。

如果这个等待时间比较短,频次也比较低,那一直让这个连接保持就行了,等有数据再返回。

@guojingkang 订阅等待的过程中怎么阻塞 A 端这个 HTTP 请求

@wiviwiv 你的需求不太清晰呀,最好能清晰得描述下流程

@guojingkang 使用 A 服务请求 B 服务的资源,期间阻塞 A 上面的请求 直到 B 返回结果 B 服务是一个异步任务,请求完成后通过回调通知 A 的请求是否完成。

@wiviwiv A 向 B发起请求,B进行处理,建议这里用一个中间结构来处理 B 返回结果,sql或者redis等等等,A 主动轮询中间结构,得到想要的结果再 res.end

回到顶部