النقل من تطبيق Google App Engine Java إلى "تشغيل السحابة الإلكترونية باستخدام Jib"

1. نظرة عامة

تهدف سلسلة الدروس التطبيقية حول الترميز هذه (البرامج التعليمية العملية التي يمكن إكمالها بالسرعة التي تناسبك) إلى مساعدة مطوّري تطبيقات Java على Google App Engine (الإصدار العادي) في تحديث تطبيقاتهم من خلال إرشادهم خلال سلسلة من عمليات نقل البيانات. باتّباع هذه الخطوات، يمكنك تعديل تطبيقك ليصبح أكثر قابلية للنقل، ويمكنك اختيار وضعه في حاوية لاستخدامه مع Cloud Run، وهي خدمة شقيقة لخدمة App Engine لاستضافة الحاويات على Google Cloud، وخدمات أخرى لاستضافة الحاويات.

يعلّمك هذا البرنامج التعليمي كيفية إنشاء حاوية لتطبيق App Engine من أجل نشره على خدمة Cloud Run المُدارة بالكامل باستخدام Jib. باستخدام Jib، يمكنك إنشاء صور Docker، وهي منصة معروفة في المجال لتطوير التطبيقات وشحنها وتشغيلها في حاويات.

بالإضافة إلى تعليمك الخطوات المطلوبة للانتقال من App Engine إلى Cloud Run، ستتعلّم أيضًا كيفية ترقية تطبيق Java 8 App Engine إلى Java 17.

إذا كان تطبيقك يستخدم خدمات App Engine المجمّعة القديمة أو ميزات App Engine الأخرى بشكل مكثّف، ننصحك بنقل البيانات من هذه الخدمات المجمّعة أو استبدال هذه الميزات قبل الانتقال إلى Cloud Run. إذا كنت بحاجة إلى مزيد من الوقت للبحث في خيارات النقل أو أردت مواصلة استخدام الخدمات المجمّعة القديمة في الوقت الحالي، يمكنك مواصلة الوصول إلى الخدمات المجمّعة في App Engine لإصدار Java 11/17 عند الترقية إلى وقت تشغيل أحدث. عندما يصبح تطبيقك أكثر قابلية للنقل، يمكنك الرجوع إلى هذا الدرس التطبيقي حول الترميز لمعرفة كيفية تطبيق التعليمات على تطبيقك.

ستتعرَّف على كيفية إجراء ما يلي:

  • استخدام Cloud Shell
  • تفعيل واجهات برمجة التطبيقات Cloud Run وArtifact Registry وCloud Build
  • وضع تطبيقك في حاوية باستخدام Jib وCloud Build
  • نشر صور الحاويات على Cloud Run

المتطلبات

استطلاع

كيف ستستخدم هذا البرنامج التعليمي؟

قراءة المحتوى فقط قراءة المحتوى وإكمال التمارين

كيف تقيّم تجربتك مع Java؟

مبتدئ متوسط متمكّن

ما هو تقييمك لتجربة استخدام خدمات Google Cloud؟

مبتدئ متوسط متقدّم

2. الخلفية

توفّر أنظمة "المنصة كخدمة" (PaaS)، مثل App Engine وCloud Functions، العديد من المزايا لفريقك وتطبيقك، مثل السماح لمشرفي النظام وDevOps بالتركيز على إنشاء الحلول. باستخدام المنصات التي لا تتطلّب خادمًا، يمكن لتطبيقك أن يوسّع نطاقه تلقائيًا حسب الحاجة، ويقلّص نطاقه إلى الصفر مع إمكانية الدفع حسب الاستخدام للمساعدة في التحكّم في التكاليف، واستخدام مجموعة متنوعة من لغات التطوير الشائعة.

ومع ذلك، فإنّ مرونة الحاويات جذّابة أيضًا. بفضل إمكانية اختيار أي لغة وأي مكتبة وأي برنامج ثنائي، تمنحك الحاويات أفضل ما في كلا الخيارين: سهولة استخدام الحوسبة بدون خادم ومرونة الحاويات. هذا هو الهدف من Cloud Run.

