GRPC: जावा / स्काला में उच्च-थ्रूपुट क्लाइंट बनाते हैं


9

मेरे पास एक सेवा है जो संदेशों को काफी उच्च दर पर स्थानांतरित करती है।

वर्तमान में यह akka-tcp द्वारा परोसा जाता है और यह प्रति मिनट 3.5M संदेश बनाता है। मैंने grpc को एक कोशिश देने का फैसला किया। दुर्भाग्य से यह बहुत छोटे थ्रूपुट के परिणामस्वरूप हुआ: ~ 500k संदेश प्रति मिनट एक भी कम।

क्या आप कृपया इसे अनुकूलित करने की अनुशंसा कर सकते हैं?

मेरा सेटअप

हार्डवेयर : 32 कोर, 24 जीबी हीप।

grpc संस्करण : 1.25.0

संदेश प्रारूप और समापन बिंदु

संदेश मूल रूप से एक द्विआधारी बूँद है। ग्राहक 100K - 1M और एक ही अनुरोध (अतुल्यकालिक) में अधिक संदेश प्रवाहित करता है, सर्वर किसी भी चीज़ का जवाब नहीं देता है, ग्राहक एक नो-ऑप ऑब्जर्वर का उपयोग करता है

service MyService {
    rpc send (stream MyMessage) returns (stream DummyResponse);
}

message MyMessage {
    int64 someField = 1;
    bytes payload = 2;  //not huge
}

message DummyResponse {
}

समस्या: अक्का कार्यान्वयन की तुलना में संदेश की दर कम है। मैं कम CPU उपयोग का निरीक्षण करता हूं, इसलिए मुझे संदेह है कि grpc कॉल वास्तव में आंतरिक रूप से अवरुद्ध है क्योंकि यह अन्यथा कहता है। कॉलिंग onNext()वास्तव में तुरंत वापस नहीं आती है, लेकिन मेज पर जीसी भी है।

मैंने इस मुद्दे को कम करने के लिए अधिक प्रेषकों को स्पॉन करने की कोशिश की, लेकिन बहुत सुधार नहीं हुआ।

मेरे निष्कर्ष Grpc वास्तव में प्रत्येक संदेश पर एक 8KB बाइट बफर आवंटित करता है जब इसे क्रमबद्ध करता है। स्टैकट्रेस देखें:

java.lang.Thread.State: BLOCKED com (google पर ऑब्जेक्ट मॉनीटर पर) com.google.com। com। 105) io.grpc.internal.MessageFramer.writeToOutputStream (MessageFramer.java:274) पर io.grpc.internal.MessageFramer.writeKramownLengthUncompressed (MessageFramer.java:230) पर io.grpc.internet.in.in पर लॉग इन करें। :: 168) io.grpc.internal.MessageFramer.writePayload (MessageFramer.java:141) पर io.grpc.internal.AbstractStream.writeMessage (AbstractWream.java:53) पर io.grpc.internal.ForwardingClientStream.writeMessage फ़ॉरवर्ड करें। java: 37) io.grpc.internal.DelayedStream.writeMessage (DelayedStream.java:252) पर io.grpc.internal।Io.grpc.in.in. क्लाइंट पर ईमेल करें। (ForwardingClientCall.java:37) पर io.grpc.stub.ClientCalls $ CallToStreamObserverAdapter.onNext (ClientCalls.java:346)

सराहना के माध्यम से उच्च throughput grpc ग्राहकों के निर्माण पर सर्वोत्तम प्रथाओं के साथ कोई मदद।


क्या आप प्रोटोबॉफ़ का उपयोग कर रहे हैं? यह कोड पथ केवल तभी लिया जाना चाहिए जब InputStream MethodDescriptor.Marshaller.stream द्वारा वापस लौटा दिया गया हो () अयोग्य को लागू नहीं करता है। प्रोटोबुफ मार्शल ड्रेनेबल का समर्थन करता है। यदि आप Protobuf का उपयोग कर रहे हैं, तो क्या यह संभव है कि एक ClientInterceptor MethodDescriptor को बदल रहा है?
एरिक एंडरसन

@EricAnderson आपको प्रतिक्रिया के लिए धन्यवाद। मैंने ग्रेडल (com.google.protobuf: protoc: 3.10.1, io.grpc: protoc-gen-grpc-java: 1.25.0) और के साथ मानक प्रोटोबुक की कोशिश की scalapb। संभवतः यह स्टैकट्रेस वास्तव में स्केलपब-जनरेटेड कोड से था। मैंने स्केलपब से जुड़ी हर चीज को हटा दिया, लेकिन इसने बहुत अधिक प्रदर्शन करने में मदद नहीं की।
simpadjo

@EricAnderson मैंने अपनी समस्या हल की। आपको grpc के डेवलपर के रूप में पिंग करना। क्या मेरा जवाब समझ में आता है?
सिमडोज़ो

जवाबों:


4

मैंने ManagedChannelप्रति गंतव्य कई उदाहरण बनाकर समस्या हल की । लेखों के बावजूद कहा ManagedChannelजा सकता है कि पर्याप्त कनेक्शन स्वयं ही जा सकता है इसलिए एक उदाहरण पर्याप्त है जो मेरे मामले में सच नहीं है।

एक्का-टीसीपी कार्यान्वयन के साथ प्रदर्शन समानता में है।


