2015-06-15 13 views
10

मुझे पता है कि HTTP एक अनुरोध-प्रतिक्रिया प्रोटोकॉल है। मेरी समस्या, संक्षेप में, यह है कि क्लाइंट सर्वर को लंबे समय तक चलने वाली प्रक्रिया शुरू करने का अनुरोध करता है, और मैं प्रगति के क्लाइंट को प्रगति जानकारी वाले एक साधारण JSON संदेश के साथ सूचित करना चाहता हूं।सर्वर द्वारा शुरू किए गए अनुरोध

HTTP/1.1 में मुझे पता है कि मैं वेबस्केट या सर्वर से भेजे गए ईवेंट (एसएसई) या लंबे मतदान का उपयोग कर सकता हूं।

अब मुझे पता है कि HTTP/2 वेबस्केट का समर्थन नहीं करता है।

मेरा सवाल है, HTTP/2 पर ऐसी चीजों को संभालने का सबसे अच्छा तरीका क्या है?

क्या कोई नई चीजें हैं जिन्हें मुझे HTTP/2 में सर्वर द्वारा शुरू किए गए अनुरोधों को संभालने के बारे में पता नहीं है?

यदि मैं मायने रखता हूं, तो मैं गो भाषा का उपयोग कर रहा हूं।

उत्तर

8

वेबसाइकिल से पहले हमने मतदान किया था। इसका शाब्दिक अर्थ है क्लाइंट को समय-समय पर (प्रत्येक कुछ सेकंड, या जो भी समय अवधि आपके आवेदन के लिए समझ में आता है), सर्वर को नौकरी की स्थिति जानने के लिए अनुरोध करें।

कई लोगों का उपयोग "अनुकूल" मतदान एक अनुकूलन है। इसमें सर्वर अनुरोध को स्वीकार करता है, और आंतरिक रूप से सर्वर पर, परिवर्तनों की जांच करता है, और कोई भी नहीं होने पर सो जाता है, जब तक कोई विशिष्ट टाइमआउट नहीं पहुंच जाता है या वांछित घटना होती है, जिसे तब क्लाइंट को वापस भेज दिया जाता है।

यदि कोई टाइमआउट पहुंच गया है, तो कनेक्शन बंद हो गया है और ग्राहक को एक और अनुरोध करने की आवश्यकता है। सर्वर कोड निम्नलिखित कुछ ऐसा दिखाई देगा, मान लें कार्यों उनके नाम और हस्ताक्षर के आधार पर समझदार बातें करते हैं:

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. 
} 

टाइमआउट को संभालने के लिए context package का उपयोग करें और एक समय समाप्ति के साथ एक संदर्भ बनाने के लिए किया जाएगा एक बेहतर तरीका ।

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 एक धीमी कॉल हो सकता है जा रहा है: यह कुछ ऐसा दिखाई देगा।

+0

धन्यवाद, यह उपयोगी है, मैंने मतदान के बारे में सोचा था, लेकिन क्या यह वास्तव में http2 पर रीयलटाइम ऐप्स के लिए जाने का तरीका है ?, अगर राज्य में बदलाव नहीं आया तो अनुरोध क्यों करें? मुझे अनुरोध के बिना क्लाइंट को अनुरोध भेजने के बारे में कुछ भी नहीं मिला। – FPGA

+1

आम तौर पर HTTP सर्वर से ग्राहकों को अनुरोध करने में सक्षम होने की उम्मीद नहीं है। अधिकांश समय आपको क्लाइंट को फ़ायरवॉल किया जाएगा, एनएटी के पीछे, या अन्यथा पहुंच योग्य नहीं है। HTTP2 ठंडा है, लेकिन जब तक कि आप अपनी कुछ नई सुविधाओं का उपयोग नहीं कर रहे हैं (जो कि संभवतः गो के कार्यान्वयन की संभावना नहीं है, इस समय के लिए बहुत कच्चा है), आप केवल HTTP 1.1 के साथ चिपके रह सकते हैं और अच्छे पुराने websockets का उपयोग कर सकते हैं।गो में तैयार होने पर HTTP2 में अपग्रेड लगभग निश्चित रूप से बहुत आसान होगा। – Endophage

3

आप एचटीएमएल 5 टेक्स्ट/इवेंट-स्ट्रीम ए.के.ए. सर्वर साइड इवेंट्स (एसएसई) का उपयोग करने पर विचार कर सकते हैं। सवाल में एसएसई का उल्लेख है, क्या यह http2 के साथ अच्छी तरह से काम नहीं करेगा?

SSE के बारे में

निम्न आलेख में, (आईई वर्तमान में केवल ब्राउज़र कि SSE का समर्थन नहीं करता है) http2 धक्का जनरल लेख एसएसई के साथ संयुक्त है।दस्तावेज़ ग्राहक कैश में धकेल दिया जाता है और SSE ग्राहक को सूचित करने के क्या दस्तावेजों अपने कैश से प्राप्त किया जा सकता है (= सर्वर शुरू की एक भी http2 कनेक्शन पर अनुरोध) प्रयोग किया जाता है:

