gRPC क्या है? APISIX के साथ कैसे काम करें?

Zexuan Luo

Zexuan Luo

September 28, 2022

Ecosystem

gRPC क्या है

gRPC Google द्वारा खुला स्रोत किया गया एक RPC फ्रेमवर्क है जो सेवाओं के बीच संचार को एकीकृत करने का लक्ष्य रखता है। यह फ्रेमवर्क HTTP/2 को अपने ट्रांसफर प्रोटोकॉल के रूप में और Protocol Buffers को इंटरफेस विवरण भाषा के रूप में उपयोग करता है। यह सेवाओं के बीच कॉल के लिए स्वचालित रूप से कोड जनरेट कर सकता है।

gRPC का प्रभुत्व

gRPC डेवलपर्स और क्लाउड-नेटिव वातावरण पर Google के असाधारण प्रभाव के कारण RPC फ्रेमवर्क का मानक बन गया है।

etcd फ़ंक्शन को इनवोक करना चाहते हैं? gRPC!

OpenCensus डेटा भेजना चाहते हैं? gRPC!

Go में लागू माइक्रोसर्विस में RPC का उपयोग करना चाहते हैं? gRPC!

gRPC का प्रभुत्व इतना मजबूत है कि यदि आपने gRPC को अपने RPC फ्रेमवर्क के रूप में नहीं चुना है, तो आपको एक ठोस कारण देना होगा कि क्यों नहीं। अन्यथा, कोई न कोई हमेशा पूछेगा, आप मुख्यधारा के gRPC को क्यों नहीं चुनते? यहां तक कि अलीबाबा, जिसने अपने RPC फ्रेमवर्क Dubbo को जोरदार तरीके से प्रचारित किया है, ने Dubbo 3 के नवीनतम संस्करण में प्रोटोकॉल डिज़ाइन को बड़े पैमाने पर संशोधित किया है, इसे gRPC और Dubbo 2 दोनों के साथ संगत gRPC वेरिएंट में बदल दिया है। वास्तव में, Dubbo 3 को Dubbo 2 से अपग्रेड कहने के बजाय, यह gRPC के प्रभुत्व को स्वीकार करने जैसा है।

कई सेवाएं जो gRPC प्रदान करती हैं, वे संबंधित HTTP इंटरफेस भी प्रदान करती हैं, लेकिन ऐसे इंटरफेस अक्सर केवल संगतता के लिए होते हैं। gRPC संस्करण का उपयोगकर्ता अनुभव बहुत बेहतर होता है। यदि आप gRPC के माध्यम से एक्सेस कर सकते हैं, तो आप सीधे संबंधित SDK को इम्पोर्ट कर सकते हैं। यदि आप केवल सामान्य HTTP API का उपयोग कर सकते हैं, तो आपको आमतौर पर एक डॉक्यूमेंट पेज पर निर्देशित किया जाएगा, और आपको संबंधित HTTP ऑपरेशन स्वयं लागू करने होंगे। हालांकि HTTP एक्सेस OpenAPI स्पेक के माध्यम से संबंधित SDK जनरेट कर सकता है, लेकिन केवल कुछ ही प्रोजेक्ट HTTP उपयोगकर्ताओं को gRPC जितनी गंभीरता से लेते हैं क्योंकि HTTP एक कम प्राथमिकता है।

क्या मुझे gRPC का उपयोग करना चाहिए

APISIX etcd को कॉन्फ़िगरेशन सेंटर के रूप में उपयोग करता है। v3 से, etcd ने अपने इंटरफेस को gRPC में माइग्रेट कर दिया है। हालांकि, OpenResty इकोसिस्टम में कोई भी प्रोजेक्ट gRPC का समर्थन नहीं करता है, इसलिए APISIX केवल etcd के HTTP API को कॉल कर सकता है। etcd के HTTP API gRPC-gateway के माध्यम से प्रदान किए जाते हैं। मूल रूप से, etcd अपने सर्वर साइड पर एक HTTP से gRPC प्रॉक्सी चलाता है, और फिर बाहरी HTTP अनुरोधों को gRPC-gateway के माध्यम से gRPC अनुरोधों में परिवर्तित किया जाता है। इस संचार विधि को कुछ वर्षों से तैनात करने के बाद, हमें HTTP API और gRPC API के बीच इंटरैक्शन में कुछ समस्याएं मिली हैं। gRPC-gateway होने का मतलब यह नहीं है कि HTTP एक्सेस पूरी तरह से समर्थित है। अभी भी सूक्ष्म अंतर हैं।