لا يهدف هذا الدرس التطبيقي حول الترميز إلى تعليمك كيفية استخدام Cloud Run، بل يمكنك الاطّلاع على مستندات Cloud Run لمعرفة ذلك. الهدف هنا هو أن تتعرّف على كيفية إنشاء حاوية لتطبيق App Engine من أجل Cloud Run (أو الخدمات الأخرى المستضافة في حاويات). هناك بعض النقاط التي يجب معرفتها قبل المتابعة، وأهمها أنّ تجربة المستخدم ستكون مختلفة قليلاً.

في هذا الدرس التطبيقي، ستتعلّم كيفية إنشاء الحاويات ونشرها. ستتعرَّف على كيفية:

  • تضمين تطبيقك في حاوية باستخدام Jib
  • إيقاف استخدام إعدادات App Engine
  • ويمكنك اختياريًا تحديد خطوات الإنشاء لخدمة Cloud Build.

سيتضمّن ذلك التوقّف عن استخدام بعض الميزات الخاصة بـ App Engine. إذا كنت تفضّل عدم اتّباع هذا المسار، يمكنك الترقية إلى وقت تشغيل Java 11/17 مع إبقاء تطبيقاتك على App Engine بدلاً من ذلك.

3- الإعداد/العمل التحضيري

1. إعداد المشروع

في هذا البرنامج التعليمي، ستستخدم تطبيقًا نموذجيًا من مستودع appengine-java-migration-samples في مشروع جديد تمامًا. تأكَّد من أنّ المشروع يتضمّن حساب فوترة نشطًا.

إذا كنت تنوي نقل تطبيق حالي على App Engine إلى Cloud Run، يمكنك استخدام هذا التطبيق بدلاً من ذلك.

نفِّذ الأمر التالي لتفعيل واجهات برمجة التطبيقات اللازمة لمشروعك:

gcloud services enable artifactregistry.googleapis.com cloudbuild.googleapis.com run.googleapis.com

2. الحصول على نموذج تطبيق أساسي

استنسِخ نموذج التطبيق إما على جهازك أو على Cloud Shell، ثم انتقِل إلى المجلد baseline.

العينة هي تطبيق Datastore مستند إلى Java 8 وServlet ومخصّص للنشر على App Engine. اتّبِع التعليمات الواردة في ملف README حول كيفية إعداد هذا التطبيق لنشره على App Engine.

3. (اختياري) نشر تطبيق أساسي

لا يلزم اتّخاذ الخطوات التالية إلا إذا أردت التأكّد من أنّ التطبيق يعمل على App Engine قبل نقل البيانات إلى Cloud Run.

يُرجى الرجوع إلى الخطوات الواردة في ملف README.md:

  1. تثبيت واجهة سطر الأوامر gcloud أو إعادة التعرّف عليها
  2. ابدأ gcloud CLI لمشروعك باستخدام gcloud init
  3. إنشاء مشروع App Engine باستخدام gcloud app create
  4. نشر نموذج التطبيق على App Engine
./mvnw package appengine:deploy -Dapp.projectId=$PROJECT_ID
  1. التأكّد من أنّ التطبيق يعمل على App Engine بدون مشاكل

4. إنشاء مستودع Artifact Registry

بعد إنشاء حاوية لتطبيقك، ستحتاج إلى مكان لإرسال الصور وتخزينها. الطريقة المقترَحة لتنفيذ ذلك على Google Cloud هي استخدام Artifact Registry.

أنشئ المستودع الذي يحمل الاسم migration باستخدام gcloud على النحو التالي:

gcloud artifacts repositories create migration --repository-format=docker \
--description="Docker repository for the migrated app" \
--location="northamerica-northeast1"

يُرجى العِلم أنّ هذا المستودع يستخدم نوع التنسيق docker، ولكن تتوفّر عدة أنواع من المستودعات.

في هذه المرحلة، يكون لديك تطبيق App Engine الأساسي، ويكون مشروعك على Google Cloud جاهزًا لنقل البيانات إلى Cloud Run.

