Apache में gzip कम्प्रेशन सक्षम होने पर सामग्री-लंबाई नहीं भेजी गई?


13

मैं वास्तव में इस अपाचे व्यवहार को समझने में कुछ मदद की सराहना करूंगा।

मैं एप्लिकेशन / json में iPhone उद्देश्य-सी ऐप से PHP में संचार कर रहा हूं। सर्वर पर Gzip संपीड़न सक्षम है, और क्लाइंट द्वारा अनुरोध किया गया है।

मेरे .htaccess से:

AddOutputFilterByType DEFLATE text/html text/plain text/xml application/x-httpd-php application/json

छोटे अनुरोधों के लिए, अपाचे 'सामग्री-लंबाई' हेडर सेट कर रहा है। उदाहरण के लिए (ये मान हेडर से ऑब्जेक्टिव-सी में आउटपुट हैं):

Connection = "Keep-Alive";
"Content-Encoding" = gzip;
"Content-Length" = 185;     <-------------
"Content-Type" = "application/json";
Date = "Wed, 22 Sep 2010 12:20:27 GMT";
"Keep-Alive" = "timeout=3, max=149";
Server = Apache;
Vary = "Accept-Encoding";
"X-Powered-By" = "PHP/5.2.13";
"X-Uncompressed-Content-Length" = 217;

X- असम्पीडित-सामग्री-लंबाई एक हेडर है जिसे मैं असम्पीडित JSON स्ट्रिंग के आकार में जोड़ रहा हूँ।

जैसा कि आप देख सकते हैं, यह अनुरोध बहुत छोटा है (217 बाइट्स)।

यहाँ एक बड़े अनुरोध (282888 बाइट्स) के शीर्ष लेख हैं:

Connection = "Keep-Alive";
"Content-Encoding" = gzip;
"Content-Type" = "application/json";
Date = "Wed, 22 Sep 2010 12:20:29 GMT";
"Keep-Alive" = "timeout=3, max=148";
Server = Apache;
"Transfer-Encoding" = Identity;
Vary = "Accept-Encoding";
"X-Powered-By" = "PHP/5.2.13";
"X-Uncompressed-Content-Length" = 282888;

ध्यान दें कि सामग्री-लंबाई नहीं दी गई है।

मेरे सवाल:

  1. अपाचे बड़े अनुरोध के लिए सामग्री-लंबाई क्यों नहीं भेजता है?
  2. क्या तथ्य यह है कि 'कंटेंड-एन्कोडिंग = गज़िप' का मतलब यह है कि गज़िप संपीड़न अभी भी बड़े अनुरोध पर काम कर रहा है, भले ही मैं आकार अंतर को सत्यापित नहीं कर सकता हूं?
  3. क्या उपयोगकर्ताओं को डेटा उपयोग की अधिक सटीक रिपोर्ट करने के लिए इन बड़े अनुरोधों के लिए वास्तविक सामग्री-लंबाई को शामिल करने के लिए मैं अपाचे प्राप्त कर सकता हूं?

इस ऐप का उपयोग उन डेटा योजनाओं पर किया जा सकता है जो महंगे हैं, इसलिए उपयोगकर्ता को वास्तविक उपयोग की रिपोर्ट करने की मेरी इच्छा है, न कि 30-70% फुलाया हुआ उपयोग (कुछ सौ अतिरिक्त केबी ज्यादा नहीं लग सकते हैं - लेकिन इन योजनाओं की लागत $ 1 के बीच हो सकती है) और $ 10 प्रति एमबी!)।

अग्रिम में धन्यवाद।

जवाबों:


14

मार्टिन Fjordvalds के अलावा जवाब:

Apache chunked एन्कोडिंग का उपयोग केवल तभी करता है जब संकुचित फ़ाइल आकार DeflateBufferSize से बड़ा हो। इस बफ़र के आकार को बढ़ाने से सर्वर को बड़ी फ़ाइलों के लिए भी एन्कोडिंग का उपयोग करने से रोका जा सकेगा, जिससे कंटेंट-लेंथ को इत्तला दे दी गई डेटा के लिए भी भेजा जा सकेगा।

अधिक जानकारी यहां उपलब्ध है: http://httpd.apache.org/docs/2.2/mod/mod_deflate.html#deflatebuffersize


अच्छा है। यह शायद इस समस्या को हल करने का सबसे तेज़ तरीका है। यदि किसी को उच्च स्तर के अनुकूलन की आवश्यकता है (उदाहरण के लिए कुछ अनुरोधों को न लें), तो एक मैनुअल समाधान के लिए मेरा उत्तर serverfault.com/a/183856/54957 देखें ।
विलियम डेनिस

7

लगता है कि अपाचे चोक हुई एन्कोडिंग कर रहा है, इसका मतलब यह है कि यह डेटा भेज सकता है क्योंकि यह gzipped होने के बजाय पूरी प्रतिक्रिया की प्रतीक्षा कर रहा है। यह काफी मानक अभ्यास है, मैं अपाचे के साथ पर्याप्त रूप से परिचित नहीं हूं यह कहने के लिए कि क्या इसे अक्षम किया जा सकता है, हालांकि।


जानकारी के लिए धन्यवाद, आपने मुझे सही दिशा में बताया, और मैंने इसे हल किया।
विलियम डेनिस