यहां etcd के साथ पिछले कुछ वर्षों में हमारे सामने आई संबंधित समस्याओं की सूची दी गई है:

  1. gRPC-gateway डिफ़ॉल्ट रूप से अक्षम। मेन्टेनर की लापरवाही के कारण, etcd का डिफ़ॉल्ट कॉन्फ़िगरेशन कुछ प्रोजेक्ट्स में gRPC-gateway को सक्षम नहीं करता है। इसलिए हमें डॉक्यूमेंट में निर्देश जोड़ने पड़े कि वर्तमान etcd में gRPC-gateway सक्षम है या नहीं। देखें https://github.com/apache/apisix/pull/2940
  2. डिफ़ॉल्ट रूप से, gRPC प्रतिक्रियाओं को 4MB तक सीमित करता है। etcd अपने प्रदान किए गए SDK में इस प्रतिबंध को हटा देता है लेकिन gRPC-gateway में इसे हटाना भूल गया। यह पता चला कि आधिकारिक etcdctl (जो इसके प्रदान किए गए SDK पर बनाया गया है) ठीक काम करता है, लेकिन APISIX नहीं। देखें https://github.com/etcd-io/etcd/issues/12576
  3. एक ही समस्या - इस बार एक ही कनेक्शन के लिए अधिकतम अनुरोधों की संख्या के साथ। Go का HTTP2 इम्प्लीमेंटेशन में MaxConcurrentStreams कॉन्फ़िगरेशन होता है जो एकल क्लाइंट द्वारा भेजे जा सकने वाले एक साथ अनुरोधों की संख्या को नियंत्रित करता है, जो डिफ़ॉल्ट रूप से 250 है। कौन सा क्लाइंट सामान्य रूप से एक साथ 250 से अधिक अनुरोध भेजेगा? इसलिए etcd ने हमेशा इस कॉन्फ़िगरेशन का उपयोग किया है। हालांकि, gRPC-gateway, जो सभी HTTP अनुरोधों को स्थानीय gRPC इंटरफेस पर प्रॉक्सी करता है, इस सीमा को पार कर सकता है। देखें https://github.com/etcd-io/etcd/issues/14185
  4. etcd द्वारा mTLS सक्षम करने के बाद, etcd सर्वर प्रमाणपत्र और क्लाइंट प्रमाणपत्र दोनों के रूप में एक ही प्रमाणपत्र का उपयोग करता है, gRPC-gateway के लिए सर्वर प्रमाणपत्र, और gRPC-gateway द्वारा gRPC इंटरफेस तक पहुंचने के लिए क्लाइंट प्रमाणपत्र। यदि प्रमाणपत्र पर सर्वर ऑथ एक्सटेंशन सक्षम है, लेकिन क्लाइंट ऑथ एक्सटेंशन सक्षम नहीं है, तो प्रमाणपत्र सत्यापन में एक त्रुटि होगी। एक बार फिर, etcdctl के साथ सीधे एक्सेस करना ठीक काम करता है (क्योंकि इस मामले में प्रमाणपत्र को क्लाइंट प्रमाणपत्र के रूप में उपयोग नहीं किया जाएगा), लेकिन APISIX नहीं। देखें https://github.com/etcd-io/etcd/issues/9785
  5. mTLS सक्षम करने के बाद, etcd प्रमाणपत्रों के उपयोगकर्ता जानकारी की सुरक्षा नीतियों को कॉन्फ़िगर करने की अनुमति देता है। जैसा कि ऊपर बताया गया है, gRPC-gateway gRPC इंटरफेस तक पहुंचने के लिए एक निश्चित क्लाइंट प्रमाणपत्र का उपयोग करता है न कि शुरुआत में HTTP इंटरफेस तक पहुंचने के लिए उपयोग किए गए प्रमाणपत्र की जानकारी का। इस प्रकार, यह सुविधा स्वाभाविक रूप से काम नहीं करेगी क्योंकि क्लाइंट प्रमाणपत्र निश्चित है और इसे बदला नहीं जाएगा। देखें https://github.com/apache/apisix/issues/5608

