التشغيل السريع: إنشاء دالة Java في Azure من سطر الأوامر

استخدم أدوات سطر الأوامر لإنشاء دالة Java تستجيب لطلبات HTTP. اختبر التعليمات البرمجية محليًا، ثم انشرها إلى بيئة بلا خادم Azure Functions.

يؤدي إكمال هذه البداية السريعة إلى تكبد تكلفة صغيرة تبلغ بضعة سنتات أمريكية أو أقل في حساب Azure الخاص بك.

إذا لم يكن Maven هو أداة التطوير المفضلة لديك، فتحقق من البرامج التعليمية المماثلة لمطوري Java باستخدام ⁧⁩Gradle⁧⁩ و⁧⁩IntelliJ IDEA⁧⁩ و⁧⁩Visual Studio Code⁧⁩.

1. إعداد بيئتك

قبل أن تبدأ، يجب أن يكون لديك ما يلي:

التحقق من المتطلبات الأساسية

  • في نافذة طرفية أو أوامر، قم بتشغيل func --version للتحقق من أن أدوات Azure Functions Core Tools هي الإصدار 3.x.

  • قم بتشغيل ⁧az --version⁩ للتحقق من أن إصدار Azure CLI هو 2.4 أو أحدث.

  • قم بتشغيل ⁧az login⁩ لتسجيل الدخول إلى Azure والتأكد من أن الاشتراك نشط.



2. إنشاء مشروع دالة محلية

في وظائف Azure، يعد مشروع الدالة حاوية لدالة فردية واحدة أو أكثر تستجيب كل منها لمشغل معين. تشترك جميع الدوال في المشروع في نفس التكوينات المحلية والاستضافة. في هذا القسم، يمكنك إنشاء مشروع دالة يحتوي على دالة واحدة.

  1. في مجلد فارغ، قم بتشغيل الأمر التالي لإنشاء مشروع الدالات من ⁧⁩نموذج Maven الأصلي⁧⁩.

    mvn archetype:generate -DarchetypeGroupId=com.microsoft.azure -DarchetypeArtifactId=azure-functions-archetype -DjavaVersion=8
    

    لتشغيل الوظائف على Java 11

    استخدم -DjavaVersion=11 إذا كنت تريد تشغيل دالاتك على Java 11. لمعرفة المزيد، راجع ⁧⁩إصدارات Java⁧⁩.

  2. يطلب منك Maven القيم اللازمة لإنهاء إنشاء المشروع عند النشر. توفير القيم التالية عند المطالبة:

    المطالبة القيمة الوصف
    ⁩groupId⁧ com.fabrikam قيمة تُعرّف المشروع الخاص بك بشكل فريد عبر جميع المشاريع، باتباع ⁧⁩قواعد تسمية الحزمة⁧⁩ لـ Java التالية.
    ⁩artifactId⁧ fabrikam-functions قيمة تمثل اسم jar، بدون رقم إصدار.
    ⁩إصدار⁧ 1.0-SNAPSHOT اختر القيمة الافتراضية.
    ⁩الحزمة⁧ com.fabrikam قيمة تمثل حزمة Java للتعليمات البرمجية للدالة التي تم إنشاؤها. استخدم الافتراضي.
  3. اكتب ⁧Y⁩ أو اضغط إدخال للتأكيد.

    يقوم Maven بإنشاء ملفات المشروع في مجلد جديد باسم ⁧⁩artifactId⁧⁩، وهو في هذا المثال⁧fabrikam-functions⁩.

  4. انتقل إلى مجلد المشروع:

    cd fabrikam-functions
    

ما الذي تم إنشاؤه في المجلد LocalFunctionProj؟

يحتوي هذا المجلد على ملفات مختلفة للمشروع، مثل ⁧⁩Function.java⁧⁩ و⁧⁩FunctionTest.java⁧⁩ و⁧⁩pom.xml⁧⁩. هناك أيضًا ملفات تكوينات تسمى ⁧⁩local.settings.json⁧⁩ و⁧⁩host.json⁧⁩. لأن ⁧⁩local.settings.json⁧⁩ يمكن أن يحتوي على أسرار تم تنزيلها من Azure، يتم استبعاد الملف من التحكم في المصدر افتراضيا في ملف ⁧⁩.gitignore⁧⁩.


رمز للوظيفة.java

تحتوي ⁧⁩Function.java⁧⁩ على ⁧run⁩ أسلوب يتلقى بيانات الطلب في المتغير ⁧request⁩ وهو⁧⁩HttpRequestMessage⁧⁩ التي تم تمييزها بتعليق توضيحي ⁧⁩HttpTrigger⁧⁩ الذي يعرف سلوك المشغل.