स्वीकार किए जाते हैं। हालांकि इस प्रश्न को पढ़ने वाले किसी के लिए - कृपया विस्तृत समाधान के लिए मेरा उत्तर पढ़ें। असल में, आप बफ़रिंग और मैन्युअल रूप से उत्तर को संपीड़ित करके चंकिंग (और शून्य सामग्री-लंबाई) से बच सकते हैं।
विलियम डेनिस

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

@redbmk उचित बिंदु, मैं सिर्फ कृतघ्न प्रतीत नहीं करना चाहता था। फिलिप वास्तव में इसके लिए एकदम सही सरल है, इसलिए मैंने उसका ओवर खान स्वीकार कर लिया है।
विलियम डेनिस

5

ठीक है, मैं इसे हल करने में कामयाब रहा। जैसा कि मार्टिन एफ सही ढंग से बताते हैं, अपाचे उत्तर को चकित कर रहा है इसलिए सामग्री का आकार ज्ञात नहीं है। कई लोगों के लिए यह वांछनीय है (पृष्ठ लोड तेजी से)। यह डाउनलोड प्रगति की रिपोर्ट नहीं कर पाने की लागत पर आता है।

मेरे जैसे उन लोगों के लिए जो वास्तव में डाउनलोड प्रगति की रिपोर्ट करना चाहते हैं, यदि आप अपाचे या पीएचपी के स्वचालित गज़िप समर्थन का उपयोग करते हैं, तो बहुत कम है जो आप कर सकते हैं। इसका समाधान मैन्युअल रूप से करना है। यह लगता है की तुलना में आसान है:

यदि आप पूरी फाइलें भेज रहे हैं, तो PHP में एक एकल चंक (सामग्री-लंबाई के साथ) को मजबूर करने के लिए यह एक बढ़िया उदाहरण है: http://www.php.net/manual/en/function.ob-start.php # 94,741

यदि आप उत्पन्न डेटा भेज रहे हैं, तो उपरोक्त नमूने की तरह, अपने डेटा को एन्कोड करने के लिए gzencode का उपयोग करें। एक पूर्व-आवश्यकता यह है कि आपके सभी आउटपुट डेटा को एक चर में संग्रहीत किया जाता है (आप इसे मदद करने के लिए ob_start का उपयोग कर सकते हैं यदि आपको बफर करने की आवश्यकता है, तो बफर की सामग्री प्राप्त करें)।

        // $replyBody is the entire contents of your reply

        header("Content-Type: application/json");  // or whatever yours is

        // checks if gzip is supported by client
        $pack = true;
        if(empty($_SERVER["HTTP_ACCEPT_ENCODING"]) || strpos($_SERVER["HTTP_ACCEPT_ENCODING"], 'gzip') === false)
        {
            $pack = false;
        }

        // if supported, gzips data
        if($pack) {
            header("Content-Encoding: gzip");
            $replyBody = gzencode($replyBody, 9, FORCE_GZIP);
        }

        // compressed or not, sets the Content-Length           
        header("Content-Length: " . mb_strlen($replyBody, 'latin1'));

        // outputs reply & exits
        echo $replyBody;
        exit;

और वोइला!

इसे स्वयं करने का एक और बड़ा लाभ यह है कि आप संपीड़न स्तर निर्धारित कर सकते हैं। यह मेरे मोबाइल एप्लिकेशन के लिए बहुत अच्छा है, क्योंकि मैं उच्चतम संपीड़न स्तर पर सेट कर सकता हूं (इसलिए मेरे उपयोगकर्ता डेटा के लिए कम भुगतान करते हैं!) - जबकि सर्वर शायद बेहतर सीपीयू / आकार के व्यापार के लिए एक मध्यम संपीड़न स्तर का उपयोग करता है। संपीड़न का स्तर कुछ ऐसा है जो मेरा मानना ​​है कि आप केवल तभी बदल सकते हैं जब आप httpd.conf (जो साझा होस्टिंग पर, मैं नहीं कर सकता) को संपादित कर सकता है।

इसलिए मैंने अपना DEFLATE .htaccess निर्देश सब कुछ के लिए रखा है, लेकिन मेरा आवेदन / json जवाब देता है जिसे मैं अब उपरोक्त तरीके से एन्कोड करता हूं।

धन्यवाद फिर से मार्टिन एफ, आपने मुझे इस समस्या को हल करने के लिए आवश्यक चिंगारी दी :)


1
संयोग से, JSON डेटा (भारी दोहराया कुंजियों के साथ) की बचत बहुत बड़ी है , एक मामले में 77% की कमी। यह $ 1 प्रति एमबी पर एक बड़ा सौदा है ...
विलियम डेनिस

1
आपको शायद strlen($replyBody)इसके बजाय बस का उपयोग करना चाहिए mb_strlen($replyBody, 'latin1')। सामग्री-लंबाई केवल बाइट्स की संख्या है (वर्ण नहीं), जो कि स्ट्रलेन () आपको देता है। Mb_strlen () का उपयोग करते हुए 'latin1' तरह के काम करता है क्योंकि latin1 अक्षर हमेशा 8 बिट्स के होते हैं, लेकिन इसमें उन बाइट्स के साथ समस्या हो सकती है जो बाइट्स का उत्पादन करते हैं जो कि मान्य latin1 वर्ण नहीं हैं।
20
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.