हम समस्याओं को दो बिंदुओं में सारांशित कर सकते हैं:

  1. gRPC-gateway (और शायद HTTP को gRPC में परिवर्तित करने के अन्य प्रयास) एक चांदी की गोली नहीं है जो सभी समस्याओं को ठीक कर दे।
  2. etcd के डेवलपर्स HTTP विधि पर पर्याप्त जोर नहीं देते हैं। और उनका सबसे बड़ा उपयोगकर्ता, Kubernetes, इस सुविधा का उपयोग नहीं करता है।

हम यहां किसी विशिष्ट सॉफ्टवेयर की समस्याओं के बारे में बात नहीं कर रहे हैं, etcd केवल एक विशिष्ट उदाहरण है जो gRPC का उपयोग करता है। सभी सेवाएं जो gRPC को अपने प्राथमिक RPC फ्रेमवर्क के रूप में उपयोग करती हैं, HTTP के लिए उनके समर्थन में समान सीमाएं हैं।

APISIX 3.0 इस समस्या को कैसे हल करता है

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

कार्यभार और स्थिरता को ध्यान में रखते हुए, हमने पहियों को फिर से बनाने के बजाय सामान्यतः उपयोग किए जाने वाले gRPC लाइब्रेरी पर आधारित विकास करने का निर्णय लिया। हमने निम्नलिखित gRPC लाइब्रेरीज़ की जांच की:

  1. NGINX की gRPC सेवा। NGINX gRPC को बाहरी उपयोगकर्ताओं के लिए एक्सपोज़ नहीं करता है, यहां तक कि एक उच्च-स्तरीय API भी नहीं। यदि आप इसे उपयोग करना चाहते हैं, तो आप केवल कुछ निम्न-स्तरीय फ़ंक्शन को कॉपी कर सकते हैं और फिर उन्हें एक उच्च-स्तरीय इंटरफेस में एकीकृत कर सकते हैं। उन्हें एकीकृत करने से अतिरिक्त कार्यभार होगा।
  2. C++ के लिए आधिकारिक gRPC लाइब्रेरी। चूंकि हमारा सिस्टम NGINX पर आधारित है, इसलिए C++ लाइब्रेरीज़ को एकीकृत करना थोड़ा जटिल हो सकता है। इसके अलावा, इस लाइब्रेरी की निर्भरता लगभग 2GB है, जो APISIX के निर्माण के लिए एक बड़ी चुनौती होगी।
  3. gRPC का आधिकारिक Go इम्प्लीमेंटेशन। Go में एक शक्तिशाली टूलचेन है, और हम जल्दी से प्रोजेक्ट को इसमें बना सकते हैं। हालांकि, यह दुर्भाग्यपूर्ण है कि इस इम्प्लीमेंटेशन का प्रदर्शन C++ संस्करण से बहुत दूर है। इसलिए हमने एक अन्य Go इम्प्लीमेंटेशन को देखा: https://github.com/bufbuild/connect-go/। दुर्भाग्य से, इस प्रोजेक्ट का प्रदर्शन आधिकारिक संस्करण से बेहतर नहीं है।
  4. gRPC लाइब्रेरी का Rust इम्प्लीमेंटेशन। यह लाइब्रेरी निर्भरता प्रबंधन और प्रदर्शन को जोड़ने के लिए एक प्राकृतिक विकल्प होगा। दुर्भाग्य से, हम Rust से परिचित नहीं हैं और इस पर दांव नहीं लगाएंगे।

gRPC क्लाइंट के ऑपरेशन मूल रूप से सभी IO बाउंड होते हैं, इसलिए प्रदर्शन आवश्यकता प्राथमिक नहीं है। सावधानीपूर्वक विचार करने के बाद, हमने इसे Go-gRPC पर आधारित लागू किया।