मूल बातें की SSE: सर्वर साइड पर, आप शुरू के साथ:

Content-Type: text/event-stream\n\n 

तो हर बार जब आप ग्राहक के लिए एक अद्यतन भेजना चाहते हैं के लिए आप भेजने

data: { "name": "value", "othername": "othervalue" }\n\n 

समाप्त होने पर, पहले कनेक्शन बंद करने, आप वैकल्पिक भेज सकते हैं:

retry: 60000\n\n 

ब्राउज़र को निर्देश देने के बाद 60000 msec

एक नया कनेक्शन ब्राउज़र कनेक्शन इस तरह किया जाता है में पुन: प्रयास करना :

var URL = "http://myserver/myeventstreamer" 
if (!!window.EventSource) { 
    source = new EventSource(URL); 
} else { 
    // Resort to xhr polling :(
    alert ("This browser does not support Server Sent Events\nPlease use another browser") 
} 

source.addEventListener('message', function(e) { 
    console.log(e.data); 
}, false); 

source.addEventListener('open', function(e) { 
    // Connection was opened. 
}, false); 

source.addEventListener('error', function(e) { 
    if (e.readyState == EventSource.CLOSED) { 
    // Connection was closed. 
    } 
}, false); 
+0

कृपया ध्यान दें कि सर्वर हमेशा एसएसई में HTTP अनुरोध प्राप्त करेगा। यदि आप अपने HTTP सर्वर या ब्राउज़र के नेटवर्क लॉग में एक्सेस लॉग की जांच करेंगे तो आपको पता चलेगा। –

1

आप पाठ के रूप में JSON संदेश भेजना चाहते हैं, तो एक server-sent event (SSE) यह करने के लिए एक अच्छा तरीका है। एसएसई को पाठ भेजने के लिए डिज़ाइन किया गया है। सभी घटना डेटा यूटीएफ -8 अक्षरों में एन्कोड किया गया है। नकारात्मकता यह है कि इससे एसएसई के माध्यम से बाइनरी डेटा भेजने में अक्षम हो जाता है।

यदि आप बाइनरी डेटा भेजना चाहते हैं, तो आपको HTTP/2 द्वारा पेश की गई Server Push तंत्र में रुचि हो सकती है। सर्वर पुश एक HTTP/2 सर्वर को क्लाइंट को अपनी पहल पर किसी भी प्रकार की फाइल भेजने की अनुमति देता है। इसे सर्वर पुश "प्रतिक्रिया" कहा जाता है, भले ही इसे क्लाइंट से पूछने से पहले भेजा जाता है। क्लाइंट स्वचालित रूप से अपने कैश में सर्वर पुश प्रतिक्रिया के माध्यम से भेजी गई फ़ाइल संग्रहीत करता है। फ़ाइल के लिए एक बाद का अनुरोध तुरंत कैश से सर्वर के लिए एक गोल यात्रा के बिना पूरा किया जाता है।

यह वेब ब्राउज़र पर बाइनरी डेटा को धक्का देने का एक प्रभावी तरीका है। हिचकिचाहट यह है कि सर्वर पुश प्रतिक्रिया आने पर ब्राउज़र का दस्तावेज़ ऑब्जेक्ट मॉडल (DOM) अधिसूचित नहीं किया जाता है। ब्राउजर केवल यह पता लगाता है कि डेटा इसके कैश में है जब यह इसके लिए अनुरोध करता है। हम इस समस्या को निम्नलिखित तरीके से काम कर सकते हैं। सर्वर पुश के साथ बाइनरी डेटा भेजने के तुरंत बाद, सर्वर क्लाइंट को एसएसई भेजता है ताकि यह सूचित किया जा सके कि डेटा को उसके कैश में धक्का दिया गया है। अब ग्राहक इसका अनुरोध करके डेटा को अपने कैश से पुनर्प्राप्त कर सकता है।

लेकिन जब तक आप एसएसई का उपयोग कर रहे हैं, तो एसएसई के माध्यम से फ़ाइल को पहली जगह क्यों न भेजें? क्योंकि यदि आप बाइनरी डेटा से निपट रहे हैं, तो आप छोटे फ़ाइल आकार से लाभ उठा सकते हैं जो सर्वर पुश आपको प्राप्त करने की अनुमति देता है। एक छोटे JSON संदेश के लिए, सर्वर पुश का उपयोग करने के लिए यह समझ में नहीं आता है। ऐसी परिस्थितियों में जहां आप द्विआधारी डेटा को दबा रहे हैं और आपको बैंडविड्थ को संरक्षित करना है, एसएसई अधिसूचना के बाद सर्वर पुश के माध्यम से डेटा भेजने पर विचार करें।

मतदान के विपरीत, इस दृष्टिकोण को ग्राहक से आवधिक अनुरोधों की आवश्यकता नहीं है। सर्वर जब भी चाहें सर्वर पुश प्रतिक्रिया भेज सकता है।

संबंधित मुद्दे