परिचय
Apache Hadoop में पाए जाने वाले कुछ कॉन्फ़िगरेशन गुण क्लाइंट पर सीधा प्रभाव डालते हैं, जैसे Apache HBase। उन गुणों में से एक को "dfs.datanode.max.xcievers" कहा जाता है, और यह HDFS सबप्रोजेक्ट से संबंधित है। यह सर्वर साइड थ्रेड्स की संख्या और - कुछ हद तक - डेटा कनेक्शन के लिए उपयोग किए जाने वाले सॉकेट को परिभाषित करता है। इस संख्या को बहुत कम सेट करने से आपके क्लस्टर के बढ़ने या उपयोग में वृद्धि के साथ समस्याएँ हो सकती हैं। यह पोस्ट आपको यह समझने में मदद करेगी कि क्लाइंट और सर्वर के बीच क्या होता है, और इस संपत्ति के लिए उचित संख्या कैसे निर्धारित करें।
समस्या
चूंकि एचबीएएस एचडीएफएस के अंदर अपनी जरूरत की हर चीज संग्रहित कर रहा है, इसलिए "dfs.datanode.max.xcievers" कॉन्फ़िगरेशन प्रॉपर्टी द्वारा लगाई गई कठोर ऊपरी सीमा के परिणामस्वरूप एचबीएएस के लिए बहुत कम संसाधन उपलब्ध हो सकते हैं, जो कनेक्शन के दोनों ओर IOException के रूप में प्रकट होता है। यहां HBase मेलिंग सूची से एक उदाहरण दिया गया है [1], जहां निम्नलिखित संदेश शुरू में रीजनसर्वर की ओर से लॉग किए गए थे:
2008-11-11 19:55:52,451 INFO org.apache.hadoop.dfs.DFSClient: में अपवाद createBlockOutputStream java.io.IOException:स्ट्रीम से नहीं पढ़ा जा सका
2008-11-11 19:55:52,451 INFO org.apache.hadoop.dfs.DFSClient: ब्लॉक को छोड़ना blk_-5467014108758633036_595771
2008-11- 11 19:55:58,455 WARN org.apache.hadoop.dfs.DFSClient: DataStreamer अपवाद:java.io.IOException:नया ब्लॉक बनाने में असमर्थ।
2008-11-11 19:55:58,455 WARN org.apache .hadoop.dfs.DFSClient:ब्लॉक blk_-5467014108758633036_595771 खराब डेटानोड के लिए त्रुटि रिकवरी . जबरदस्ती सर्वर बंद करना
Hadoop DataNode लॉग के साथ इसे सहसंबंधित करने से निम्नलिखित प्रविष्टि का पता चला:
ERROR org.apache.hadoop.dfs.DataNode: DatanodeRegistration(10.10.10.53:50010,storageID=DS-1570581820-10.10.10.53-50010-1224117842339,infoPort=50075, ipcPort=50020):DataXceiver:java.io.IOException: xceiverCount 258 समवर्ती xcivers 256 की सीमा से अधिक है
इस उदाहरण में, DataNodes के लिए "dfs.datanode.max.xcievers" के निम्न मान के कारण संपूर्ण क्षेत्र सर्वर बंद हो गया। यह वाकई बहुत खराब स्थिति है। दुर्भाग्य से, कोई कठोर नियम नहीं है जो बताता है कि आवश्यक सीमा की गणना कैसे करें। आमतौर पर यह सलाह दी जाती है कि संख्या को डिफ़ॉल्ट 256 से बढ़ाकर 4096 कर दें (देखें [1], [2], [3], [4], और [5] संदर्भ के लिए)। यह इस गुण को सभी DataNodes की hdfs-site.xml फ़ाइल में जोड़कर किया जाता है (ध्यान दें कि यह गलत वर्तनी है):
ध्यान दें:कॉन्फ़िगरेशन फ़ाइल में यह परिवर्तन करने के बाद आपको अपने DataNodes को पुनरारंभ करना होगा।
इससे उपरोक्त समस्या में मदद मिलनी चाहिए, लेकिन आप अभी भी इस बारे में अधिक जानना चाहेंगे कि यह सब एक साथ कैसे चलता है, और इन संसाधनों के साथ HBase क्या कर रहा है। हम इस पोस्ट के शेष भाग में इस पर चर्चा करेंगे। लेकिन ऐसा करने से पहले, हमें इस बारे में स्पष्ट होना चाहिए कि आप इस संख्या को बहुत अधिक क्यों नहीं सेट कर सकते हैं, जैसे कि 64K और इसके साथ किया जाना चाहिए।
ऊपरी सीमा का एक कारण है, और यह दुगना है:सबसे पहले, धागे को अपने स्वयं के ढेर की आवश्यकता होती है, जिसका अर्थ है कि वे स्मृति पर कब्जा कर लेते हैं। वर्तमान सर्वरों के लिए इसका अर्थ डिफ़ॉल्ट रूप से 1MB प्रति थ्रेड[6] है। दूसरे शब्दों में, यदि आप सभी 4096 DataXceiver थ्रेड्स का उपयोग करते हैं, तो आपको उन्हें समायोजित करने के लिए लगभग 4GB हीप की आवश्यकता होगी। यह उस स्थान में कटौती करता है जिसे आपने मेमस्टोर और ब्लॉक कैश के लिए आवंटित किया है, साथ ही साथ JVM के अन्य सभी चलती भागों में भी। सबसे खराब स्थिति में, आप आउटऑफमेमरी अपवाद में भाग सकते हैं, और क्षेत्र सर्वर प्रक्रिया टोस्ट है। आप इस गुण को एक उचित उच्च संख्या पर सेट करना चाहते हैं, लेकिन बहुत अधिक भी नहीं।
दूसरा, इन कई थ्रेड्स के सक्रिय होने से आप देखेंगे कि आपका सीपीयू तेजी से लोड होता जा रहा है। सभी समवर्ती कार्यों को संभालने के लिए कई संदर्भ स्विच हो रहे होंगे, जो वास्तविक कार्य के लिए संसाधनों को छीन लेते हैं। स्मृति के बारे में चिंताओं के साथ, आप चाहते हैं कि थ्रेड्स की संख्या असीमित रूप से न बढ़े, लेकिन एक उचित ऊपरी सीमा प्रदान करें - और यही "dfs.datanode.max.xcievers" के लिए है।
Hadoop फ़ाइल सिस्टम विवरण
क्लाइंट साइड से, एचडीएफएस लाइब्रेरी पथ नामक अमूर्तता प्रदान कर रही है। यह वर्ग Hadoop द्वारा समर्थित फ़ाइल सिस्टम में एक फ़ाइल का प्रतिनिधित्व करता है, जिसे FileSystem वर्ग द्वारा दर्शाया जाता है। सार फाइलसिस्टम वर्ग के कुछ ठोस कार्यान्वयन हैं, जिनमें से एक डिस्ट्रीब्यूटेडफाइल सिस्टम है, जो एचडीएफएस का प्रतिनिधित्व करता है। बदले में यह वर्ग वास्तविक DFSClient वर्ग को लपेटता है जो दूरस्थ सर्वरों, यानी NameNode और कई DataNodes के साथ सभी इंटरैक्शन को संभालता है।
जब कोई क्लाइंट, जैसे HBase, एक फ़ाइल खोलता है, तो वह ऐसा करता है, उदाहरण के लिए, FileSystem वर्ग के ओपन () या क्रिएट () विधियों को कॉल करके, यहाँ सबसे सरल अवतार
public DFSInputStream open(String src) IOException फेंकता है
public FSDataOutputStream create(Path f) IOException फेंकता हैपी>
लौटाए गए स्ट्रीम इंस्टेंस को सर्वर-साइड सॉकेट और थ्रेड की आवश्यकता होती है, जिसका उपयोग डेटा के ब्लॉक को पढ़ने और लिखने के लिए किया जाता है। वे क्लाइंट और सर्वर के बीच डेटा का आदान-प्रदान करने के लिए अनुबंध का हिस्सा बनते हैं। ध्यान दें कि विभिन्न मशीनों के बीच अन्य, आरपीसी-आधारित प्रोटोकॉल उपयोग में हैं, लेकिन इस चर्चा के उद्देश्य से उन्हें अनदेखा किया जा सकता है।
लौटाया गया स्ट्रीम इंस्टेंस एक विशेष DFSOutputStream या DFSInputStream वर्ग है, जो यह पता लगाने के लिए NameNode के साथ सभी इंटरैक्शन को संभालता है कि ब्लॉक की प्रतियां कहां रहती हैं, और डेटा संचार प्रति ब्लॉक प्रति DataNode।
सर्वर साइड पर, DataNode DataXceiverServer का एक उदाहरण लपेटता है, जो वास्तविक वर्ग है जो उपरोक्त कॉन्फ़िगरेशन कुंजी को पढ़ता है और सीमा पार होने पर उपरोक्त अपवाद भी फेंकता है।
जब DataNode प्रारंभ होता है, तो यह एक थ्रेड समूह बनाता है और उल्लिखित DataXceiverServer उदाहरण को इस प्रकार प्रारंभ करता है:
this.threadGroup =new ThreadGroup(“dataXceiverServer”);
this.dataXceiverServer =new Daemon( थ्रेडग्रुप,
नया डेटाXceiverServer(ss, conf, this));
this.threadGroup.setDaemon(true); // खाली होने पर स्वतः नष्ट हो जाता है
ध्यान दें कि DataXceiverServer थ्रेड पहले से ही थ्रेड समूह का एक स्थान ले रहा है। इस समूह में वर्तमान में सक्रिय थ्रेड्स की संख्या को पुनः प्राप्त करने के लिए DataNode में यह आंतरिक वर्ग भी है:
/** प्रति नोड समवर्ती xceivers की संख्या। */
int getXceiverCount() {
return threadGroup ==null ? 0 :threadGroup.activeCount();
}
क्लाइंट द्वारा शुरू किए गए पढ़ने और लिखने के ब्लॉक, कनेक्शन बनाने का कारण बनते हैं, जो DataXceiverServer थ्रेड द्वारा एक DataXceiver उदाहरण में लपेटा जाता है। इस हैंड ऑफ के दौरान, उपरोक्त थ्रेड समूह में एक थ्रेड बनाया और पंजीकृत किया जाता है। तो प्रत्येक सक्रिय पढ़ने और लिखने के संचालन के लिए सर्वर की तरफ एक नया धागा ट्रैक किया जाता है। यदि समूह में थ्रेड्स की संख्या कॉन्फ़िगर की गई अधिकतम से अधिक है, तो उक्त अपवाद को फेंक दिया जाता है और डेटानोड के लॉग में दर्ज किया जाता है:
if (curXceiverCount> dataXceiverServer.maxXceiverCount) {
नया IOException फेंकें ("xceiverCount" + curXceiverCount
+ ” समवर्ती xcievers की सीमा से अधिक है ”
+ dataXceiverServer.maxXceiverCount);
}
ग्राहकों के लिए निहितार्थ
अब, प्रश्न यह है कि क्लाइंट पढ़ने और लिखने का सर्वर साइड थ्रेड्स से क्या संबंध है। इससे पहले कि हम विवरण में जाएं, आइए डिबग जानकारी का उपयोग करें जिसे डेटाएक्सीवर वर्ग लॉग करता है जब इसे बनाया और बंद किया जाता है
LOG.debug(“सक्रिय कनेक्शनों की संख्या है:” + datanode.getXceiverCount());
…
LOG.debug(datanode.dnRegistration + “:सक्रिय कनेक्शन की संख्या है:” + datanode.getXceiverCount());
और HBase की शुरुआत के दौरान मॉनिटर करें कि DataNode पर क्या लॉग किया गया है। सादगी के लिए यह एक एकल DataNode और RegionServer उदाहरण के साथ एक छद्म वितरित सेटअप पर किया जाता है। निम्नलिखित रीजनसर्वर के स्थिति पृष्ठ के शीर्ष को दिखाता है।
महत्वपूर्ण हिस्सा "मैट्रिक्स" अनुभाग में है, जहां यह "स्टोरफाइल्स =22" कहता है। इसलिए, यह मानते हुए कि HBase के पास संभालने के लिए कम से कम कई फाइलें हैं, साथ ही राइट-फॉरवर्ड लॉग के लिए कुछ अतिरिक्त फाइलें हैं, हमें उपरोक्त लॉग संदेश स्थिति को देखना चाहिए कि हमारे पास कम से कम 22 "सक्रिय कनेक्शन" हैं। आइए HBase शुरू करें और DataNode और RegionServer लॉग फाइलों की जांच करें:
कमांड लाइन:
$ bin/start-hbase.sh
…
DataNode Log:
2012-03-05 13:01:35,309 DEBUG org.apache.hadoop.hdfs.server.datanode. DataNode:सक्रिय कनेक्शन की संख्या है:1
2012-03-05 13:01:35,315 DEBUG org.apache.hadoop.hdfs.server.datanode.DataNode:DatanodeRegistration(127.0.0.1:50010, storageID=DS- 1423642448-10.0.0.64-50010-1321352233772, infoPort=50075, ipcPort=50020):सक्रिय कनेक्शनों की संख्या है:2
12/03/05 13:01:35 INFO Regionserver.MemStoreFlusher:GlobalMemStoreLimit=396.7m, GlobalMemStoreLimitLowMark=347.1m, maxHeap=991.7m
12/03/05 13:01:39 जानकारी http.HttpServer:webServer.getConnectors()[0].getLocalPort() द्वारा लौटाया गया पोर्ट ओपन से पहले() है -1 . श्रोता को 60030 को खोलना
2012-03-05 13:01:40,003 DEBUG org.apache.hadoop.hdfs.server.datanode.DataNode:सक्रिय कनेक्शन की संख्या है:1
12/03/05 13:01:40 INFO Regionserver.HRegionServer:क्षेत्र खोलने का अनुरोध प्राप्त हुआ:-ROOT-,0.70236052
2012-03-05 13:01:40,882 DEBUG org.apache.hadoop.hdfs.server.datanode.DataNode :सक्रिय कनेक्शन की संख्या है:3
2012-03-05 13:01:40,884 DEBUG org.apache.hadoop.hdfs.server.datanode.DataNode:DatanodeRegistration(127.0.0.1:50010, storageID=DS-1423642448 -10.0.0.64-50010-1321352233772, infoPort =50075, ipcPort =50020):सक्रिय कनेक्शन की संख्या है:4
2012-03-05 13:01:40,888 DEBUG org.apache.hadoop.hdfs.server। datanode.DataNode:सक्रिय कनेक्शनों की संख्या है:3
…
12/03/05 13:01:40 INFO Regionserver.HRegion:ऑनलाइन -रूट-,0.70236052; अगला अनुक्रम =63083
2012-03-05 13:01:40,982 डीबग org.apache.hadoop.hdfs.server.datanode.DataNode:सक्रिय कनेक्शन की संख्या है:3
2012-03-05 13 :01:40,983 DEBUG org.apache.hadoop.hdfs.server.datanode.DataNode:DatanodeRegistration(127.0.0.1:50010, storageID=DS-1423642448-10.0.0.64-50010-1321352233772, infoPort=50075, ipcPort=50020):सक्रिय कनेक्शनों की संख्या है:4
…
12/03/05 13:01:41 INFO Regionserver.HRegionServer:क्षेत्र खोलने का अनुरोध प्राप्त हुआ:.META.,1.1028785192
2012-03 -05 13:01:41,026 डीबग org.apache.hadoop.hdfs.server.datanode.DataNode:सक्रिय कनेक्शन की संख्या है:3
2012-03-05 13:01:41,027 डीबग org.apache.hadoop। एचडीएफएस। …
12/03/05 13:01:41 जानकारी क्षेत्रसर्वर। क्षेत्र:ऑनलाइन .META।, 1.1028785192; अगला अनुक्रम =63082
2012-03-05 13:01:41,109 DEBUG org.apache.hadoop.hdfs.server.datanode.DataNode:सक्रिय कनेक्शन की संख्या है:3
2012-03-05 13 :01:41,114 डीबग org.apache.hadoop.hdfs.server.datanode.DataNode:सक्रिय कनेक्शन की संख्या है:4
2012-03-05 13:01:41,117 डीबग org.apache.hadoop.hdfs.server .datanode.DataNode:सक्रिय कनेक्शनों की संख्या है:5
12/03/05 13:01:41 INFO Regionserver.HRegionServer:16 क्षेत्रों को खोलने का अनुरोध प्राप्त हुआ
12/03/05 13 :01:41 INFO Regionserver.HRegionServer:क्षेत्र खोलने का अनुरोध प्राप्त हुआ:उपयोगकर्ता तालिका,,1330944810191.62a312d67981c86c42b6bc02e6ec7e3f। 1330944810191.90d287473fe223f0ddc137020efda25d.
…
2012-03-05 13:01:41,246 DEBUG org.apache.hadoop.hdfs.server.datanode. DataNode:सक्रिय कनेक्शन की संख्या है:6
2012-03-05 13:01:41,248 DEBUG org.apache.hadoop.hdfs.server.datanode.DataNode:सक्रिय कनेक्शन की संख्या है:7
…
2012-03-05 13:01:41,257 DEBUG org.apache.hadoop.hdfs.server.datanode.DataNode:DatanodeRegistration(127.0.0.1:50010, storageID=DS-1423642448-10.0.0.64-50010-1321352233772 , infoPort=50075, ipcPort=50020):सक्रिय कनेक्शनों की संख्या है:10
2012-03-05 13:01:41,257 DEBUG org.apache.hadoop.hdfs.server.datanode.DataNode:DatanodeRegistration(127.0.0.1)। 0.1:50010, स्टोरेजआईडी=डीएस-1423642448-10.0.0.64-50010-1321352233772, इन्फोपोर्ट=50075, आईपीसीपोर्ट=50020):सक्रिय कनेक्शनों की संख्या है:9
…
12/03/05 13:01:41 INFO Regionserver.HRegion:ऑनलाइन यूजरटेबल, यूजर1120311784,1330944810191.90d287473fe223f0ddc137020efda25d।; अगला अनुक्रम आईडी=62917
12/03/05 13:01:41 जानकारी क्षेत्रसर्वर। क्षेत्र:ऑनलाइन उपयोगकर्ता तालिका,1330944810191.62a312d67981c86c42b6bc02e6ec7e3f।; अगला अनुक्रम आईडी=62916
…
12/03/05 13:01:41 जानकारी क्षेत्रसर्वर। क्षेत्र:ऑनलाइन उपयोगकर्ता योग्य, उपयोगकर्ता1361265841,1330944811370.80663fcf291e3ce00080599964f406ba।; अगला सीक्वेंसिड=62919
2012-03-05 13:01:41,474 DEBUG org.apache.hadoop.hdfs.server.datanode.DataNode:सक्रिय कनेक्शन की संख्या है:6
2012-03-05 13 :01:41,491 डीबग org.apache.hadoop.hdfs.server.datanode.DataNode:सक्रिय कनेक्शन की संख्या है:7
2012-03-05 13:01:41,495 डीबग org.apache.hadoop.hdfs.server .datanode.DataNode:DatanodeRegistration(127.0.0.1:50010, storageID=DS-1423642448-10.0.0.64-50010-1321352233772, infoPort=50075, ipcPort=50020):सक्रिय कनेक्शन की संख्या है:8
2012-03 -05 13:01:41,508 DEBUG org.apache.hadoop.hdfs.server.datanode.DataNode:सक्रिय कनेक्शन की संख्या है:7
…
12/03/05 13:01:41 जानकारी क्षेत्रसर्वर .HRegion:ऑनलाइन उपयोगकर्ता तालिका, उपयोगकर्ता1964968041,1330944848231.dd89596e9129e1caa7e07f8a491c9734।; अगला सीक्वेंसिड=62920
2012-03-05 13:01:41,618 DEBUG org.apache.hadoop.hdfs.server.datanode.DataNode:सक्रिय कनेक्शन की संख्या है:6
2012-03-05 13 :01:41,621 DEBUG org.apache.hadoop.hdfs.server.datanode.DataNode:DatanodeRegistration(127.0.0.1:50010, storageID=DS-1423642448-10.0.0.64-50010-1321352233772, infoPort=50075, ipcPort=50020):सक्रिय कनेक्शन की संख्या है:7
…
2012-03-05 13:01:41,829 DEBUG org.apache.hadoop.hdfs.server.datanode.DataNode:DatanodeRegistration(127.0.0.1:50010, storageID =DS-1423642448-10.0.0.64-50010-1321352233772, infoPort=50075, ipcPort=50020):सक्रिय कनेक्शनों की संख्या है:7
12/03/05 13:01:41 INFO Regionserver.HRegion:ऑनलाइन यूजरटेबल ,user515290649,1330944849739.d23924dc9e9d5891f332c337977af83d।; अगला सीक्वेंसिड=62926
2012-03-05 13:01:41,832 DEBUG org.apache.hadoop.hdfs.server.datanode.DataNode:सक्रिय कनेक्शन की संख्या है:6
2012-03-05 13 :01:41,838 DEBUG org.apache.hadoop.hdfs.server.datanode.DataNode:DatanodeRegistration(127.0.0.1:50010, storageID=DS-1423642448-10.0.0.64-50010-1321352233772, infoPort=50075, ipcPort=50020):सक्रिय कनेक्शनों की संख्या है:7
12/03/05 13:01:41 INFO क्षेत्रसर्वर।HRक्षेत्र:ऑनलाइन उपयोगकर्ताटेबल,उपयोगकर्ता757669512,1330944850808.cd0d6f16d8ae9cf0c9277f5d6c6c6b9f।; अगला सीक्वेंसिड=62929
…
2012-03-05 14:01:39,711 DEBUG org.apache.hadoop.hdfs.server.datanode.DataNode:सक्रिय कनेक्शन की संख्या है:4
2012 -03-05 22:48:41,945 DEBUG org.apache.hadoop.hdfs.server.datanode.DataNode:DatanodeRegistration(127.0.0.1:50010, storageID=DS-1423642448-10.0.0.64-50010-1321352233772, infoPort=50075, आईपीसीपोर्ट =50020):सक्रिय कनेक्शनों की संख्या है:4
12/03/05 22:48:41 जानकारी क्षेत्रसर्वर। क्षेत्र:ऑनलाइन उपयोगकर्ता योग्य, उपयोगकर्ता757669512,1330944850808.cd0d6f16d8ae9cf0c9277f5d6c6c6b9f।; अगला सीक्वेंसिड=62929
2012-03-05 22:48:41,963 डिबग संगठन -50010-1321352233772, infoPort=50075, ipcPort=50020):सक्रिय कनेक्शनों की संख्या है:4
आप देख सकते हैं कि एक के बाद एक क्षेत्र कैसे खुलते हैं, लेकिन आप यह भी देख सकते हैं कि सक्रिय कनेक्शनों की संख्या कभी भी 22 तक नहीं चढ़ती है - यह मुश्किल से 10 तक भी पहुंचती है। ऐसा क्यों है? इसे बेहतर ढंग से समझने के लिए, हमें यह देखना होगा कि HDFS में फ़ाइलें सर्वर-साइड DataXceiver के उदाहरण के लिए कैसे मैप करती हैं - और वे वास्तविक थ्रेड्स का प्रतिनिधित्व करती हैं।
Hadoop डीप डाइव
उपरोक्त DFSInputStream और DFSOutputStream वास्तव में सामान्य स्ट्रीम अवधारणाओं के आसपास हैं। वे क्लाइंट-सर्वर संचार को इन मानक जावा इंटरफेस में लपेटते हैं, जबकि आंतरिक रूप से ट्रैफ़िक को चयनित डेटानोड पर रूट करते हैं - जो कि वर्तमान ब्लॉक की एक प्रति रखता है। इसे आवश्यकतानुसार इन कनेक्शनों को खोलने और बंद करने की स्वतंत्रता है। जैसे ही क्लाइंट एचडीएफएस में एक फाइल पढ़ता है, क्लाइंट लाइब्रेरी क्लासेस ब्लॉक से ब्लॉक में पारदर्शी रूप से स्विच करती हैं, और इसलिए डेटानोड से डेटानोड में स्विच करती हैं, इसलिए इसे आवश्यकतानुसार कनेक्शन खोलना और बंद करना होगा।
DFSInputStream में DFSClient.BlockReader वर्ग का एक उदाहरण है, जो DataNode से कनेक्शन खोलता है। स्ट्रीम इंस्टेंस प्रत्येक कॉल को पढ़ने के लिए blockSeekTo() को कॉल करता है () जो कनेक्शन खोलने का ख्याल रखता है, अगर पहले से कोई नहीं है। एक बार जब एक ब्लॉक पूरी तरह से पढ़ जाता है तो कनेक्शन बंद हो जाता है। स्ट्रीम को बंद करने का प्रभाव बिल्कुल वैसा ही होता है।
DFSOutputStream में एक समान सहायक वर्ग, DataStreamer है। यह सर्वर से कनेक्शन को ट्रैक करता है, जो कि nextBlockOutputStream() विधि द्वारा शुरू किया जाता है। इसमें और भी आंतरिक वर्ग हैं जो ब्लॉक डेटा को लिखने में मदद करते हैं, जिन्हें हम यहां संक्षिप्तता के लिए छोड़ देते हैं।
ब्लॉक लिखने और पढ़ने दोनों को सर्वर-साइड पर सॉकेट और इंटरमीडिएट डेटा रखने के लिए एक थ्रेड की आवश्यकता होती है, जिसे DataXceiver इंस्टेंस में लपेटा जाता है। आपका क्लाइंट क्या कर रहा है, इस पर निर्भर करते हुए, आप देखेंगे कि कनेक्शन की संख्या HDFS में वर्तमान में एक्सेस की गई फ़ाइलों की संख्या के आसपास उतार-चढ़ाव करती है।
ऊपर दिए गए HBase पहेली पर वापस जाएं:शुरुआत के दौरान आपको 22 (और अधिक) कनेक्शन नहीं दिखाई देने का कारण यह है कि जब क्षेत्र खुलते हैं, तो केवल आवश्यक डेटा HFile का जानकारी ब्लॉक होता है। प्रत्येक फ़ाइल के बारे में महत्वपूर्ण विवरण प्राप्त करने के लिए इस ब्लॉक को पढ़ा जाता है, लेकिन फिर बंद कर दिया जाता है। इसका मतलब यह है कि सर्वर-साइड संसाधन त्वरित उत्तराधिकार में जारी किया जाता है। शेष चार कनेक्शन निर्धारित करना कठिन है। आप DataNode पर सभी थ्रेड्स को डंप करने के लिए JStack का उपयोग कर सकते हैं, जो इस उदाहरण में यह प्रविष्टि दिखाता है:
“DataXceiver for client /127.0.0.1:64281 [sending Block blk_5532741233443227208_4201]” daemon prio=5 tid=7fb96481d000 nid=0x1178b4000 रन करने योग्य [1178b3000]
java.lang.Thread.State:RUNNABLE
…
“DataXceiver for client /127.0.0.1:64172 [Receive Block blk_-2005512129579433420_4199 क्लाइंट=DFSClient_hb_rs_10.0.0.29 ,60020,1330984111693_1330984118810]” डेमन प्रियो=5 टीआईडी=7fb966109000 एनआईडी=0x1169cb000 रननेबल [1169ca000]
java.lang.Thread.State:RUNNABLE
…
ये केवल DataXceiver प्रविष्टियां हैं (इस उदाहरण में), इसलिए थ्रेड समूह में गिनती थोड़ी भ्रामक है। याद रखें कि DataXceiverServer डेमॉन थ्रेड पहले से ही एक अतिरिक्त प्रविष्टि के लिए खाता है, जो तीन सक्रिय कनेक्शन के लिए उपरोक्त दो खातों के साथ संयुक्त है - जिसका वास्तव में तीन सक्रिय थ्रेड्स का अर्थ है। इसके बजाय लॉग चार बताता है, यह है कि यह एक सक्रिय थ्रेड से गिनती लॉग करता है जो समाप्त होने वाला है। इसलिए, चार की गिनती लॉग होने के तुरंत बाद, यह वास्तव में एक कम है, यानी तीन और इसलिए सक्रिय थ्रेड्स की हमारी हेड काउंट से मेल खाती है।
यह भी ध्यान दें कि आंतरिक सहायक वर्ग, जैसे कि PacketResponder सक्रिय होने के दौरान समूह में एक और थ्रेड पर कब्जा कर लेता है। JStack आउटपुट उस तथ्य को इंगित करता है, थ्रेड को इस प्रकार सूचीबद्ध करता है:
“PacketResponder 0 for Block blk_-2005512129579433420_4199” daemon prio=5 tid=7fb96384d000 nid=0x116ace000 Object.wait में () [116acd000]
java.lang.Thread.State:TIMED_WAITING (ऑब्जेक्ट मॉनिटर पर)
java.lang.Object.wait(Native Method)
at org.apache.hadoop पर। hdfs.server.datanode.BlockReceiver$PacketResponder \
.lastDataNodeRun(BlockReceiver.java:779)
- लॉक (एक org.apache.hadoop.hdfs.server.datanode.BlockReceiver$PacketResponder)
org.apache.hadoop.hdfs.server.datanode.BlockReceiver$PacketResponder.run(BlockReceiver.java:870)
java.lang.Thread.run(Thread.java:680)
यह थ्रेड वर्तमान में TIMED_WAITING स्थिति में है और इसे सक्रिय नहीं माना जाता है। यही कारण है कि DataXceiver लॉग स्टेटमेंट द्वारा उत्सर्जित काउंट में इस तरह के थ्रेड्स शामिल नहीं हैं। यदि क्लाइंट द्वारा डेटा भेजने के कारण वे सक्रिय हो जाते हैं, तो सक्रिय थ्रेड काउंट फिर से बढ़ जाएगा। एक और बात ध्यान देने योग्य है कि इस थ्रेड को क्लाइंट और सर्वर के बीच एक अलग कनेक्शन, या सॉकेट की आवश्यकता नहीं है। पैकेट रेस्पॉन्डर ब्लॉक डेटा प्राप्त करने और राइट पाइपलाइन में अगले डेटानोड पर स्ट्रीम करने के लिए सर्वर साइड पर सिर्फ एक थ्रेड है।
Hadoop fsck कमांड में यह रिपोर्ट करने का विकल्प भी होता है कि वर्तमान में कौन सी फाइलें लिखने के लिए खुली हैं:
$hadoop fsck /hbase -openforwrite
FSCK लार्सजॉर्ज द्वारा /10.0.0.29 से पाथ / के लिए शुरू किया गया सोम मार्च 05 22:59:47 सीईटी 2012 पर एचबेस ………………………………..स्थिति:स्वस्थ
कुल आकार: 2088783626 B
कुल dirs: 54
कुल फ़ाइलें: 45
…
यह तुरंत एक अधिकृत सर्वर-साइड थ्रेड से संबंधित नहीं है, क्योंकि ये ब्लॉक आईडी द्वारा आवंटित किए जाते हैं। लेकिन आप इससे अंदाजा लगा सकते हैं कि लिखने के लिए एक खुला खंड है। Hadoop कमांड के पास वास्तविक फाइलों को प्रिंट करने के लिए अतिरिक्त विकल्प हैं और उनमें शामिल आईडी को ब्लॉक करें:
$hadoop fsck /hbase -files -blocks
FSCK को लार्सजॉर्ज द्वारा /10.0.0.29 से शुरू किया गया मंगल 06 मार्च 10:39:50 सीईटी 2012 पर पथ / एचबेस
…
/hbase/.META./1028785192/.tmp
/hbase/.META./1028785192/info
/hbase/.META./1028785192/info/4027596949915293355 36517 बाइट्स, 1 ब्लॉक: ठीक है
0. blk_5532741233443227208_4201 लेन=36517 उत्तर=1
…
स्थिति:स्वस्थ
कुल आकार: 2088788703 B
कुल dirs : 54
कुल फ़ाइलें: 45 (वर्तमान में लिखी जा रही फ़ाइलें:1)
कुल ब्लॉक (सत्यापित): 64 (औसत ब्लॉक आकार 32637323 बी) (कुल खुले फ़ाइल ब्लॉक (मान्य नहीं):1)
न्यूनतम रूप से दोहराए गए ब्लॉक: 64 (100.0%)
…
इससे आपको दो चीज़ें मिलती हैं। सबसे पहले, सारांश बताता है कि कमांड के चलने के समय एक खुला फ़ाइल ब्लॉक है - ऊपर "-openforwrite" विकल्प द्वारा रिपोर्ट की गई गणना से मेल खाता है। दूसरे, प्रत्येक फ़ाइल के आगे ब्लॉक की सूची आपको थ्रेड नाम को उस फ़ाइल से मिलाने देती है जिसमें ब्लॉक का उपयोग किया जा रहा है। इस उदाहरण में आईडी "blk_5532741233443227208_4201" वाला ब्लॉक सर्वर से क्लाइंट को भेजा जाता है, यहां एक रीजनसर्वर है। यह ब्लॉक HBase .META के अंतर्गत आता है। तालिका, जैसा कि Hadoop fsck कमांड के आउटपुट द्वारा दिखाया गया है। JStack और fsck का संयोजन lsof ("खुली फाइलों को सूचीबद्ध करने के लिए लिनक्स कमांड लाइन पर एक उपकरण") के लिए एक गरीब आदमी के प्रतिस्थापन के रूप में काम कर सकता है।
JStack यह भी रिपोर्ट करता है कि ब्लॉक आईडी "blk_-20055129579433420_4199" के लिए एक पैकेट रेस्पॉन्डर के साथ एक डेटाएक्ससीवर थ्रेड है, लेकिन यह आईडी fsck द्वारा रिपोर्ट किए गए ब्लॉक की सूची से गायब है। ऐसा इसलिए है क्योंकि ब्लॉक अभी समाप्त नहीं हुआ है और इसलिए पाठकों के लिए उपलब्ध नहीं है। दूसरे शब्दों में, Hadoop fsck केवल पूर्ण (या समन्वयित [7] [8], Hadoop संस्करण के लिए जो इस सुविधा का समर्थन करता है) ब्लॉक पर रिपोर्ट करता है।
HBase पर वापस जाएं
सभी क्षेत्रों को खोलने के लिए सर्वर पर उतने संसाधनों की आवश्यकता नहीं है जितनी आपने अपेक्षा की होगी। यदि आप संपूर्ण HBase तालिका को स्कैन करते हैं, तो आप HBase को सभी HFiles में सभी ब्लॉक पढ़ने के लिए बाध्य करते हैं:
HBase शेल:
hbase(main):003:0> 'usertable' स्कैन करें
…
1000000 1460.3120 सेकंड में पंक्ति(पंक्तियाँ)
DataNode Log:
2012-03-05 14:42:20,580 DEBUG org.apache.hadoop.hdfs.server.datanode. DataNode:सक्रिय कनेक्शन की संख्या है:6
2012-03-05 14:43:23,293 DEBUG org.apache.hadoop.hdfs.server.datanode.DataNode:सक्रिय कनेक्शन की संख्या है:7
2012 -03-05 14:43:23,299 DEBUG org.apache.hadoop.hdfs.server.datanode.DataNode:DatanodeRegistration(127.0.0.1:50010, storageID=DS-1423642448-10.0.0.64-50010-1321352233772, infoPort=50075, ipcPort=50020):सक्रिय कनेक्शनों की संख्या है:8
…
2012-03-05 14:49:24,332 DEBUG org.apache.hadoop.hdfs.server.datanode.DataNode:DatanodeRegistration(127.0.0.1)। 0.1:50010, स्टोरेजआईडी=DS-1423642448-10.0.0.64-50010-1321352233772, infoPort=50075, ipcPort=50020):सक्रिय कनेक्शनों की संख्या है:11
2012-03-05 14:49:24,332 DEBUG org .apache.hadoop.hdfs.server.datanode.DataNode:सक्रिय कनेक्शन की संख्या है:10
2012-03-05 14:49:59,987 DEBUG org.apache.hadoop.hdfs.server.datanod e.DataNode:सक्रिय कनेक्शन की संख्या है:11
2012-03-05 14:51:12,603 DEBUG org.apache.hadoop.hdfs.server.datanode.DataNode:DatanodeRegistration(127.0.0.1:50010, storageID=DS-1423642448-10.0.0.64-50010-1321352233772, infoPort =50075, ipcPort =50020):सक्रिय कनेक्शन की संख्या है:12
2012-03-05 14:51:12,605 DEBUG org.apache.hadoop.hdfs .server.datanode.DataNode:सक्रिय कनेक्शन की संख्या है:11
2012-03-05 14:51:46,473 DEBUG org.apache.hadoop.hdfs.server.datanode.DataNode:सक्रिय कनेक्शन की संख्या है:12
…
2012-03-05 14:56:59,420 DEBUG org.apache.hadoop.hdfs.server.datanode.DataNode:सक्रिय कनेक्शन की संख्या है:15
2012-03-05 14:57:31,722 DEBUG org.apache.hadoop.hdfs.server.datanode.DataNode:सक्रिय कनेक्शन की संख्या है:16
2012-03-05 14:58:24,909 DEBUG org.apache.hadoop.hdfs। server.datanode.DataNode:DatanodeRegistration(127.0.0.1:50010, storageID=DS-1423642448-10.0.0.64-50010-1321352233772, infoPort=50075, ipcPort=50020):अधिनियम की संख्या ive कनेक्शन है:17
2012-03-05 14:58:24,910 DEBUG org.apache.hadoop.hdfs.server.datanode.DataNode:सक्रिय कनेक्शन की संख्या है:16
…
2012-03-05 15:04:17,688 DEBUG org.apache.hadoop.hdfs.server.datanode.DataNode:सक्रिय कनेक्शन की संख्या है:21
2012-03-05 15:04:17,689 DEBUG org.apache .hadoop.hdfs.server.datanode.DataNode:DatanodeRegistration(127.0.0.1:50010, storageID=DS-1423642448-10.0.0.64-50010-1321352233772, infoPort=50075, ipcPort=50020):सक्रिय कनेक्शन की संख्या है:22
2012-03-05 15:04:54,545 DEBUG org.apache.hadoop.hdfs.server.datanode.DataNode:सक्रिय कनेक्शन की संख्या है:21
2012-03-05 15:05:55,901 डीबग org.apache.hadoop.hdfs.server.datanode.DataNode:DatanodeRegistration(127.0.0.1:50010, storageID=DS-1423642448-10.0.0.64-50010-1321352233772, infoPort=50075, ipcPort=50020):सक्रिय कनेक्शनों की संख्या है :22
2012-03-05 15:05:55,901 DEBUG org.apache.hadoop.hdfs.server.datanode.DataNode:सक्रिय कनेक्शन की संख्या है:21
सक्रिय कनेक्शनों की संख्या अब मायावी 22 तक पहुंच गई है। ध्यान दें कि इस गणना में पहले से ही सर्वर थ्रेड शामिल है, इसलिए HBase को संभाली जाने वाली फ़ाइलों की संख्या के आधार पर - हम अभी भी सैद्धांतिक अधिकतम पर विचार कर सकते हैं, जो कि हम थोड़ा कम हैं।
इस सबका क्या मतलब है?
तो, आपको कितने "xcievers (sic)" की आवश्यकता है? यह देखते हुए कि आप केवल HBase का उपयोग करते हैं, आप बस उपरोक्त "स्टोरफाइल्स" मीट्रिक (जो आपको गैंग्लिया या जेएमएक्स के माध्यम से भी मिलते हैं) की निगरानी कर सकते हैं और इंटरमीडिएट और राइट-फॉरवर्ड लॉग फ़ाइलों के लिए कुछ प्रतिशत जोड़ सकते हैं। यह गति में सिस्टम के लिए काम करना चाहिए। हालाँकि, यदि आप उस संख्या को एक निष्क्रिय, पूरी तरह से कॉम्पैक्ट सिस्टम पर निर्धारित करते हैं और मान लेते हैं कि यह अधिकतम है, तो आप नियमित मेमस्टोर फ्लश के दौरान अधिक स्टोर फ़ाइलों को जोड़ना शुरू करने के बाद, जैसे ही आप शुरू करते हैं, आपको यह संख्या बहुत कम हो सकती है। HBase तालिकाओं में डेटा जोड़ें। या यदि आप उसी क्लस्टर पर MapReduce का भी उपयोग करते हैं, तो Flume लॉग एकत्रीकरण, और इसी तरह। आपको उन अतिरिक्त फाइलों का हिसाब देना होगा, और इससे भी महत्वपूर्ण बात यह है कि पढ़ने और लिखने के लिए ब्लॉक खोलना होगा।
फिर से ध्यान दें कि इस पोस्ट में उदाहरण एकल डेटानोड का उपयोग कर रहे हैं, कुछ ऐसा जो आपके पास वास्तविक क्लस्टर पर नहीं होगा। इसके लिए, आपको स्टोर फ़ाइलों की कुल संख्या (HBase मीट्रिक के अनुसार) को आपके पास मौजूद DataNodes की संख्या से विभाजित करना होगा। यदि आपके पास, उदाहरण के लिए, 1000 की एक स्टोर फ़ाइल संख्या है, और आपके क्लस्टर में 10 डेटा नोड हैं, तो आपको प्रति DataNode 256 xceiver थ्रेड्स के डिफ़ॉल्ट के साथ ठीक होना चाहिए।
सबसे खराब स्थिति सभी सक्रिय पाठकों और लेखकों की संख्या होगी, यानी वे जो वर्तमान में डेटा भेज या प्राप्त कर रहे हैं। लेकिन चूंकि यह समय से पहले निर्धारित करना कठिन है, आप एक सभ्य रिजर्व में निर्माण पर विचार करना चाहेंगे। इसके अलावा, चूंकि लेखन प्रक्रिया को एक अतिरिक्त - हालांकि कम समय तक चलने वाला - थ्रेड (पैकेट रेस्पॉन्डर के लिए) की आवश्यकता होती है, इसलिए आपको उसके लिए भी हिसाब देना होगा। तो एक उचित, बल्कि सरलीकृत सूत्र हो सकता है:
यह सूत्र ध्यान में रखता है कि आपको एक सक्रिय लेखक के लिए लगभग दो धागे और एक सक्रिय पाठक के लिए दूसरे की आवश्यकता है। इसके बाद इसे सारांशित किया जाता है और DataNodes की संख्या से विभाजित किया जाता है, क्योंकि आपको प्रति DataNode "dfs.datanode.max.xcievers" निर्दिष्ट करना होता है।
If you loop back to the HBase RegionServer screenshot above, you saw that there were 22 store files. These are immutable and will only be read, or in other words occupy one thread only. For all memstores that are flushed to disk you need two threads – but only until they are fully written. The files are finalized and closed for good, cleaning up any thread in the process. So these come and go based on your flush frequency. Same goes for compactions, they will read N files and write them into a single new one, then finalize the new file. As for the write-ahead logs, these will occupy a thread once you have started to add data to any table. There is a log file per server, meaning that you can only have twice as many active threads for these files as you have RegionServers.
For a pure HBase setup (HBase plus its own HDFS, with no other user), we can estimate the number of needed DataXceiver’s with the following formula:
Since you will be hard pressed to determine the active number of store files, flushes, and so on, it might be better to estimate the theoretical maximum instead. This maximum value takes into account that you can only have a single flush and compaction active per region at any time. The maximum number of logs you can have active matches the number of RegionServers, leading us to this formula:
Obviously, the number of store files will increase over time, and the number of regions typically as well. Same for the numbers of servers, so keep in mind to adjust this number over time. In practice, you can add a buffer of, for example, 20%, as shown in the formula below – in an attempt to not force you to change the value too often.
On the other hand, if you keep the number of regions fixed per server[9], and rather split them manually, while adding new servers as you grow, you should be able to keep this configuration property stable for each server.
Final Advice &TL;DR
Here is the final formula you want to use:
It computes the maximum number of threads needed, based on your current HBase vitals (no. of store files, regions, and region servers). It also adds a fudge factor of 20% to give you room for growth. Keep an eye on the numbers on a regular basis and adjust the value as needed. You might want to use Nagios with appropriate checks to warn you when any of the vitals goes over a certain percentage of change.
Note:Please make sure you also adjust the number of file handles your process is allowed to use accordingly[10]. This affects the number of sockets you can use, and if that number is too low (default is often 1024), you will get connection issues first.
Finally, the engineering devil on one of your shoulders should already have started to snicker about how horribly non-Erlang-y this is, and how you should use an event driven approach, possibly using Akka with Scala[11] – if you want to stay within the JVM world. Bear in mind though that the clever developers in the community share the same thoughts and have already started to discuss various approaches[12][13].
Links:
- [1] http://old.nabble.com/Re%3A-xceiverCount-257-exceeds-the-limit-of-concurrent-xcievers-256-p20469958.html
- [2] http://ccgtech.blogspot.com/2010/02/hadoop-hdfs-deceived-by-xciever.html
- [3] https://issues.apache.org/jira/browse/HDFS-1861 “Rename dfs.datanode.max.xcievers and bump its default value”
- [4] https://issues.apache.org/jira/browse/HDFS-1866 “Document dfs.datanode.max.transfer.threads in hdfs-default.xml”
- [5] http://hbase.apache.org/book.html#dfs.datanode.max.xcievers
- [6] http://www.oracle.com/technetwork/java/hotspotfaq-138619.html#threads_oom
- [7] https://issues.apache.org/jira/browse/HDFS-200 “In HDFS, sync() not yet guarantees data available to the new readers”
- [8] https://issues.apache.org/jira/browse/HDFS-265 “Revisit append”
- [9] http://search-hadoop.com/m/CBBoV3z24H1 “HBase, mail # user – region size/count per regionserver”
- [10] http://hbase.apache.org/book.html#ulimit “ulimit and nproc”
- [11] http://akka.io/ “Akka”
- [12] https://issues.apache.org/jira/browse/HDFS-223 “Asynchronous IO Handling in Hadoop and HDFS”
- [13] https://issues.apache.org/jira/browse/HDFS-918 “Use single Selector and small thread pool to replace many instances of BlockSender for reads”