Lua के कोरोटीन शेड्यूलर के साथ समन्वय करने के लिए, हमने एक NGINX C मॉड्यूल लिखा: https://github.com/api7/grpc-client-nginx-module। पहले, हम Go कोड को cgo के माध्यम से स्टैटिकली-लिंक्ड लाइब्रेरी में संकलित करके इस C मॉड्यूल में एकीकृत करना चाहते थे, लेकिन हमने पाया कि चूंकि Go एक मल्टी-थ्रेडेड एप्लिकेशन है, इसलिए फोर्क करने के बाद चाइल्ड प्रोसेस पैरेंट प्रोसेस के सभी थ्रेड्स को इनहेरिट नहीं करेगा। NGINX के मास्टर-वर्कर मल्टी-प्रोसेस आर्किटेक्चर के लिए अनुकूलित करने का कोई तरीका नहीं है। इसलिए हमने Go कोड को डायनामिक लिंक लाइब्रेरी (DLL) में संकलित किया और फिर इसे रनटाइम में वर्कर प्रोसेस में लोड किया।

हमने Go के कोरोटीन्स और Lua के कोरोटीन्स के साथ समन्वय करने के लिए एक टास्क क्यू मैकेनिज्म लागू किया। जब Lua कोड एक gRPC IO ऑपरेशन शुरू करता है, तो यह Go साइड पर एक टास्क सबमिट करता है और खुद को निलंबित कर देता है। एक Go कोरोटीन इस टास्क को निष्पादित करेगा, और निष्पादन परिणाम को क्यू में लिखा जाएगा। NGINX साइड पर एक बैकग्राउंड थ्रेड टास्क निष्पादन परिणाम को खपत करता है, संबंधित Lua कोरोटीन को रीशेड्यूल करता है, और Lua कोड को निष्पादित करना जारी रखता है। इस तरह, gRPC IO ऑपरेशन Lua कोड की नजर में सामान्य सॉकेट ऑपरेशन से अलग नहीं होते हैं।

अब, NGINX C मॉड्यूल का अधिकांश काम हो चुका है। हमें केवल etcd के .proto फ़ाइल (जो इसके gRPC इंटरफेस को परिभाषित करता है) को निकालना है, इसे संशोधित करना है, और फिर Lua में फ़ाइल को लोड करना है ताकि निम्नलिखित etcd क्लाइंट प्राप्त हो:

local gcli = require("resty.grpc") assert(gcli.load("t/testdata/rpc.proto")) local conn = assert(gcli.connect("127.0.0.1:2379")) local st, err = conn:new_server_stream("etcdserverpb.Watch", "Watch", {create_request = {key = ngx.var.arg_key}}, {timeout = 30000}) if not st then ngx.status = 503 ngx.say(err) return end for i = 1, (ngx.var.arg_count or 10) do local res, err = st:recv() ngx.log(ngx.WARN, "received ", cjson.encode(res)) if not res then ngx.status = 503 ngx.say(err) break end end

यह gRPC-आधारित इम्प्लीमेंटेशन lua-resty-etcd, एक etcd-HTTP क्लाइंट प्रोजेक्ट जिसमें केवल Lua में 1600 लाइनें हैं, से बेहतर है।

बेशक, हम अभी भी lua-resty-etcd को बदलने से बहुत दूर हैं। etcd के साथ पूरी तरह से जुड़ने के लिए, grpc-client-nginx-module को निम्नलिखित फ़ंक्शन को पूरा करने की भी आवश्यकता है:

  1. mTLS समर्थन
  2. gRPC मेटाडेटा कॉन्फ़िगरेशन का समर्थन
  3. पैरामीटर कॉन्फ़िगरेशन का समर्थन (जैसे MaxConcurrentStreams और MaxRecvMsgSize)
  4. L4 से अनुरोधों का समर्थन

सौभाग्य से, हमने आधार तैयार कर लिया है, और इन चीजों का समर्थन करना केवल समय की बात है।

grpc-client-nginx-module को APISIX 3.0 में एकीकृत किया जाएगा, फिर APISIX उपयोगकर्ता APISIX प्लगइन में इस मॉड्यूल के तरीकों का उपयोग करके सीधे gRPC सेवाओं के साथ संचार कर सकते हैं।

gRPC के लिए नेटिव समर्थन के साथ, APISIX को etcd का बेहतर अनुभव मिलेगा और gRPC स्वास्थ्य जांच और gRPC-आधारित ओपन टेलीमेट्री डेटा रिपोर्टिंग जैसी सुविधाओं के लिए संभावनाओं के द्वार खुलेंगे।

हम भविष्य में APISIX की और अधिक gRPC-आधारित सुविधाओं को देखने के लिए उत्साहित हैं!

Tags: