1. खास जानकारी
यह लैब ऐसी सुविधाएं और क्षमताएं दिखाती है जो कंटेनर वाले एनवायरमेंट में Java ऐप्लिकेशन डेवलप करने का काम करने वाले सॉफ़्टवेयर इंजीनियर के लिए डेवलपमेंट वर्कफ़्लो को आसान बनाने के लिए डिज़ाइन की गई हैं. सामान्य कंटेनर डेवलपमेंट के लिए, उपयोगकर्ता को कंटेनर के ब्यौरे और कंटेनर बनाने की प्रोसेस को समझना ज़रूरी है. इसके अलावा, डेवलपर को आम तौर पर अपने काम करने का फ़्लो तोड़ना पड़ता है, ताकि वे रिमोट एनवायरमेंट में अपने ऐप्लिकेशन की जांच करने और उन्हें डीबग करने के लिए, अपने IDE को छोड़ दें. इस ट्यूटोरियल में बताए गए टूल और टेक्नोलॉजी की मदद से, डेवलपर अपने IDE को छोड़े बिना, कंटेनर वाले ऐप्लिकेशन के साथ असरदार तरीके से काम कर सकते हैं.
आपको क्या सीखने को मिलेगा
इस लैब में, आपको GCP में कंटेनर को डेवलप करने के तरीकों के बारे में जानकारी मिलेगी. जैसे:
- सेटअप और ज़रूरी शर्तें
- नया Java स्टार्टर ऐप्लिकेशन बनाना
- डेवलपमेंट प्रोसेस की जानकारी
- सीआरयूडी रेस्ट सर्विस की सुविधा आसानी से बनाई जा रही है
- साफ़-सफ़ाई सेवा
2. सेटअप और ज़रूरी शर्तें
अपने हिसाब से एनवायरमेंट सेटअप करें
- Google Cloud Console में साइन इन करें और नया प्रोजेक्ट बनाएं या किसी मौजूदा प्रोजेक्ट का फिर से इस्तेमाल करें. अगर आपके पास पहले से Gmail या Google Workspace खाता नहीं है, तो आपको नया खाता बनाना होगा.
- प्रोजेक्ट का नाम, इस प्रोजेक्ट में हिस्सा लेने वाले लोगों का डिसप्ले नेम होता है. यह एक वर्ण स्ट्रिंग है, जिसका इस्तेमाल Google API नहीं करता. साथ ही, आप इसे किसी भी समय अपडेट कर सकते हैं.
- प्रोजेक्ट आईडी, Google Cloud के सभी प्रोजेक्ट के लिए यूनीक होना चाहिए. साथ ही, आईडी को बदला नहीं जा सकता. सेट अप के बाद इसे बदला नहीं जा सकता. Cloud Console, एक यूनीक स्ट्रिंग अपने-आप जनरेट करता है; आम तौर पर, आपको उसके होने की कोई परवाह नहीं होती. ज़्यादातर कोडलैब में, आपको प्रोजेक्ट आईडी का रेफ़रंस देना पड़ता है और आम तौर पर इसकी पहचान
PROJECT_ID
के रूप में की जाती है. इसलिए, अगर आपको यह पसंद नहीं आता है, तो कोई भी कोड जनरेट करें. इसके अलावा, खुद का भी कोड बनाकर देखा जा सकता है कि वह उपलब्ध है या नहीं. फिर यह "फ़्रोज़न" होता है प्रोजेक्ट बनने के बाद. - तीसरी वैल्यू, प्रोजेक्ट नंबर है, जिसका इस्तेमाल कुछ एपीआई करते हैं. दस्तावेज़ में इन तीनों वैल्यू के बारे में ज़्यादा जानें.
- इसके बाद, आपको क्लाउड संसाधनों/एपीआई का इस्तेमाल करने के लिए, Cloud Console में बिलिंग की सुविधा चालू करनी होगी. इस कोडलैब का इस्तेमाल करने पर, आपको ज़्यादा पैसे नहीं चुकाने होंगे. इस ट्यूटोरियल के अलावा किसी अन्य प्लैटफ़ॉर्म पर बिलिंग न करने के लिए, संसाधनों को बंद करने के लिए, "साफ़-सफ़ाई" का पालन करें कोडलैब के आखिर में दिए गए निर्देश देखें. Google Cloud के नए उपयोगकर्ता, 300 डॉलर के मुफ़्त ट्रायल वाले प्रोग्राम में हिस्सा ले सकते हैं.
Cloudshell एडिटर शुरू करें
इस लैब को Google Cloud Shell Editor के साथ इस्तेमाल करने के लिए डिज़ाइन और टेस्ट किया गया था. एडिटर को ऐक्सेस करने के लिए,
- https://console.cloud.google.com पर जाकर, अपना Google प्रोजेक्ट ऐक्सेस करें.
- सबसे ऊपर दाएं कोने में मौजूद, Cloud Shell एडिटर आइकॉन पर क्लिक करें
- आपकी विंडो के सबसे नीचे एक नया पैनल खुलेगा
- 'एडिटर' बटन पर क्लिक करें
- इसके बाद, दाईं ओर एक एक्सप्लोरर और बीच वाले हिस्से में एडिटर खुलेगा
- स्क्रीन के सबसे नीचे टर्मिनल पैनल भी उपलब्ध होना चाहिए
- अगर टर्मिनल खुला नहीं है, तो नई टर्मिनल विंडो खोलने के लिए `ctrl+`` के कुंजी कॉम्बिनेशन का इस्तेमाल करें
gcloud सेट अप करें
Cloud Shell में, अपना प्रोजेक्ट आईडी और वह इलाका सेट करें जहां आपको अपना ऐप्लिकेशन डिप्लॉय करना है. उन्हें PROJECT_ID
और REGION
वैरिएबल के तौर पर सेव करें.
export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')
सोर्स कोड पाना
इस लैब का सोर्स कोड, GitHub पर GoogleCloudPlatform में कंटेनर-developer-वर्कशॉप में मौजूद है. नीचे दिए गए निर्देश से इसे क्लोन करें और फिर डायरेक्ट्री में बदलें.
git clone https://github.com/GoogleCloudPlatform/container-developer-workshop.git
cd container-developer-workshop/labs/spring-boot
इस लैब में इस्तेमाल किए जा रहे इन्फ़्रास्ट्रक्चर का प्रावधान करें
इस लैब में, आपको GKE (जीकेई) पर कोड डिप्लॉय करना होगा. साथ ही, CloudSql के डेटाबेस में सेव किए गए डेटा को ऐक्सेस करना होगा. नीचे दी गई सेटअप स्क्रिप्ट आपके लिए यह इन्फ़्रास्ट्रक्चर तैयार करती है. प्रावधान की प्रोसेस में 10 मिनट से ज़्यादा लगेंगे. सेटअप प्रोसेस होने के दौरान, अगले कुछ चरण पूरे किए जा सकते हैं.
./setup.sh
3. नया Java स्टार्टर ऐप्लिकेशन बनाना
इस सेक्शन में, आपको Spring.io के सैंपल ऐप्लिकेशन की मदद से, नए सिरे से Java Spring बूट ऐप्लिकेशन बनाने का विकल्प मिलेगा
सैंपल ऐप्लिकेशन का क्लोन बनाएं
- कोई स्टार्टर ऐप्लिकेशन बनाएँ
curl https://start.spring.io/starter.zip -d dependencies=web -d type=maven-project -d javaVersion=11 -d packageName=com.example.springboot -o sample-app.zip
- ऐप्लिकेशन को अनज़िप करें
unzip sample-app.zip -d sample-app
- सैंपल-ऐप्लिकेशन डायरेक्ट्री में बदलें और फ़ोल्डर को Cloud Shell IDE फ़ाइल फ़ोल्डर में खोलें
cd sample-app && cloudshell workspace .
स्प्रिंग-बूट-डेवलपर टूल जोड़ें और जिब
Spring बूट DevTools चालू करने के लिए, अपने एडिटर में एक्सप्लोरर से pom.xml खोलें और उसे खोलें. इसके बाद, नीचे दिए गए कोड को ब्यौरे वाली लाइन के बाद चिपकाएं, जिस पर <description>स्प्रिंग बूट का डेमो प्रोजेक्ट</description> लिखा हो
- pom.xml में Spring-boot-devtools जोड़ें
प्रोजेक्ट के रूट में pom.xml खोलें. Description
एंट्री के बाद, नीचे दिया गया कॉन्फ़िगरेशन जोड़ें.
pom.xml
<!-- Spring profiles-->
<profiles>
<profile>
<id>sync</id>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
</profile>
</profiles>
- pom.xml में jib-maven-plugin को चालू करें
Jib, Google का एक ओपन सोर्स Java कंटेनरिंग टूल है. इसकी मदद से, Java डेवलपर उन Java टूल का इस्तेमाल करके कंटेनर बना सकते हैं जिनके बारे में उन्हें पता है. Jib एक तेज़ और आसान कंटेनर इमेज बिल्डर है जो आपके ऐप्लिकेशन को कंटेनर इमेज में पैक करने के सभी चरणों को पूरा करता है. इसके लिए आपको Dockerfile लिखना या डॉकर इंस्टॉल करना ज़रूरी नहीं है. साथ ही, इसे सीधे Maven और Gradle में इंटिग्रेट किया गया है.
pom.xml फ़ाइल में नीचे की ओर स्क्रोल करें और Jib प्लगिन को शामिल करने के लिए, Build
सेक्शन को अपडेट करें. बिल्ड पूरा होने पर, इस सेक्शन में इनसे जुड़ी जानकारी मौजूद होनी चाहिए.
pom.xml
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- Jib Plugin-->
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<version>3.2.0</version>
</plugin>
<!-- Maven Resources Plugin-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
</plugin>
</plugins>
</build>
बिल्ड फ़ाइल बदलने की सूचना मिलने पर Always
चुनें.
मेनिफ़ेस्ट जनरेट करें
Skaffold टूल, कंटेनर डेवलपमेंट को आसान बनाने के लिए इंटिग्रेट किए गए टूल उपलब्ध कराते हैं. इस चरण में, स्केलिंग की शुरुआत करें, जिससे Kubernetes YAML फ़ाइलें अपने-आप बन जाएंगी. यह प्रोसेस, Dockerfile जैसी कंटेनर इमेज की परिभाषाओं वाली डायरेक्ट्री की पहचान करने की कोशिश करती है. इसके बाद, हर डायरेक्ट्री के लिए डिप्लॉयमेंट और सर्विस मेनिफ़ेस्ट बनाती है.
प्रोसेस शुरू करने के लिए, नीचे दिया गया निर्देश चलाएं.
- टर्मिनल में नीचे दिया गया निर्देश चलाएं
skaffold init --generate-manifests
- जब कहा जाए, तब:
- अपने कर्सर को
Jib Maven Plugin
पर ले जाने के लिए, ऐरो का इस्तेमाल करें - विकल्प चुनने के लिए, स्पेसबार दबाएं.
- जारी रखने के लिए Enter दबाएं
- पोर्ट के लिए 8080 डालें
- कॉन्फ़िगरेशन सेव करने के लिए, y डालें
फ़ाइल फ़ोल्डर विज़, skaffold.yaml
और deployment.yaml
में दो फ़ाइलें जोड़ी गई हैं
ऐप्लिकेशन का नाम अपडेट करें
कॉन्फ़िगरेशन में शामिल डिफ़ॉल्ट मान वर्तमान में आपके ऐप्लिकेशन के नाम से मेल नहीं खाते. फ़ाइलों को डिफ़ॉल्ट मानों की बजाय अपने ऐप्लिकेशन के नाम का संदर्भ देने के लिए अपडेट करें.
- Skaffold कॉन्फ़िगरेशन में एंट्री बदलें
skaffold.yaml
खोलें- इमेज के उस नाम को चुनें जो फ़िलहाल
pom-xml-image
के तौर पर सेट है - राइट क्लिक करें और 'सभी घटनाएं बदलें' को चुनें
- नया नाम,
demo-app
के तौर पर लिखें
- Kubernetes कॉन्फ़िगरेशन में एंट्री बदलें
deployment.yaml
फ़ाइल खोलें- इमेज के उस नाम को चुनें जो फ़िलहाल
pom-xml-image
के तौर पर सेट है - राइट क्लिक करें और 'सभी घटनाएं बदलें' को चुनें
- नया नाम,
demo-app
के तौर पर लिखें
हॉट सिंक चालू करें
ऑप्टिमाइज़ किए गए हॉट रीलोड का अनुभव देने के लिए, आपको Jib की सिंक करने की सुविधा का इस्तेमाल करना होगा. इस चरण में, बिल्ड प्रोसेस में स्केल को इस सुविधा का इस्तेमाल करने के लिए कॉन्फ़िगर किया जाएगा.
ध्यान दें कि "सिंक करें" आप स्कैफ़ोल्ड कॉन्फ़िगरेशन में जिस प्रोफ़ाइल को कॉन्फ़िगर कर रहे हैं वह स्प्रिंग "सिंक" का इस्तेमाल करती है वह प्रोफ़ाइल जिसे आपने पिछले चरण में कॉन्फ़िगर किया है, जहां आपने Spring-dev-tools के लिए सहायता चालू की है.
- स्केलोल्ड कॉन्फ़िगरेशन अपडेट करें
skaffold.yaml फ़ाइल में, फ़ाइल के पूरे बिल्ड सेक्शन को नीचे दी गई जानकारी से बदलें. फ़ाइल के अन्य सेक्शन में बदलाव न करें.
skaffold.yaml
build:
artifacts:
- image: demo-app
jib:
project: com.example:demo
type: maven
args:
- --no-transfer-progress
- -Psync
fromImage: gcr.io/distroless/java:debug
sync:
auto: true
डिफ़ॉल्ट रास्ता जोड़ें
/src/main/java/com/example/springboot/ पर HelloController.java नाम की फ़ाइल बनाएं
डिफ़ॉल्ट http रूट बनाने के लिए, नीचे दिए गए कॉन्टेंट को फ़ाइल में चिपकाएं
HelloController.java
package com.example.springboot;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.beans.factory.annotation.Value;
@RestController
public class HelloController {
@Value("${target:local}")
String target;
@GetMapping("/")
public String hello()
{
return String.format("Hello from your %s environment!", target);
}
}
4. डेवलपमेंट प्रोसेस की जानकारी
इस सेक्शन में, आपको बुनियादी प्रोसेस जानने और स्टार्टर ऐप्लिकेशन के कॉन्फ़िगरेशन और सेटअप की पुष्टि करने के लिए, Cloud Code प्लगिन का इस्तेमाल करने के कुछ चरणों के बारे में बताया जाएगा.
Cloud Code, आपके डेवलपमेंट प्रोसेस को आसान बनाने के लिए skaffold के साथ इंटिग्रेट होता है. जब इन चरणों को GKE (जीकेई) पर डिप्लॉय किया जाता है, तो Cloud Code और Skaffold, आपके कंटेनर की इमेज अपने-आप बनाएंगे, उसे कंटेनर रजिस्ट्री में पुश करेंगे, और आपके ऐप्लिकेशन को GKE (जीकेई) पर डिप्लॉय कर देंगे. ऐसा, पर्दे के पीछे की गतिविधियों और डेवलपर फ़्लो से जुड़ी जानकारी को समझकर किया जा सकता है. Cloud Code, कंटेनर पर आधारित डेवलपमेंट के लिए पारंपरिक डीबग और हॉटसिंक क्षमताएं देकर आपकी डेवलपमेंट प्रोसेस को बेहतर बनाता है.
Kubernetes में डिप्लॉय करें
- Cloud Shell Editor में सबसे नीचे मौजूद पैनल में, Cloud Code फ़ाॅर्म चुनें
- सबसे ऊपर दिखने वाले पैनल में, Kubernetes पर डीबग करें चुनें. अगर पूछा जाए, तो मौजूदा Kubernetes संदर्भ इस्तेमाल करने के लिए 'हां' चुनें.
- पहली बार कमांड चलाने पर स्क्रीन के सबसे ऊपर एक प्रॉम्प्ट दिखेगा जिसमें पूछा जाएगा कि क्या आपको मौजूदा Kubernetes कॉन्टेक्स्ट चाहिए, तो "हां" चुनें और उसका इस्तेमाल मौजूदा संदर्भ के तौर पर करें.
- इसके बाद एक प्रॉम्प्ट दिखेगा, जिसमें पूछा जाएगा कि किस कंटेनर रजिस्ट्री का इस्तेमाल करना है. दी गई डिफ़ॉल्ट वैल्यू को स्वीकार करने के लिए, Enter दबाएं
- प्रोग्रेस और सूचनाएं देखने के लिए, सबसे नीचे मौजूद पैनल में आउटपुट टैब चुनें
- "Kubernetes: रन/डीबग - ज़्यादा जानकारी" चुनें अतिरिक्त विवरण और कंटेनर से लाइव स्ट्रीमिंग लॉग देखने के लिए दाईं ओर दिए गए चैनल ड्रॉप-डाउन में
- "Kubernetes: रन/डीबग" चुनकर, आसान बनाए गए व्यू पर वापस जाएं ड्रॉपडाउन से
- बिल्ड और टेस्ट पूरे होने के बाद, आउटपुट टैब में यह मैसेज दिखता है:
Resource deployment/demo-app status completed successfully
और एक यूआरएल दिखता है: "सर्विस डेमो-ऐप्लिकेशन से फ़ॉरवर्ड किया गया यूआरएल: http://localhost:8080" - Cloud Code टर्मिनल में, आउटपुट (http://localhost:8080) में मौजूद यूआरएल पर कर्सर घुमाएं. इसके बाद, दिखने वाले टूल टिप में 'वेब झलक खोलें' चुनें.
जवाब यह होगा:
Hello from your local environment!
ब्रेकपॉइंट इस्तेमाल करें
- /src/main/java/com/example/springboot/HeyController.java पर मौजूद HelloController.java ऐप्लिकेशन खोलें
return String.format("Hello from your %s environment!", target);
को देखने वाले रूट पाथ के लिए, रिटर्न स्टेटमेंट ढूंढें- लाइन नंबर की बाईं ओर मौजूद खाली जगह पर क्लिक करके, उस लाइन में एक ब्रेकपॉइंट जोड़ें. ब्रेकपॉइंट सेट होने का पता लगाने के लिए, लाल रंग का इंंडिकेटर दिखेगा
- अपने ब्राउज़र को रीलोड करें और ध्यान दें कि डीबगर इस प्रोसेस को ब्रेकपॉइंट पर रोक देता है. साथ ही, इससे आपको GKE (जीकेई) में रिमोट तरीके से चल रहे ऐप्लिकेशन के अलग-अलग सैंड स्टेट की जांच करने की अनुमति मिलती है
- जब तक आपको "टारगेट" नहीं मिल जाता, तब तक वैरिएबल सेक्शन में नीचे की ओर क्लिक करें वैरिएबल.
- मौजूदा वैल्यू को "स्थानीय" के तौर पर देखें
- वैरिएबल के नाम "टारगेट" पर दो बार क्लिक करें और पॉप-अप में, वैल्यू को "Cloud" जैसे कुछ अलग में बदलें
- डीबग कंट्रोल पैनल में 'जारी रखें' बटन पर क्लिक करें
- अपने ब्राउज़र में उस जवाब की समीक्षा करें जो अब आपकी डाली गई अपडेट की गई वैल्यू दिखाता है.
फिर से लोड करें
- कोई दूसरी वैल्यू दिखाने के लिए स्टेटमेंट बदलें. जैसे, "%s कोड का हैलो"
- फ़ाइल अपने-आप सेव हो जाती है और GKE (जीकेई) के रिमोट कंटेनर में सिंक हो जाती है
- अपडेट किए गए नतीजे देखने के लिए, अपना ब्राउज़र रीफ़्रेश करें.
- डीबग टूलबार में लाल रंग के स्क्वेयर पर क्लिक करके, डीबग करने वाले सेशन को रोकें
5. सीआरयूडी रेस्ट सर्विस की सुविधा आसानी से बनाई जा रही है
इस समय आपका ऐप्लिकेशन कंटेनर वाले डेवलपमेंट के लिए पूरी तरह से कॉन्फ़िगर हो गया है और आपने Cloud Code के साथ बेसिक डेवलपमेंट वर्कफ़्लो को समझ लिया है. नीचे दिए गए सेक्शन में, Google Cloud में मैनेज किए जा रहे डेटाबेस से कनेक्ट करके अन्य सर्विस एंडपॉइंट को जोड़कर, उन चीज़ों की प्रैक्टिस की जाती है जो आपने सीखी हैं.
डिपेंडेंसी कॉन्फ़िगर करें
ऐप्लिकेशन कोड, बाकी सेवा से जुड़े डेटा को बनाए रखने के लिए, डेटाबेस का इस्तेमाल करता है. पक्का करें कि ये डिपेंडेंसी उपलब्ध हैं. इसके लिए, pom.xl में ये चीज़ें जोड़ें
pom.xml
फ़ाइल खोलें और इन्हें कॉन्फ़िगरेशन के डिपेंडेंसी सेक्शन में जोड़ें
pom.xml
<!-- Database dependencies-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
बाकी सेवा को कोड करें
Quote.java
/src/main/java/com/example/springboot/ में कोट.java नाम की एक फ़ाइल बनाएं और नीचे दिए गए कोड में कॉपी करें. यह ऐप्लिकेशन में इस्तेमाल किए गए कोटेशन ऑब्जेक्ट के लिए, इकाई के मॉडल के बारे में बताता है.
package com.example.springboot;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.util.Objects;
@Entity
@Table(name = "quotes")
public class Quote
{
@Id
@Column(name = "id")
private Integer id;
@Column(name="quote")
private String quote;
@Column(name="author")
private String author;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getQuote() {
return quote;
}
public void setQuote(String quote) {
this.quote = quote;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Quote quote1 = (Quote) o;
return Objects.equals(id, quote1.id) &&
Objects.equals(quote, quote1.quote) &&
Objects.equals(author, quote1.author);
}
@Override
public int hashCode() {
return Objects.hash(id, quote, author);
}
}
QuoteRepository.java
src/main/java/com/example/springboot पर कोटRepository.java नाम की फ़ाइल बनाएं और नीचे दिए गए कोड में कॉपी करें
package com.example.springboot;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
public interface QuoteRepository extends JpaRepository<Quote,Integer> {
@Query( nativeQuery = true, value =
"SELECT id,quote,author FROM quotes ORDER BY RANDOM() LIMIT 1")
Quote findRandomQuote();
}
यह कोड, डेटा को सेव करके रखने के लिए JPA का इस्तेमाल करता है. यह क्लास Spring JPARepository
इंटरफ़ेस को बड़ा करती है और कस्टम कोड बनाने की अनुमति देती है. आपने कोड में, पसंद के मुताबिक findRandomQuote
तरीका जोड़ा है.
QuoteController.java
सेवा के लिए एंडपॉइंट दिखाने के लिए, QuoteController
क्लास यह सुविधा देगी.
src/main/java/com/example/springboot पर CutController.java नाम की एक फ़ाइल बनाएं और नीचे दिए गए कॉन्टेंट में कॉपी करें
package com.example.springboot;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class QuoteController {
private final QuoteRepository quoteRepository;
public QuoteController(QuoteRepository quoteRepository) {
this.quoteRepository = quoteRepository;
}
@GetMapping("/random-quote")
public Quote randomQuote()
{
return quoteRepository.findRandomQuote();
}
@GetMapping("/quotes")
public ResponseEntity<List<Quote>> allQuotes()
{
try {
List<Quote> quotes = new ArrayList<Quote>();
quoteRepository.findAll().forEach(quotes::add);
if (quotes.size()==0 || quotes.isEmpty())
return new ResponseEntity<List<Quote>>(HttpStatus.NO_CONTENT);
return new ResponseEntity<List<Quote>>(quotes, HttpStatus.OK);
} catch (Exception e) {
System.out.println(e.getMessage());
return new ResponseEntity<List<Quote>>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@PostMapping("/quotes")
public ResponseEntity<Quote> createQuote(@RequestBody Quote quote) {
try {
Quote saved = quoteRepository.save(quote);
return new ResponseEntity<Quote>(saved, HttpStatus.CREATED);
} catch (Exception e) {
System.out.println(e.getMessage());
return new ResponseEntity<Quote>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@PutMapping("/quotes/{id}")
public ResponseEntity<Quote> updateQuote(@PathVariable("id") Integer id, @RequestBody Quote quote) {
try {
Optional<Quote> existingQuote = quoteRepository.findById(id);
if(existingQuote.isPresent()){
Quote updatedQuote = existingQuote.get();
updatedQuote.setAuthor(quote.getAuthor());
updatedQuote.setQuote(quote.getQuote());
return new ResponseEntity<Quote>(updatedQuote, HttpStatus.OK);
} else {
return new ResponseEntity<Quote>(HttpStatus.NOT_FOUND);
}
} catch (Exception e) {
System.out.println(e.getMessage());
return new ResponseEntity<Quote>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@DeleteMapping("/quotes/{id}")
public ResponseEntity<HttpStatus> deleteQuote(@PathVariable("id") Integer id) {
try {
quoteRepository.deleteById(id);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
} catch (RuntimeException e) {
System.out.println(e.getMessage());
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}
डेटाबेस कॉन्फ़िगरेशन जोड़ें
application.yaml
सेवा से ऐक्सेस किए जाने वाले बैकएंड डेटाबेस के लिए कॉन्फ़िगरेशन जोड़ें. application.yaml
फ़ाइल नाम की फ़ाइल को src/main/resources
में बदलाव करें या बनाएं. साथ ही, बैकएंड के लिए पैरामीटर वाला Spring कॉन्फ़िगरेशन जोड़ें.
target: local spring: config: activate: on-profile: cloud-dev datasource: url: 'jdbc:postgresql://${DB_HOST:127.0.0.1}/${DB_NAME:quote_db}' username: '${DB_USER:user}' password: '${DB_PASS:password}' jpa: properties: hibernate: jdbc: lob: non_contextual_creation: true dialect: org.hibernate.dialect.PostgreSQLDialect hibernate: ddl-auto: update
डेटाबेस माइग्रेशन जोड़ें
src/main/resources/db/migration/ पर जाकर फ़ोल्डर बनाएं
एक एसक्यूएल फ़ाइल बनाएं: V1__create_quotes_table.sql
नीचे दिए गए कॉन्टेंट को फ़ाइल में चिपकाएं
V1__create_quotes_table.sql
CREATE TABLE quotes(
id INTEGER PRIMARY KEY,
quote VARCHAR(1024),
author VARCHAR(256)
);
INSERT INTO quotes (id,quote,author) VALUES (1,'Never, never, never give up','Winston Churchill');
INSERT INTO quotes (id,quote,author) VALUES (2,'While there''s life, there''s hope','Marcus Tullius Cicero');
INSERT INTO quotes (id,quote,author) VALUES (3,'Failure is success in progress','Anonymous');
INSERT INTO quotes (id,quote,author) VALUES (4,'Success demands singleness of purpose','Vincent Lombardi');
INSERT INTO quotes (id,quote,author) VALUES (5,'The shortest answer is doing','Lord Herbert');
Kubernetes कॉन्फ़िगरेशन
deployment.yaml
फ़ाइल में नीचे दिए गए बदलाव, ऐप्लिकेशन को CloudSQL इंस्टेंस से कनेक्ट करने की अनुमति देते हैं.
- TARGET - वैरिएबल को कॉन्फ़िगर करके उस परिवेश का संकेत देता है, जहां ऐप्लिकेशन निष्पादित होता है
- SPRING_PROFILES_ACTIVE - सक्रिय Spring प्रोफ़ाइल दिखाता है, जिसे
cloud-dev
पर कॉन्फ़िगर किया जाएगा - DB_Host - डेटाबेस का निजी आईपी, जिसे डेटाबेस इंस्टेंस बनाए जाने के बाद या Google Cloud Console के नेविगेशन मेन्यू में
SQL
पर क्लिक करके नोट किया जाता है - कृपया वैल्यू बदलें ! - DB_USER और DB_PASS - जैसा कि CloudSQL इंस्टेंस कॉन्फ़िगरेशन में सेट किया गया है, उसे GCP में सीक्रेट के तौर पर स्टोर किया गया है
नीचे दिए गए कॉन्टेंट का इस्तेमाल करके, अपने डिप्लॉयमेंट.yaml को अपडेट करें.
deployment.yaml
apiVersion: v1
kind: Service
metadata:
name: demo-app
labels:
app: demo-app
spec:
ports:
- port: 8080
protocol: TCP
clusterIP: None
selector:
app: demo-app
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-app
labels:
app: demo-app
spec:
replicas: 1
selector:
matchLabels:
app: demo-app
template:
metadata:
labels:
app: demo-app
spec:
containers:
- name: demo-app
image: demo-app
env:
- name: PORT
value: "8080"
- name: TARGET
value: "Local Dev - CloudSQL Database - K8s Cluster"
- name: SPRING_PROFILES_ACTIVE
value: cloud-dev
- name: DB_HOST
value: ${DB_INSTANCE_IP}
- name: DB_PORT
value: "5432"
- name: DB_USER
valueFrom:
secretKeyRef:
name: gke-cloud-sql-secrets
key: username
- name: DB_PASS
valueFrom:
secretKeyRef:
name: gke-cloud-sql-secrets
key: password
- name: DB_NAME
valueFrom:
secretKeyRef:
name: gke-cloud-sql-secrets
key: database
DB_Host वैल्यू को अपने डेटाबेस के पते से बदलें
export DB_INSTANCE_IP=$(gcloud sql instances describe quote-db-instance \
--format=json | jq \
--raw-output ".ipAddresses[].ipAddress")
envsubst < deployment.yaml > deployment.new && mv deployment.new deployment.yaml
ऐप्लिकेशन डिप्लॉय करें और उसकी पुष्टि करें
- Cloud Shell Editor में सबसे नीचे मौजूद पैनल में, Cloud Code चुनें. इसके बाद, स्क्रीन पर सबसे ऊपर मौजूद Kubernetes पर डीबग करें चुनें.
- बिल्ड और टेस्ट पूरे होने के बाद, आउटपुट टैब में यह मैसेज दिखता है:
Resource deployment/demo-app status completed successfully
और एक यूआरएल दिखता है: "सर्विस डेमो-ऐप्लिकेशन से फ़ॉरवर्ड किया गया यूआरएल: http://localhost:8080" - रैंडम कोट देखें
Cloud Shell Terminal से, रैंडम-कोट वाले एंडपॉइंट के लिए, नीचे दिए गए कमांड को कई बार चलाएं. बार-बार किए गए कॉल पर अलग-अलग कोट के रूप में आने पर देखें
curl -v 127.0.0.1:8080/random-quote
- कोटेशन जोड़ें
नीचे दिए गए निर्देश का इस्तेमाल करके, id=6 का इस्तेमाल करके एक नया कोटेशन बनाएं और देखें कि अनुरोध वापस आया है
curl -v -H 'Content-Type: application/json' -d '{"id":"6","author":"Henry David Thoreau","quote":"Go confidently in the direction of your dreams! Live the life you have imagined"}' -X POST 127.0.0.1:8080/quotes
- कोटेशन मिटाना
अब मिटाने के तरीके से जोड़े गए कोटेशन को मिटाएं और HTTP/1.1 204
रिस्पॉन्स कोड देखें.
curl -v -X DELETE 127.0.0.1:8080/quotes/6
- सर्वर की गड़बड़ी
एंट्री मिटाए जाने के बाद पिछला अनुरोध फिर से चलाकर, गड़बड़ी की स्थिति का अनुभव करें
curl -v -X DELETE 127.0.0.1:8080/quotes/6
ध्यान दें कि रिस्पॉन्स, HTTP:500 Internal Server Error
दिखाता है.
ऐप्लिकेशन को डीबग करना
पिछले सेक्शन में, जब आपने ऐसी एंट्री को मिटाने की कोशिश की थी जो डेटाबेस में नहीं थी, तो आपको ऐप्लिकेशन में गड़बड़ी की स्थिति मिली. इस सेक्शन में, समस्या का पता लगाने के लिए एक ब्रेकपॉइंट सेट किया जाएगा. DELETE कार्रवाई के दौरान यह गड़बड़ी हुई. इसलिए, छूट कंट्रोलर क्लास के साथ काम किया जाएगा.
- src.main.java.com.example.springboot.उसकाController.java खोलें
deleteQuote()
तरीका ढूंढें- वह लाइन ढूंढें जहां डेटाबेस से किसी आइटम को मिटाएं:
quoteRepository.deleteById(id);
- लाइन नंबर की बाईं ओर मौजूद खाली जगह पर क्लिक करके, उस लाइन पर एक ब्रेकपॉइंट सेट करें.
- एक लाल इंंडिकेटर दिखेगा कि ब्रेकपॉइंट सेट हो गया है
delete
निर्देश फिर से चलाएं
curl -v -X DELETE 127.0.0.1:8080/quotes/6
- बाईं ओर मौजूद कॉलम में मौजूद आइकॉन पर क्लिक करके, डीबग व्यू पर वापस जाएं
- ChatController क्लास में रोकी गई डीबग लाइन को देखें.
- डीबगर में,
step over
आइकॉन पर क्लिक करें और देखें कि कोई अपवाद दिख रहा है या नहीं - देखें कि बहुत सामान्य
RuntimeException was caught.
यह क्लाइंट को अंदरूनी सर्वर गड़बड़ी एचटीटीपी 500 दिखाता है, जो सही नहीं है.
Trying 127.0.0.1:8080... * Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0) > DELETE /quotes/6 HTTP/1.1 > Host: 127.0.0.1:8080 > User-Agent: curl/7.74.0 > Accept: */* > * Mark bundle as not supporting multiuse < HTTP/1.1 500 < Content-Length: 0 < Date: < * Connection #0 to host 127.0.0.1 left intact
कोड अपडेट करना
यह कोड गलत है और EmptyResultDataAccessException
अपवाद को पहचानने और एचटीटीपी 404 'नहीं मिला' स्थिति कोड को वापस भेजने के लिए, अपवाद ब्लॉक को फिर से तैयार किया जाना चाहिए.
गड़बड़ी ठीक करें.
- डीबग सेशन अब भी चल रहा है. इसके बाद, "जारी रखें" को दबाकर अनुरोध को पूरा करें बटन पर क्लिक करें.
- इसके बाद कोड में यह ब्लॉक जोड़ें:
} catch (EmptyResultDataAccessException e){
return new ResponseEntity<HttpStatus>(HttpStatus.NOT_FOUND);
}
तरीका कुछ ऐसा दिखना चाहिए
public ResponseEntity<HttpStatus> deleteQuote(@PathVariable("id") Integer id) { try { quoteRepository.deleteById(id); return new ResponseEntity<>(HttpStatus.NO_CONTENT); } catch(EmptyResultDataAccessException e){ return new ResponseEntity<HttpStatus>(HttpStatus.NOT_FOUND); } catch (RuntimeException e) { System.out.println(e.getMessage()); return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); } }
- मिटाएं निर्देश को फिर से चलाएं
curl -v -X DELETE 127.0.0.1:8080/quotes/6
- डीबगर पर जाएं और देखें कि
EmptyResultDataAccessException
को पकड़ा जा रहा है और कॉलर को एचटीटीपी 404 नहीं मिला.
Trying 127.0.0.1:8080... * Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0) > DELETE /quotes/6 HTTP/1.1 > Host: 127.0.0.1:8080 > User-Agent: curl/7.74.0 > Accept: */* > * Mark bundle as not supporting multiuse < HTTP/1.1 404 < Content-Length: 0 < Date: < * Connection #0 to host 127.0.0.1 left intact
- डीबग टूलबार में लाल रंग के स्क्वेयर पर क्लिक करके, डीबग करने वाले सेशन को रोकें
6. साफ़-सफ़ाई सेवा
बधाई हो! इस लैब में, आपने शुरुआत से एक नया Java ऐप्लिकेशन बनाया है और उसे कंटेनर के साथ असरदार तरीके से काम करने के लिए कॉन्फ़िगर किया है. इसके बाद, आपने पुराने ऐप्लिकेशन स्टैक में मिलने वाले डेवलपर फ़्लो का इस्तेमाल करके, अपने ऐप्लिकेशन को किसी रिमोट GKE क्लस्टर में डिप्लॉय और डीबग किया.
लैब पूरा होने के बाद, स्टोरेज खाली करने के लिए:
- लैब में इस्तेमाल की गई फ़ाइलें मिटाना
cd ~ && rm -rf container-developer-workshop
- प्रोजेक्ट को मिटाएं, ताकि उससे जुड़े सभी इन्फ़्रास्ट्रक्चर और संसाधनों को हटाया जा सके