Websocket の前には、ポーリングがありました。これは文字通り、クライアントが定期的に (数秒ごと、またはアプリケーションにとって意味のある期間)、サーバーにリクエストを送信してジョブのステータスを確認することを意味します。
多くの人が使用する最適化は、「長い」ポーリングです。これには、サーバーがリクエストを受け入れ、サーバーの内部で変更をチェックし、何もない間は特定のタイムアウトに達するか目的のイベントが発生するまでスリープし、クライアントにメッセージが返されるようにすることが含まれます。
タイムアウトに達すると、接続が閉じられ、クライアントは別の要求を行う必要があります。サーバーコードは次のようになります。関数が名前と署名に基づいて適切な処理を行うと仮定します。
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.
}
タイムアウトを処理するためのより良い方法は、コンテキスト パッケージを使用し、タイムアウトのあるコンテキストを作成することです。それは次のようになります。
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
}
}
}
checkStatus
この 2 番目のバージョンは、特に呼び出しが遅くなる可能性がある場合に、より信頼性の高い時間で返されます。