/**
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See License.txt in the project root for
 * license information.
 */

package com.functions;

import com.microsoft.azure.functions.ExecutionContext;
import com.microsoft.azure.functions.HttpMethod;
import com.microsoft.azure.functions.HttpRequestMessage;
import com.microsoft.azure.functions.HttpResponseMessage;
import com.microsoft.azure.functions.HttpStatus;
import com.microsoft.azure.functions.annotation.AuthorizationLevel;
import com.microsoft.azure.functions.annotation.FixedDelayRetry;
import com.microsoft.azure.functions.annotation.FunctionName;
import com.microsoft.azure.functions.annotation.HttpTrigger;

import java.util.Optional;

/**
 * Azure Functions with HTTP Trigger.
 */
public class Function {
    /**
     * This function listens at endpoint "/api/HttpExample". Two ways to invoke it using "curl" command in bash:
     * 1. curl -d "HTTP Body" {your host}/api/HttpExample
     * 2. curl "{your host}/api/HttpExample?name=HTTP%20Query"
     */
    @FunctionName("HttpExample")
    public HttpResponseMessage run(
            @HttpTrigger(
                name = "req",
                methods = {HttpMethod.GET, HttpMethod.POST},
                authLevel = AuthorizationLevel.ANONYMOUS)
                HttpRequestMessage<Optional<String>> request,
            final ExecutionContext context) {
        context.getLogger().info("Java HTTP trigger processed a request.");

        // Parse query parameter
        final String query = request.getQueryParameters().get("name");
        final String name = request.getBody().orElse(query);

        if (name == null) {
            return request.createResponseBuilder(HttpStatus.BAD_REQUEST).body("Please pass a name on the query string or in the request body").build();
        } else {
            return request.createResponseBuilder(HttpStatus.OK).body("Hello, " + name).build();
        }
    }

    public static int count = 1;

    /**
     * This function listens at endpoint "/api/HttpExampleRetry". The function is re-executed in case of errors until the maximum number of retries occur.
     * Retry policies: https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-error-pages?tabs=java
     */
    @FunctionName("HttpExampleRetry")
    @FixedDelayRetry(maxRetryCount = 3, delayInterval = "00:00:05")
    public HttpResponseMessage HttpExampleRetry(
        @HttpTrigger(
            name = "req",
            methods = {HttpMethod.GET, HttpMethod.POST},
            authLevel = AuthorizationLevel.ANONYMOUS)
            HttpRequestMessage<Optional<String>> request,
        final ExecutionContext context) throws Exception {
        context.getLogger().info("Java HTTP trigger processed a request.");

        if(count<3) {
            count ++;
            throw new Exception("error");
        }

        // Parse query parameter
        final String query = request.getQueryParameters().get("name");
        final String name = request.getBody().orElse(query);

        if (name == null) {
            return request.createResponseBuilder(HttpStatus.BAD_REQUEST).body("Please pass a name on the query string or in the request body").build();
        } else {
            return request.createResponseBuilder(HttpStatus.OK).body(name).build();
        }
    }

    /**
     * This function listens at endpoint "/api/HttpTriggerJavaVersion".
     * It can be used to verify the Java home and java version currently in use in your Azure function
     */
    @FunctionName("HttpTriggerJavaVersion")
    public static HttpResponseMessage HttpTriggerJavaVersion(
        @HttpTrigger(
            name = "req",
            methods = {HttpMethod.GET, HttpMethod.POST},
            authLevel = AuthorizationLevel.ANONYMOUS)
            HttpRequestMessage<Optional<String>> request,
        final ExecutionContext context
    ) {
        context.getLogger().info("Java HTTP trigger processed a request.");
        final String javaVersion = getJavaVersion();
        context.getLogger().info("Function - HttpTriggerJavaVersion" + javaVersion);
        return request.createResponseBuilder(HttpStatus.OK).body("HttpTriggerJavaVersion").build();
    }

    public static String getJavaVersion() {
        return String.join(" - ", System.getProperty("java.home"), System.getProperty("java.version"));
    }
}

يتم إنشاء رسالة الاستجابة بواسطة واجهة برمجيات تطبيقات⁧⁩HttpResponseMessage.Builder⁧⁩.

يقوم النموذج الأصلي أيضًا بإنشاء اختبار وحدة لدالتك. عند تغيير الدالة لإضافة روابط أو إضافة دالات جديدة إلى المشروع، ستحتاج أيضًا إلى تعديل الاختبارات في الملف ⁧⁩FunctionTest.java⁧⁩.


رمز pom.xml