4. تعديل ملفات التطبيق

في الحالات التي يستخدم فيها تطبيقك خدمات App Engine المجمّعة القديمة أو إعداداتها أو ميزات أخرى خاصة بـ App Engine، ننصحك بمواصلة الوصول إلى هذه الخدمات أثناء الترقية إلى وقت التشغيل الجديد. يوضّح هذا الدرس التطبيقي حول الترميز مسار نقل للتطبيقات التي تستخدم حاليًا خدمات مستقلة، أو يمكن إعادة تصميمها بشكل معقول للقيام بذلك.

1. الترقية إلى Java 17

إذا كان تطبيقك يستخدم Java 8، ننصحك بالترقية إلى إصدار أحدث من الإصدارات المرشّحة للدعم الطويل الأمد، مثل الإصدار 11 أو 17، لمواكبة تحديثات الأمان والاستفادة من ميزات اللغة الجديدة.

ابدأ بتعديل السمات في pom.xml لتضمين ما يلي:

<properties>
    <java.version>17</java.version>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
</properties>

سيؤدي ذلك إلى ضبط إصدار المشروع على 17، وإعلام المكوّن الإضافي لبرنامج الترجمة بأنّك تريد الوصول إلى ميزات لغة Java 17، وأنّك تريد أن تكون الفئات التي تم تجميعها متوافقة مع Java 17 JVM.

2. تضمين خادم ويب

هناك عدد من الاختلافات بين App Engine وCloud Run التي يجب أخذها في الاعتبار عند الانتقال بينهما. أحد الاختلافات هو أنّه في حين أنّ وقت تشغيل Java 8 في App Engine كان يوفّر خادم Jetty ويديره للتطبيقات التي يستضيفها، لا تفعل Cloud Run ذلك. سنستخدم Spring Boot لتوفير خادم ويب وحاوية servlet.

أضِف الاعتمادات التالية:

<dependencies>
<!-- ... -->
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
       <version>2.6.6</version>
       <exclusions>
           <!-- Exclude the Tomcat dependency -->
           <exclusion>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter-tomcat</artifactId>
           </exclusion>
       </exclusions>
   </dependency>
   <!-- Use Jetty instead -->
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-jetty</artifactId>
       <version>2.6.6</version>
   </dependency>
<!-- ... -->
</dependencies>

تضمّن Spring Boot خادم Tomcat تلقائيًا، ولكن سيستبعد هذا النموذج هذا العنصر ويستخدم Jetty لتقليل الاختلافات في السلوك التلقائي بعد نقل البيانات. يمكننا أيضًا ضبط إصدار Jetty ليكون مطابقًا للإصدار الذي يوفّره App Engine بدون أي إعدادات إضافية.

<properties>
    <java.version>17</java.version>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
    <jetty.version>9.4.46.v20220331</jetty.version>
</properties>

3. إعداد Spring Boot

مع أنّ Spring Boot ستتمكّن من إعادة استخدام برامج معالجة طلبات HTTP بدون تعديل، إلا أنّها ستتطلّب بعض الإعدادات لتسهيل العثور عليها.

أنشئ فئة MigratedServletApplication.java التالية في حزمة com.example.appengine:

package com.example.appengine;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;

@ServletComponentScan
@SpringBootApplication
@EnableAutoConfiguration
public class MigratedServletApplication {
    public static void main(String[] args) {
        SpringApplication.run(MigratedServletApplication.class, args);
    }
}

يُرجى العِلم أنّ ذلك يشمل التعليق التوضيحي @ServletComponentScan الذي سيبحث (في الحزمة الحالية تلقائيًا) عن أي @WebServlets، وسيتيحها على النحو المتوقّع.

4. تعبئة التطبيق كملف JAR

على الرغم من إمكانية إنشاء حاوية لتطبيقك باستخدام Jib بدءًا من ملف war، يصبح الأمر أسهل إذا حزّمت تطبيقك كملف JAR قابل للتنفيذ. لن يتطلّب ذلك الكثير من الإعداد، خاصةً للمشاريع التي تستخدم Maven كأداة إنشاء، لأنّ حزمة jar هي السلوك التلقائي.

