1. परिचय
इस कोडलैब में, gRPC-Java का इस्तेमाल करके एक क्लाइंट और सर्वर बनाया जाएगा. ये दोनों, Java में लिखे गए रूट-मैपिंग ऐप्लिकेशन की बुनियादी ज़रूरतें पूरी करते हैं.
ट्यूटोरियल के आखिर तक, आपके पास एक ऐसा क्लाइंट होगा जो gRPC का इस्तेमाल करके, रिमोट सर्वर से कनेक्ट होता है. इससे आपको मैप पर किसी खास जगह के नाम या पते की जानकारी मिलती है. कोई ऐप्लिकेशन, इस क्लाइंट-सर्वर डिज़ाइन का इस्तेमाल करके किसी रास्ते पर मौजूद लोकप्रिय जगहों की सूची बना सकता है या उनके बारे में खास जानकारी दे सकता है.
सर्वर के एपीआई को प्रोटोकॉल बफ़र फ़ाइल में तय किया जाता है. इसका इस्तेमाल क्लाइंट और सर्वर के लिए बॉयलरप्लेट कोड जनरेट करने के लिए किया जाएगा, ताकि वे एक-दूसरे से कम्यूनिकेट कर सकें. इससे आपको इस सुविधा को लागू करने में समय और मेहनत नहीं करनी पड़ेगी.
जनरेट किया गया यह कोड, सर्वर और क्लाइंट के बीच कम्यूनिकेशन की जटिलताओं के साथ-साथ डेटा के क्रमबद्ध और क्रम से हटाने की प्रोसेस को भी मैनेज करता है.
आपको क्या सीखने को मिलेगा
- किसी सेवा के एपीआई को तय करने के लिए, प्रोटोकॉल बफ़र का इस्तेमाल कैसे करें.
- ऑटोमेटेड कोड जनरेशन का इस्तेमाल करके, प्रोटोकॉल बफ़र की परिभाषा से gRPC पर आधारित क्लाइंट और सर्वर बनाने का तरीका.
- gRPC के साथ क्लाइंट-सर्वर कम्यूनिकेशन के बारे में जानकारी.
यह कोडलैब, Java डेवलपर के लिए है. इसमें gRPC का इस्तेमाल करने का तरीका बताया गया है. साथ ही, इसमें gRPC के बारे में जानकारी दी गई है. इसके अलावा, यह कोडलैब उन लोगों के लिए भी है जो डिस्ट्रिब्यूटेड सिस्टम बनाने में दिलचस्पी रखते हैं. इसके लिए, gRPC का अनुभव होना ज़रूरी नहीं है.
2. शुरू करने से पहले
ज़रूरी शर्तें
- JDK का वर्शन 8 या इसके बाद का वर्शन
कोड प्राप्त करें
इसलिए, आपको शुरू से काम न करना पड़े, इसके लिए इस कोडलैब में ऐप्लिकेशन के सोर्स कोड का एक ढांचा दिया गया है. आपको इसे पूरा करना है. यहां दिए गए तरीके से, ऐप्लिकेशन को पूरा करने का तरीका जानें. इसमें, बॉयलरप्लेट gRPC कोड जनरेट करने के लिए, प्रोटोकॉल बफ़र कंपाइलर प्लगिन का इस्तेमाल करना भी शामिल है.
सबसे पहले, कोडलैब की वर्किंग डायरेक्ट्री बनाएं और उसमें cd करें:
mkdir grpc-java-getting-started && cd grpc-java-getting-started
कोडलैब डाउनलोड करें और उसे एक्सट्रैक्ट करें:
curl -sL https://github.com/grpc-ecosystem/grpc-codelabs/archive/refs/heads/v1.tar.gz \
| tar xvz --strip-components=4 \
grpc-codelabs-1/codelabs/grpc-java-getting-started/start_here
इसके अलावा, सिर्फ़ कोडलैब डायरेक्ट्री वाली .zip फ़ाइल डाउनलोड करके, उसे मैन्युअल तरीके से अनज़िप किया जा सकता है.
अगर आपको लागू करने के लिए टाइप नहीं करना है, तो पूरा सोर्स कोड GitHub पर उपलब्ध है.
3. सेवा के बारे में जानकारी देना
सबसे पहले, आपको प्रोटोकॉल बफ़र का इस्तेमाल करके, ऐप्लिकेशन की gRPC सेवा, उसके RPC तरीके, और अनुरोध और जवाब के मैसेज टाइप तय करने होंगे. आपकी सेवा से ये सुविधाएं मिलेंगी:
GetFeatureनाम की एक आरपीसी विधि, जिसे सर्वर लागू करता है और क्लाइंट कॉल करता है.- मैसेज टाइप
PointऔरFeature, डेटा स्ट्रक्चर होते हैं. येGetFeatureतरीके का इस्तेमाल करते समय, क्लाइंट और सर्वर के बीच शेयर किए जाते हैं. क्लाइंट, सर्वर कोGetFeatureअनुरोध में मैप के कोऑर्डिनेटPointके तौर पर देता है. इसके जवाब में सर्वर, उन कोऑर्डिनेट पर मौजूद जानकारी के साथFeatureभेजता है.
इस आरपीसी तरीके और इसके मैसेज टाइप को, दिए गए सोर्स कोड की src/main/proto/routeguide/route_guide.proto फ़ाइल में तय किया जाएगा.
प्रोटोकॉल बफ़र को आम तौर पर, protobufs कहा जाता है. gRPC की शब्दावली के बारे में ज़्यादा जानने के लिए, gRPC के मुख्य कॉन्सेप्ट, आर्किटेक्चर, और लाइफ़साइकल देखें.
इस उदाहरण में, हम Java कोड जनरेट कर रहे हैं. इसलिए, हमने java_package फ़ाइल का विकल्प और अपनी .proto में Java क्लास का नाम तय किया है:
option java_package = "io.grpc.examples.routeguide";
option java_outer_classname = "RouteGuideProto";
मैसेज के टाइप
सोर्स कोड की routeguide/route_guide.proto फ़ाइल में, सबसे पहले Point मैसेज टाइप तय करें. Point, मैप पर अक्षांश-देशांतर के निर्देशांकों के जोड़े को दिखाता है. इस कोडलैब के लिए, पूर्णांकों का इस्तेमाल करें:
message Point {
int32 latitude = 1;
int32 longitude = 2;
}
1 और 2 नंबर, message स्ट्रक्चर में मौजूद हर फ़ील्ड के लिए यूनीक आईडी नंबर होते हैं.
इसके बाद, Feature मैसेज टाइप तय करें. Feature, string फ़ील्ड का इस्तेमाल करता है. इससे Point में बताई गई जगह पर मौजूद किसी चीज़ का नाम या डाक पता पता चलता है:
message Feature {
// The name or address of the feature.
string name = 1;
// The point where the feature is located.
Point location = 2;
}
सेवा का तरीका
route_guide.proto फ़ाइल में service स्ट्रक्चर होता है, जिसका नाम RouteGuide होता है. यह ऐप्लिकेशन की सेवा के ज़रिए उपलब्ध कराए गए एक या उससे ज़्यादा तरीकों के बारे में बताता है.
RouteGuide डेफ़िनिशन में rpc तरीका GetFeature जोड़ें. जैसा कि पहले बताया गया है, यह तरीका निर्देशांकों के दिए गए सेट से किसी जगह का नाम या पता ढूंढता है. इसलिए, दिए गए Point के लिए GetFeature को Feature वैल्यू वापस करने के लिए कहें:
service RouteGuide {
// Definition of the service goes here
// Obtains the feature at a given position.
rpc GetFeature(Point) returns (Feature) {}
}
यह एक यूनेरी आरपीसी तरीका है: एक सिंपल आरपीसी, जिसमें क्लाइंट सर्वर को अनुरोध भेजता है और जवाब मिलने का इंतज़ार करता है. यह लोकल फ़ंक्शन कॉल की तरह ही होता है.
4. क्लाइंट और सर्वर कोड जनरेट करना
इसके बाद, हमें .proto सेवा की परिभाषा से gRPC क्लाइंट और सर्वर इंटरफ़ेस जनरेट करने होंगे. हम ऐसा, खास gRPC Java प्लगिन के साथ प्रोटोकॉल बफ़र कंपाइलर protoc का इस्तेमाल करके करते हैं. gRPC सेवाएं जनरेट करने के लिए, आपको proto3 कंपाइलर का इस्तेमाल करना होगा. यह कंपाइलर, proto2 और proto3, दोनों सिंटैक्स के साथ काम करता है.
Gradle या Maven का इस्तेमाल करते समय, protoc बिल्ड प्लगिन, बिल्ड के हिस्से के तौर पर ज़रूरी कोड जनरेट कर सकता है. अपनी .proto फ़ाइलों से कोड जनरेट करने का तरीका जानने के लिए, grpc-java README पढ़ें.
हमने इस प्रोजेक्ट को बनाने के लिए, कोडलैब के सोर्स कोड में Gradle एनवायरमेंट और कॉन्फ़िगरेशन दिया है.
grpc-java-getting-started डायरेक्ट्री में, यह कमांड चलाएं:
$ chmod +x gradlew $ ./gradlew generateProto
हमारी सेवा की परिभाषा से ये क्लास जनरेट की जाती हैं:
Feature.java,Point.java, और अन्य फ़ाइलें, जिनमें प्रोटोकॉल बफ़र का पूरा कोड होता है. इस कोड का इस्तेमाल, अनुरोध और जवाब के मैसेज टाइप को भरने, क्रम से लगाने, और वापस पाने के लिए किया जाता है.RouteGuideGrpc.javaमें (कुछ अन्य काम के कोड के साथ)RouteGuideसर्वर के लिए एक बेसिक क्लास होती है, जिसेRouteGuideGrpc.RouteGuideImplBaseलागू करना होता है. इसमेंRouteGuideसेवा में तय किए गए सभी तरीके और क्लाइंट के इस्तेमाल के लिए स्टब क्लास होती हैं.
5. सर्वर को लागू करना
सबसे पहले, देखते हैं कि RouteGuide सर्वर कैसे बनाया जाता है. RouteGuide सेवा को काम करने के लिए, दो चीज़ें ज़रूरी होती हैं:
- हमारी सेवा की परिभाषा से जनरेट किए गए सेवा इंटरफ़ेस को लागू करना. यह हमारी सेवा का असल "काम" करता है.
- क्लाइंट से मिले अनुरोधों को सुनने और उन्हें सही सेवा लागू करने के लिए, gRPC सर्वर को चालू करना.
RouteGuide को लागू करना
जैसा कि आप देख सकते हैं, हमारे सर्वर में एक RouteGuideService क्लास है, जो जनरेट की गई RouteGuideGrpc.RouteGuideImplBase ऐब्स्ट्रैक्ट क्लास को बढ़ाता है:
private static class RouteGuideService extends RouteGuideGrpc.RouteGuideImplBase {
...
}
हमने आपके सर्वर को सुविधाओं के साथ शुरू करने के लिए, ये दो फ़ाइलें उपलब्ध कराई हैं:
./src/main/java/io/grpc/examples/routeguide/RouteGuideUtil.java
./src/main/resources/io/grpc/examples/routeguide/route_guide_db.json
आइए, आरपीसी को लागू करने के आसान तरीके के बारे में विस्तार से जानते हैं.
यूनरी आरपीसी
RouteGuideService, हमारी सभी सेवा के तरीकों को लागू करता है. इस मामले में, यह सिर्फ़ GetFeature() है. यह क्लाइंट से Point मैसेज लेता है और जानी-पहचानी जगहों की सूची से, Feature मैसेज में जगह की जानकारी दिखाता है.
@Override
public void getFeature(Point request, StreamObserver<Feature> responseObserver) {
responseObserver.onNext(checkFeature(request));
responseObserver.onCompleted();
}
getFeature() तरीके में दो पैरामीटर होते हैं:
Point: अनुरोध.StreamObserver<Feature>: रिस्पॉन्स ऑब्ज़र्वर, जो सर्वर के लिए एक खास इंटरफ़ेस होता है. सर्वर, इस इंटरफ़ेस का इस्तेमाल करके रिस्पॉन्स भेजता है.
क्लाइंट को हमारा जवाब भेजने और कॉल को पूरा करने के लिए:
- हम क्लाइंट को वापस भेजने के लिए,
Featureरिस्पॉन्स ऑब्जेक्ट बनाते हैं और उसे भरते हैं. यह हमारी सेवा की परिभाषा में बताया गया है. इस उदाहरण में, हमने इसे अलगcheckFeature()प्राइवेट तरीके से किया है. - हम
Featureको वापस लाने के लिए, रिस्पॉन्स ऑब्ज़र्वर केonNext()तरीके का इस्तेमाल करते हैं. - हम रिस्पॉन्स ऑब्ज़र्वर के
onCompleted()तरीके का इस्तेमाल करके यह बताते हैं कि हमने आरपीसी को प्रोसेस कर लिया है.
सर्वर शुरू करना
सभी सेवा के तरीकों को लागू करने के बाद, हमें एक gRPC सर्वर शुरू करना होगा, ताकि क्लाइंट हमारी सेवा का इस्तेमाल कर सकें. हम अपने बॉयलरप्लेट में ServerBuilder ऑब्जेक्ट बनाने की सुविधा शामिल करते हैं:
ServerBuilder.forPort(port), port, RouteGuideUtil.parseFeatures(featureFile)
हम कंस्ट्रक्टर में सेवा बनाते हैं:
- बिल्डर के
forPort()तरीके का इस्तेमाल करके, उस पोर्ट के बारे में बताएं जिसका इस्तेमाल हमें क्लाइंट के अनुरोधों को सुनने के लिए करना है. यह वाइल्डकार्ड पते का इस्तेमाल करेगा. - हमारी सेवा लागू करने वाली क्लास
RouteGuideServiceका एक इंस्टेंस बनाएं और इसे बिल्डर केaddService()तरीके में पास करें. - हमारी सेवा के लिए RPC सर्वर बनाने के लिए, बिल्डर पर
build()को कॉल करें.
यहां दिए गए स्निपेट में, ServerBuilder ऑब्जेक्ट बनाने का तरीका बताया गया है.
/** Create a RouteGuide server listening on {@code port} using {@code featureFile} database. */
public RouteGuideServer(int port, URL featureFile) throws IOException {
this(Grpc.newServerBuilderForPort(port, InsecureServerCredentials.create()),
port, RouteGuideUtil.parseFeatures(featureFile));
}
यहां दिए गए स्निपेट में बताया गया है कि हम अपनी RouteGuide सेवा के लिए सर्वर ऑब्जेक्ट कैसे बनाते हैं.
/** Create a RouteGuide server using serverBuilder as a base and features as data. */
public RouteGuideServer(ServerBuilder<?> serverBuilder, int port, Collection<Feature> features) {
this.port = port;
server = serverBuilder.addService(new RouteGuideService(features))
.build();
}
स्टार्ट करने का एक ऐसा तरीका लागू करें जो ऊपर बनाए गए सर्वर पर start को कॉल करता हो.
public void start() throws IOException {
server.start();
logger.info("Server started, listening on " + port);
}
सर्वर के पूरा होने का इंतज़ार करने के लिए, कोई तरीका लागू करें, ताकि यह तुरंत बंद न हो.
/** Await termination on the main thread since the grpc library uses daemon threads. */
private void blockUntilShutdown() throws InterruptedException {
if (server != null) {
server.awaitTermination();
}
}
जैसा कि आप देख सकते हैं, हमने ServerBuilder का इस्तेमाल करके अपना सर्वर बनाया और शुरू किया है.
मुख्य तरीके में, हम:
RouteGuideServerइंस्टेंस बनाएं.- हमारी सेवा के लिए, RPC सर्वर को चालू करने के लिए
start()को कॉल करें. blockUntilShutdown()पर कॉल करके, सेवा बंद होने का इंतज़ार करें.
public static void main(String[] args) throws Exception {
RouteGuideServer server = new RouteGuideServer(8980);
server.start();
server.blockUntilShutdown();
}
6. क्लाइंट बनाना
इस सेक्शन में, हम RouteGuide सेवा के लिए क्लाइंट बनाने का तरीका जानेंगे.
स्टब को इंस्टैंशिएट करना
सेवा के तरीकों को कॉल करने के लिए, हमें सबसे पहले एक स्टब बनाना होगा. स्टब दो तरह के होते हैं. हालांकि, इस कोडलैब के लिए हमें सिर्फ़ ब्लॉक करने वाले स्टब का इस्तेमाल करना है. ये दो तरह के होते हैं:
- ब्लॉकिंग/सिंक्रोनस स्टब, जो आरपीसी कॉल करता है और सर्वर से जवाब मिलने का इंतज़ार करता है. यह जवाब देता है या अपवाद बढ़ाता है.
- नॉन-ब्लॉकिंग/एसिंक्रोनस स्टब, जो सर्वर को नॉन-ब्लॉकिंग कॉल करता है. इसमें जवाब एसिंक्रोनस तरीके से मिलता है. एसिंक्रोनस स्टब का इस्तेमाल करके ही, कुछ तरह के स्ट्रीमिंग कॉल किए जा सकते हैं.
सबसे पहले, हमें एक gRPC चैनल बनाना होगा. इसके बाद, इस चैनल का इस्तेमाल करके हमें अपना स्टब बनाना होगा.
चैनल बनाने के लिए, सीधे तौर पर ManagedChannelBuilder का इस्तेमाल किया जा सकता था.
ManagedChannelBuilder.forAddress(host, port).usePlaintext().build
हालांकि, हम एक ऐसे यूटिलिटी तरीके का इस्तेमाल करेंगे जो hostname:port के साथ एक स्ट्रिंग लेता है.
Grpc.newChannelBuilder(target, InsecureChannelCredentials.create()).build();
अब हम इस चैनल का इस्तेमाल करके, ब्लॉकिंग स्टब बना सकते हैं. इस कोडलैब के लिए, हमारे पास सिर्फ़ ब्लॉक करने वाली आरपीसी हैं. इसलिए, हम RouteGuideGrpc क्लास में दिए गए newBlockingStub तरीके का इस्तेमाल करते हैं. इस क्लास को हमने अपने .proto से जनरेट किया है.
blockingStub = RouteGuideGrpc.newBlockingStub(channel);
सेवा के तरीकों को कॉल करें
अब देखते हैं कि हम अपनी सेवा के तरीकों को कैसे कॉल करते हैं.
सिंपल आरपीसी
सिंपल आरपीसी GetFeature को कॉल करना, लोकल तरीके को कॉल करने जितना ही आसान है.
हम अनुरोध प्रोटोकॉल बफ़र ऑब्जेक्ट (हमारे मामले में Point) बनाते हैं और उसे भरते हैं. इसके बाद, इसे ब्लॉकिंग स्टब पर मौजूद getFeature() तरीके को पास करते हैं. इससे हमें Feature मिलता है.
गड़बड़ी होने पर, इसे Status के तौर पर कोड किया जाता है. इसे हम StatusRuntimeException से हासिल कर सकते हैं.
Point request = Point.newBuilder().setLatitude(lat).setLongitude(lon).build();
Feature feature;
try {
feature = blockingStub.getFeature(request);
} catch (StatusRuntimeException e) {
logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
return;
}
बॉयलरप्लेट, एक मैसेज लॉग करता है. इसमें कॉन्टेंट शामिल होता है. यह इस बात पर निर्भर करता है कि तय किए गए पॉइंट पर कोई सुविधा मौजूद थी या नहीं.
7. इसे आज़माएं!
start_hereडायरेक्ट्री में, यह कमांड चलाएं:
$ ./gradlew installDist
इससे आपका कोड कंपाइल हो जाएगा. साथ ही, इसे जार में पैकेज कर दिया जाएगा और उदाहरण को चलाने वाली स्क्रिप्ट बन जाएंगी. ये build/install/start_here/bin/ डायरेक्ट्री में बनाए जाएंगे. स्क्रिप्ट route-guide-server और route-guide-client हैं.
क्लाइंट शुरू करने से पहले, सर्वर चालू होना चाहिए.
- सर्वर चलाएं:
$ ./build/install/start_here/bin/route-guide-server
- क्लाइंट चलाएं:
$ ./build/install/start_here/bin/route-guide-client
आपको इस तरह का आउटपुट दिखेगा. इसमें टाइमस्टैंप हटा दिए गए हैं, ताकि जानकारी साफ़ तौर पर दिख सके:
INFO: *** GetFeature: lat=409,146,138 lon=-746,188,906 INFO: Found feature called "Berkshire Valley Management Area Trail, Jefferson, NJ, USA" at 40.915, -74.619 INFO: *** GetFeature: lat=0 lon=0 INFO: Found no feature at 0, 0
8. आगे क्या करना है
- gRPC का परिचय और मुख्य सिद्धांत में, जानें कि gRPC कैसे काम करता है
- बुनियादी बातों वाला ट्यूटोरियल देखें
- एपीआई के बारे में जानकारी देखें.