يتم تعريف إعدادات موارد Azure التي تم إنشاؤها لاستضافة التطبيق الخاص بك في العنصر ⁧⁩تكوين⁧⁩ المكون الإضافي مع ⁧⁩groupId⁧⁩ لـ ⁧com.microsoft.azure⁩ في ملف ⁧⁩pom.xml⁧⁩ الذي تم إنشاؤه. على سبيل المثال، يقوم عنصر التكوين أدناه بتوجيه نشر يستند إلى Maven لإنشاء تطبيق وظيفة في java-functions-group مجموعة الموارد في المنطقةwestus. يقوم تطبيق الدوال بتشغيل نفسه على Windows المستضاف في الخطة ⁧java-functions-app-service-plan⁩، وهي خطة استهلاك بلا خادم حسب الإعدادات الافتراضية.

<plugin>
    <groupId>com.microsoft.azure</groupId>
    <artifactId>azure-functions-maven-plugin</artifactId>
    <version>${azure.functions.maven.plugin.version}</version>
    <configuration>
        <!-- function app name -->
        <appName>${functionAppName}</appName>
        <!-- function app resource group -->
        <resourceGroup>${functionResourceGroup}</resourceGroup>
        <!-- function app service plan name -->
        <appServicePlanName>java-functions-app-service-plan</appServicePlanName>
        <!-- function app region-->
        <!-- refers https://github.com/microsoft/azure-maven-plugins/wiki/Azure-Functions:-Configuration-Details#supported-regions for all valid values -->
        <region>${functionAppRegion}</region>
        <!-- function pricingTier, default to be consumption if not specified -->
        <!-- refers https://github.com/microsoft/azure-maven-plugins/wiki/Azure-Functions:-Configuration-Details#supported-pricing-tiers for all valid values -->
        <!-- <pricingTier></pricingTier> -->

        <!-- Whether to disable application insights, default is false -->
        <!-- refers https://github.com/microsoft/azure-maven-plugins/wiki/Azure-Functions:-Configuration-Details for all valid configurations for application insights-->
        <!-- <disableAppInsights></disableAppInsights> -->
        <runtime>
            <!-- runtime os, could be windows, linux or docker-->
            <os>windows</os>
            <javaVersion>8</javaVersion>
            <!-- for docker function, please set the following parameters -->
            <!-- <image>[hub-user/]repo-name[:tag]</image> -->
            <!-- <serverId></serverId> -->
            <!-- <registryUrl></registryUrl>  -->
        </runtime>
        <appSettings>
            <property>
                <name>FUNCTIONS_EXTENSION_VERSION</name>
                <value>~3</value>
            </property>
        </appSettings>
    </configuration>
    <executions>
        <execution>
            <id>package-functions</id>
            <goals>
                <goal>package</goal>
            </goals>
        </execution>
    </executions>
</plugin>

يمكنك تغيير هذه الإعدادات للتحكم في كيفية إنشاء الموارد في Azure، عن طريق تغيير ⁧runtime.os⁩ من ⁧windows⁩ إلى ⁧linux⁩ قبل النشر الأولي على سبيل المثال. للحصول على قائمة كاملة بالإعدادات المدعومة من قبل المكون الإضافي Maven، راجع ⁧⁩تفاصيل التكوين⁧⁩.



3. قم بتشغيل الدالة محليًا

  1. ⁩قم بتشغيل الدالة الخاصة بك⁧⁩ عن طريق بدء تشغيل مضيف وقت تشغيل دوال Azure المحلي من المجلد ⁧⁩LocalFunctionProj⁧⁩:

    mvn clean package
    mvn azure-functions:run
    

    في نهاية الإخراج، يجب أن تظهر الأسطر التالية:

     ...
    
     Now listening on: http://0.0.0.0:7071
     Application started. Press Ctrl+C to shut down.
    
     Http Functions:
    
             HttpExample: [GET,POST] http://localhost:7071/api/HttpExample
     ...
     

    إذا لم يظهر HttpExample كما هو موضح أعلاه، فمن المحتمل أن تكون قد بدأت المضيف من خارج المجلد الجذر للمشروع. في هذه الحالة، استخدم ⁧⁩Ctrl+C⁧⁩ لإيقاف المضيف، وانتقل إلى المجلد الجذر للمشروع، وقم بتشغيل الأمر السابق مرة أخرى.

  2. ⁩انسخ عنوان URL⁧⁩ الخاص ⁧HttpExample⁩ بدالتك من هذا الإخراج إلى مستعرض وألحق سلسلة الاستعلام ⁧?name=<YOUR_NAME>⁩، ما يجعل عنوان URL الكامل يبد كـ ⁧http://localhost:7071/api/HttpExample?name=Functions⁩. يجب أن يعرض المستعرض رسالة مثل ⁧Hello Functions⁩:

    Result of the function run locally in the browser

    تعرض المحطة الطرفية التي بدأت المشروع الخاص بك فيها أيضاً مخرجات السجل عندما تقوم بتقديم طلبات.

  3. عند الانتهاء من ذلك، استخدم ⁧⁩Ctrl+C⁧⁩ واختر ⁧⁩y⁧⁩ لإيقاف مضيف الدالات.



