服务器启动的请求 [英] Server-initiated requests

查看:52
本文介绍了服务器启动的请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道HTTP是一个请求-响应协议.简而言之,我的问题是客户端向服务器发出启动长时间运行进程的请求,我想通过一条包含进度信息的简单JSON消息将进度通知客户端.

在HTTP/1.1中,我知道我可以使用WebSocket或服务器发送的事件(SSE)或长时间轮询.

现在我知道HTTP/2尚不支持WebSocket.

我的问题是,通过HTTP/2处理此类事情的最佳方法是什么?

在处理HTTP/2中服务器启动的请求时,我是否不了解任何新事物?

如果重要的话,我正在使用Go语言.

解决方案

在websocket之前,我们已经进行过轮询.从字面上看,这意味着让客户端定期(每隔几秒钟,或对您的应用程序有意义的任何时间段),向服务器发出请求以了解作业状态.

许多人使用的优化是长时间"轮询.这涉及到让服务器接受请求,并在服务器内部对更改进行检查,然后在没有更改的情况下进入睡眠状态,直到达到特定的超时时间或发生所需的事件,然后将其发回给客户端.

如果达到超时,则连接将关闭,并且客户端需要再次发出请求.服务器代码如下所示,假设这些函数根据它们的名称和签名来做明智的事情:

  import("net/http"时间")func PollingHandler(w http.ResponseWriter,r * http.Request){jobID:= getJobID(r)完成:= 60;完成>0;完成-{//重复〜1分钟状态,错误:= checkStatus(jobID)如果err!= nil {writeError(w,err)返回}如果状态!=无{writeStatus(w,状态)返回}time.Sleep(time.Second)//睡眠1秒}writeNil(w)//特定的响应告诉客户端再次请求.} 

处理超时的更好方法是使用上下文包,并使用超时.看起来像这样:

  import("net/http"时间""golang.org/x/net/context")func PollingHandler(w http.ResponseWriter,r * http.Request){jobID:= getJobID(r)ctx:= context.WithTimeout(context.Background(),time.Second * 60)为了 {选择{情况< -ctx.Done():writeNil(w)默认:状态,错误:= checkStatus(jobID)如果err!= nil {writeError(w,err)返回}如果状态!=无{writeStatus(w,状态)返回}time.Sleep(time.Second)//睡眠1秒}}} 

第二个版本将在更可靠的时间内返回,尤其是在 checkStatus 调用速度较慢的情况下.

I know that HTTP is a request-response protocol. My problem, in short, is that a client makes a request to the server to start a long running-process, and I want to inform the client of the progress with a simple JSON message containing progress info.

In HTTP/1.1 I know that I could use a WebSocket or server-sent events (SSE) or long polling.

Now I know that HTTP/2 does not support WebSocket yet.

My question is, what is the optimal way to handle such things over HTTP/2?

Are there any new things that I am not aware of to handle server-initiated requests in HTTP/2?

I am using the Go language, if that matters.

解决方案

Before websockets we had polling. This literally means having the client periodically (every few seconds, or whatever time period makes sense for your application), make a request to the server to find out the status of the job.

An optimization many people use is "long" polling. This involves having the server accept the request, and internally to the server, check for changes, and sleep while there are none, until either a specific timeout is reached or the desired event occurs, which is then messaged back to the client.

If a timeout is reached, the connection is closed and the client needs to make another request. The server code would look something like the following, assume the functions do sensible things based on their names and signatures:

import (
    "net/http"
    "time"
)

func PollingHandler(w http.ResponseWriter, r *http.Request) {
    jobID := getJobID(r)
    for finish := 60; finish > 0; finish-- { // iterate for ~1 minute
        status, err := checkStatus(jobID)
        if err != nil {
            writeError(w, err)
            return
        }
        if status != nil {
            writeStatus(w, status)
            return
        }
        time.Sleep(time.Second) // sleep 1 second
    }
    writeNil(w) // specific response telling client to request again.
}

A better way to handle the timeout would be to use the context package and create a context with a timeout. That would look something like:

import (
    "net/http"
    "time"
    "golang.org/x/net/context"
)

func PollingHandler(w http.ResponseWriter, r *http.Request) {
    jobID := getJobID(r)
    ctx := context.WithTimeout(context.Background(), time.Second * 60)
    for {
        select{
        case <-ctx.Done():
            writeNil(w)
        default: 
            status, err := checkStatus(jobID)
            if err != nil {
                writeError(w, err)
                return
            }
            if status != nil {
                writeStatus(w, status)
                return
            }
            time.Sleep(time.Second) // sleep 1 second
        }
    }

}

This second version is just going to return in a more reliable amount of time, especially in the case where checkStatus may be a slower call.

这篇关于服务器启动的请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