1
ManagedChannel (अंतर्निहित LB नीतियों के साथ) प्रति बैकएंड एक से अधिक कनेक्शन का उपयोग नहीं करता है। इसलिए यदि आप कुछ बैकएंड के साथ उच्च-थ्रूपुट हैं, तो सभी बैकेंड के कनेक्शन को संतृप्त करना संभव है। कई चैनलों का उपयोग करने से उन मामलों में प्रदर्शन बढ़ सकता है।
एरिक एंडरसन

@EricAnderson धन्यवाद मेरे मामले में कई चैनलों ने एक बैकएंड नोड के लिए भी
स्पैनिंग

कम बैकएंड और उच्च बैंडविड्थ, अधिक संभावना है कि आपको कई चैनल चाहिए। तो "सिंगल बैकएंड" अधिक संभावना है कि अधिक चैनल सहायक होगा।
एरिक एंडरसन

0

दिलचस्प सवाल। कंप्यूटर नेटवर्क पैकेज प्रोटोकॉल के ढेर का उपयोग करके एन्कोड किए जाते हैं , और ऐसे प्रोटोकॉल पिछले एक के विनिर्देशों के शीर्ष पर बनाए जाते हैं। इसलिए एक प्रोटोकॉल का प्रदर्शन (थ्रूपुट) इसे निर्मित करने के लिए उपयोग किए गए के प्रदर्शन से घिरा होता है, क्योंकि आप अंतर्निहित एक के ऊपर अतिरिक्त एन्कोडिंग / डिकोडिंग चरणों को जोड़ रहे हैं।

उदाहरण के लिए , gRPCशीर्ष पर बनाया गया है HTTP 1.1/2, जो अनुप्रयोग परत पर एक प्रोटोकॉल है , या L7जैसा कि इसके प्रदर्शन के प्रदर्शन से बाध्य है HTTP। अब HTTPस्वयं ही इसके शीर्ष पर बना हुआ है TCP, जो कि ट्रांसपोर्ट लेयर पर है , या L4, इसलिए हम यह मान सकते हैं कि gRPCथ्रूपुट परत में परोसे जाने वाले समतुल्य कोड से बड़ा नहीं हो सकता TCP

दूसरे शब्दों में: यदि आप सर्वर कच्चे TCPपैकेज को संभालने में सक्षम हैं, तो जटिलता की नई परतों को जोड़ने से ( gRPC) प्रदर्शन में कैसे सुधार होगा?


इस कारण से कि मैं स्ट्रीमिंग दृष्टिकोण का उपयोग करता हूं: मैं एक बार http कनेक्शन स्थापित करने के लिए भुगतान करता हूं और ~ 300M संदेशों का उपयोग करके भेजता हूं। यह हुड के नीचे वेबस्कॉक का उपयोग करता है जो मुझे अपेक्षाकृत कम ओवरहेड होने की उम्मीद करता है।
सिमडोज़ो

के लिए gRPCआप भी एक कनेक्शन की स्थापना के लिए एक बार भुगतान करते हैं, लेकिन आप Protobuf पार्स करने के अतिरिक्त बोझ जोड़ लिया है। वैसे भी बहुत अधिक जानकारी के बिना अनुमान लगाना कठिन है, लेकिन मैं यह शर्त लगा सकता हूं कि सामान्य तौर पर, चूंकि आप अपनी पाइपलाइन में अतिरिक्त एन्कोडिंग / डिकोडिंग कदम जोड़ रहे हैं, इसलिए gRPCकार्यान्वयन बराबर वेब सॉकेट एक से धीमा होगा।
Batato

अक्का कुछ ओवरहेड भी जोड़ता है। वैसे भी x5 मंदी बहुत ज्यादा दिखती है।
सिमडेजो

मुझे लगता है कि आपको यह दिलचस्प लग सकता है: github.com/REASY/akka-http-vs-akka-grpc , उनके मामले में (और मुझे लगता है कि यह आपके लिए फैली हुई है), टोंटी प्रोटोबोफ़ (डी) में उच्च उपयोग के कारण हो सकती है ) क्रमांकन, जो कचरा कलेक्टर को अधिक कॉल ट्रिगर करता है।
बट्टाटो

धन्यवाद, दिलचस्प इसके बावजूद कि मैंने अपना मुद्दा पहले ही हल कर लिया है
simpadjo

0

अक्का टीसीपी ने यहां कितना अच्छा प्रदर्शन किया है, इससे मैं काफी प्रभावित हूं: डी

हमारा अनुभव थोड़ा अलग था। हम अक्का क्लस्टर का उपयोग करके बहुत छोटे उदाहरणों पर काम कर रहे थे। अक्का रीमोटिंग के लिए, हमने अर्क का उपयोग करके अक्का टीसीपी से यूडीपी में बदल दिया और बहुत अधिक दर + कम और अधिक स्थिर प्रतिक्रिया समय प्राप्त किया। यहां तक ​​कि सीपीयू की खपत और ठंड की शुरुआत से प्रतिक्रिया समय के बीच संतुलन बनाने में मदद करने वाले आर्टरी में भी एक कॉन्फ़िगरेशन है।

मेरा सुझाव कुछ यूडीपी आधारित फ्रेमवर्क का उपयोग करना है जो आपके लिए ट्रांसमिशन विश्वसनीयता का भी ध्यान रखता है (जैसे कि धमनी यूडीपी), और फुलबॉश जीआरपीसी का उपयोग करने के बजाय प्रोटोबुफ का उपयोग करके क्रमबद्ध करें। HTTP / 2 ट्रांसमिशन चैनल वास्तव में उच्च थ्रूपुट कम प्रतिक्रिया समय उद्देश्यों के लिए नहीं है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.