أزِل العلامة packaging في الملف pom.xml:

<packaging>war</packaging>

بعد ذلك، أضِف spring-boot-maven-plugin:

<plugins>
<!-- ... -->
  <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <version>2.6.6</version>
  </plugin>
<!-- ... -->
</plugins>

5- نقل البيانات من إعدادات App Engine وخدماتها وتبعياتها

كما ذكرنا في بداية هذا الدرس التطبيقي حول الترميز، تم تصميم Cloud Run وApp Engine لتقديم تجارب مستخدم مختلفة. يجب إعادة إنشاء بعض الميزات التي يوفّرها App Engine بدون أي إعدادات إضافية، مثل خدمات Cron وقائمة انتظار المهام، يدويًا، وسنتناولها بمزيد من التفاصيل في وحدات لاحقة.

لا يستخدم نموذج التطبيق الخدمات المجمّعة القديمة، ولكن يمكن للمستخدمين الذين تستخدم تطبيقاتهم هذه الخدمات الرجوع إلى الأدلة التالية:

بما أنّك ستنفّذ عمليات النشر على Cloud Run من الآن فصاعدًا، يمكن إزالة appengine-maven-plugin:

<plugin>
 <groupId>com.google.cloud.tools</groupId>
 <artifactId>appengine-maven-plugin</artifactId>
 <version>2.4.1</version>
 <configuration>
   <!-- can be set w/ -DprojectId=myProjectId on command line -->
   <projectId>${app.projectId}</projectId>
   <!-- set the GAE version or use "GCLOUD_CONFIG" for an autogenerated GAE version -->
   <version>GCLOUD_CONFIG</version>
 </configuration>
</plugin>

5- تضمين التطبيق في حاوية

في هذه المرحلة، يمكنك نشر تطبيقك يدويًا على Cloud Run مباشرةً من رمز المصدر. هذا خيار ممتاز يستخدم Cloud Build في الخلفية لتوفير تجربة نشر بدون تدخل منك. سنتناول عمليات نشر المصدر بمزيد من التفصيل في وحدات تدريبية لاحقة.

بدلاً من ذلك، إذا كنت بحاجة إلى مزيد من التحكّم في طريقة نشر تطبيقك، يمكنك تحقيق ذلك من خلال تحديد ملف cloudbuild.yaml يوضّح خطوات الإصدار المقصودة بشكلٍ صريح:

1. تحديد ملف cloudbuild.yaml

أنشئ ملف cloudbuild.yaml التالي في المستوى نفسه الذي يقع فيه ملف pom.xml:

steps:
  # Test your build
  - name: maven:eclipse-temurin
    entrypoint: mvn
    args: ["test"]
  # Build with Jib
  - name: maven:eclipse-temurin
    entrypoint: mvn
    args: [ "compile", "com.google.cloud.tools:jib-maven-plugin:3.2.1:build", "-Dimage=northamerica-northeast1-docker.pkg.dev/PROJECT_ID/migration/visitors:jib"]
  # Deploy to Cloud Run
  - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
    entrypoint: gcloud
    args: [ 'run', 'deploy', 'visitors', '--image', 'northamerica-northeast1-docker.pkg.dev/PROJECT_ID/migration/visitors:jib', '--region', 'northamerica-northeast1', '--allow-unauthenticated']

بعد أن نطلب من Cloud Build اتّباع هذه الخطوات، سيتم تنفيذ ما يلي:

  1. إجراء الاختبارات باستخدام ./mvnw test
  2. إنشاء صورتك ونقلها ووضع علامة عليها في Artifact Registry باستخدام Jib
  3. نشر صورتك على Cloud Run باستخدام gcloud run deploy

يُرجى العِلم أنّه يتم توفير ‘visitors' إلى Cloud Run كاسم الخدمة المطلوب. يتيح الخيار –allow-unauthenticated للمستخدمين زيارة تطبيق الويب بدون الحاجة إلى المصادقة. احرص على استبدال PROJECT_ID برقم تعريف مشروعك في ملف cloudbuild.yaml .