4. نشر مشروع الدالة إلى Azure

يتم إنشاء تطبيق دالة والموارد ذات الصلة في Azure عند نشر مشروع الدالات لأول مرة. يتم تعريف الإعدادات الخاصة بموارد Azure التي تم إنشاؤها لاستضافة التطبيق الخاص بك في ملف ⁧⁩pom.xml⁧⁩. في هذه المقالة، سوف تقبل الإعدادات الافتراضية.


لإنشاء تطبيق وظيفي يعمل على Linux

لإنشاء تطبيق دالة يعمل على Linux بدلاً من Windows، قم بتغيير العنصر ⁧runtime.os⁩ في ملف ⁧⁩pom.xml⁧⁩ من ⁧windows⁩ إلى ⁧linux⁩. يتم دعم تشغيل Linux في خطة استهلاك في ⁧⁩هذه المناطق⁧⁩. لا يمكن أن يكون لديك تطبيقات تعمل على Linux وتطبيقات تعمل على Windows في نفس مجموعة الموارد.

  1. قبل أن تتمكن من النشر، قم بتسجيل الدخول إلى اشتراك Azure باستخدام Azure CLI أو Azure PowerShell.

    az login
    

    يقوم الأمر ⁧⁩تسجيل الدخول إلى az⁧⁩ بتسجيل الدخول إلى حساب Azure الخاص بك.

  2. استخدم الأمر التالي لنشر المشروع إلى تطبيق دالة جديد.

    mvn azure-functions:deploy
    

    يقوم النشر بحزم ملفات المشروع ونشرها إلى التطبيق الدالة الجديد باستخدام ⁧⁩نشر الرمز البريدي⁧⁩. يتم تشغيل التعليمات البرمجية من حزمة النشر في Azure.


ما الذي تم إنشاؤه في Azure؟
  • مجموعة الموارد. تحمل اسم ⁧⁩java-functions-group⁧⁩.
  • حساب التخزين. مطلوب من الدالات. يتم إنشاء الاسم بشكل عشوائي استنادًا إلى متطلبات اسم حساب التخزين.
  • خطة الاستضافة. استضافة بلا خادم لتطبيق الدالة الخاص بك في منطقة ⁧⁩Westus⁧⁩. الاسم هو ⁧⁩java-functions-app-service-plan⁧⁩.
  • تطبيق الدالة. تطبيق الدالة هو نشر الدالات الخاصة بك وتنفيذها. يتم إنشاء الاسم بشكل عشوائي استنادًا إلى ⁧⁩artifactId⁧⁩الخاصة بك، الملحقة برقم تم إنشاؤه عشوائيًا.


5. استدعاء الدالة على Azure

نظرا لأن وظيفتك تستخدم مشغل HTTP ، فإنك تستدعيه عن طريق تقديم طلب HTTP إلى عنوان URL الخاص به في المستعرض أو باستخدام أداة مثل curl.

انسخ ⁧⁩عنوان URL للاستدعاء⁧⁩ الكامل المعروض في إخراج الأمر⁧publish⁩ في شريط عناوين المتصفح، مع إرفاق معلمة الاستعلام⁧&name=Functions⁩. يجب أن يعرض المستعرض إخراجًا مشابهًا كما هو الحال عند تشغيل الدالة محليا.

The output of the function run on Azure in a browser

قم بتشغيل الأمر التالي لعرض السجلات الجارية في الوقت الحقيقي تقريباً:

func azure functionapp logstream <APP_NAME> 

في نافذة طرفية منفصلة أو في المتصفح، اضغط على وظيفة التحكم عن بعد مرة أخرى. سيُعرض سجلاً مطولاً لتنفيذ الوظيفة في Azure في المحطة الطرفية.



6. حذف الموارد

إذا تابعت الخطوة التالية وأضفت ربط مخرجات قائمة انتظار تخزين Azure، فاحتفظ بجميع مواردك في مكانها الصحيح حيث ستبني على ما قمت به بالفعل.

وإلا، استخدم الأمر التالي لحذف مجموعة الموارد وكافة الموارد المضمنة لتجنب تكبد المزيد من التكاليف.

az group delete --name java-functions-group


الخطوات التالية