بعد ذلك، أضِف عمليات ربط سياسات "إدارة الهوية وإمكانية الوصول" التالية للسماح لحساب خدمة Cloud Build بالوصول إلى Artifact Registry:

export PROJECT_ID=$(gcloud config list --format 'value(core.project)')
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)" )

gcloud projects add-iam-policy-binding $PROJECT_ID \
--member=serviceAccount:$PROJECT_NUMBER@cloudbuild.gserviceaccount.com \
--role=roles/run.admin \
--project=$PROJECT_ID
gcloud iam service-accounts add-iam-policy-binding $PROJECT_NUMBER-compute@developer.gserviceaccount.com \
--member=serviceAccount:$PROJECT_NUMBER@cloudbuild.gserviceaccount.com \
--role roles/iam.serviceAccountUser --project=$PROJECT_ID

2. تنفيذ عملية التصميم

بعد أن أبلغت Cloud Build بالخطوات المطلوبة للإنشاء، أصبحت جاهزًا للنشر بنقرة واحدة.

نفِّذ الأمر التالي:

gcloud builds submit

بعد انتهاء العملية، سيتم إنشاء صورة الحاوية وتخزينها في Artifact Registry ونشرها على Cloud Run.

في نهاية هذا الدرس التطبيقي حول الترميز، يجب أن يبدو تطبيقك مثل التطبيق في java17-and-cloud-run/finish.

وإلى هنا، فقد تحققت رغبتك! لقد نقلت بنجاح تطبيق Java 8 App Engine إلى Java 17 وCloud Run، وأصبح لديك الآن فهم أوضح للعمل المطلوب عند التبديل والاختيار بين خيارات الاستضافة.

6. الملخّص/التنظيف

تهانينا، لقد أجريت عملية الترقية والتضمين في حاوية ونقل البيانات لتطبيقك، وبذلك تكون قد أكملت هذا البرنامج التعليمي.

من هنا، الخطوة التالية هي التعرّف على المزيد حول ميزات CI/CD وأمان سلسلة الإمداد للبرامج التي أصبحت في متناول يدك الآن بعد أن أصبح بإمكانك النشر باستخدام Cloud Build:

اختياري: تنظيف الخدمة و/أو إيقافها

إذا نشرت التطبيق النموذجي على App Engine أثناء هذا البرنامج التعليمي، تذكَّر إيقاف التطبيق لتجنُّب تحمّل رسوم. عندما تكون مستعدًا للانتقال إلى الدرس التطبيقي حول الترميز التالي، يمكنك إعادة تفعيله. عند إيقاف تطبيقات App Engine، لن تتلقّى أي زيارات تؤدي إلى تحمّل رسوم، ولكن قد يتم تحصيل رسوم مقابل استخدام Datastore إذا تجاوز الحصة المجانية، لذا احذف ما يكفي من البيانات لكي لا تتجاوز هذا الحد.

من ناحية أخرى، إذا كنت لن تواصل عمليات النقل وأردت حذف كل شيء نهائيًا، يمكنك إما حذف خدمتك أو إيقاف مشروعك بالكامل.

7. مراجع إضافية

مشاكل/ملاحظات حول دروس الترميز التطبيقية الخاصة بوحدة نقل البيانات في App Engine

إذا واجهت أي مشاكل في هذا الدرس العملي، يُرجى البحث عن مشكلتك أولاً قبل إرسالها. روابط للبحث عن مشاكل جديدة وإنشائها:

مراجع لنقل البيانات

مراجع متوفرة على الإنترنت

في ما يلي مراجع على الإنترنت قد تكون ذات صلة بهذا البرنامج التعليمي:

App Engine

معلومات أخرى حول السحابة الإلكترونية

الفيديوهات

الترخيص

يخضع هذا العمل لترخيص المشاع الإبداعي مع نسب العمل إلى مؤلفه 2.0 Generic License.