توابع ابر HTTP در پایتون

۱. مقدمه

b158ce75c3cccd6d.png

پایتون یک زبان برنامه‌نویسی متن‌باز محبوب است که توسط دانشمندان داده، توسعه‌دهندگان برنامه‌های وب، مدیران سیستم و موارد دیگر مورد استفاده قرار می‌گیرد.

Cloud Functions یک پلتفرم محاسباتی بدون سرور مبتنی بر رویداد است. Cloud Functions به شما امکان می‌دهد بدون نگرانی در مورد تأمین منابع یا مقیاس‌پذیری برای رسیدگی به نیازهای متغیر، کد خود را بنویسید.

دو نوع عملکرد ابری وجود دارد:

  • توابع HTTP به درخواست‌های HTTP پاسخ می‌دهند. در این آزمایشگاه کد، چند مورد از آنها را خواهید ساخت.
  • توابع پس‌زمینه توسط رویدادها، مانند انتشار پیام در Cloud Pub/Sub یا آپلود فایل در Cloud Storage ، فعال می‌شوند. ما در این تمرین به این موضوع نمی‌پردازیم، اما می‌توانید اطلاعات بیشتر را در مستندات مطالعه کنید.

efb3268e3b74ed4f.png

این آزمایشگاه کد، شما را در ایجاد توابع ابری خودتان در پایتون راهنمایی می‌کند.

آنچه خواهید ساخت

در این آزمایشگاه کد، شما یک تابع ابری منتشر خواهید کرد که هنگام فراخوانی از طریق HTTP، لوگوی «Python Powered» را نمایش می‌دهد:

a7aaf656b78050fd.png

آنچه یاد خواهید گرفت

  • نحوه نوشتن یک تابع HTTP Cloud.
  • چگونه یک تابع HTTP Cloud بنویسیم که آرگومان‌ها را دریافت کند.
  • نحوه آزمایش یک تابع ابری HTTP.
  • نحوه اجرای یک سرور HTTP محلی پایتون برای امتحان کردن تابع.
  • چگونه یک تابع HTTP Cloud بنویسیم که یک تصویر را برمی‌گرداند.

۲. تنظیمات و الزامات

تنظیم محیط خودتنظیم

  1. وارد کنسول گوگل کلود شوید و یک پروژه جدید ایجاد کنید یا از یک پروژه موجود دوباره استفاده کنید. اگر از قبل حساب جیمیل یا گوگل ورک اسپیس ندارید، باید یکی ایجاد کنید .

fbef9caa1602edd0.png

a99b7ace416376c4.png

5e3ff691252acf41.png

  • نام پروژه، نام نمایشی برای شرکت‌کنندگان این پروژه است. این یک رشته کاراکتری است که توسط APIهای گوگل استفاده نمی‌شود. شما همیشه می‌توانید آن را به‌روزرسانی کنید.
  • شناسه پروژه در تمام پروژه‌های گوگل کلود منحصر به فرد است و تغییرناپذیر است (پس از تنظیم، قابل تغییر نیست). کنسول کلود به طور خودکار یک رشته منحصر به فرد تولید می‌کند؛ معمولاً برای شما مهم نیست که چه باشد. در اکثر آزمایشگاه‌های کد، باید شناسه پروژه خود را (که معمولاً با عنوان PROJECT_ID شناخته می‌شود) ارجاع دهید. اگر شناسه تولید شده را دوست ندارید، می‌توانید یک شناسه تصادفی دیگر ایجاد کنید. به عنوان یک جایگزین، می‌توانید شناسه خودتان را امتحان کنید و ببینید که آیا در دسترس است یا خیر. پس از این مرحله قابل تغییر نیست و در طول پروژه باقی می‌ماند.
  • برای اطلاع شما، یک مقدار سوم، شماره پروژه ، وجود دارد که برخی از APIها از آن استفاده می‌کنند. برای کسب اطلاعات بیشتر در مورد هر سه این مقادیر، به مستندات مراجعه کنید.
  1. در مرحله بعد، برای استفاده از منابع/API های ابری، باید پرداخت صورتحساب را در کنسول ابری فعال کنید . اجرای این آزمایشگاه کد هزینه زیادی نخواهد داشت، اگر اصلاً هزینه‌ای داشته باشد. برای خاموش کردن منابع به منظور جلوگیری از پرداخت صورتحساب پس از این آموزش، می‌توانید منابعی را که ایجاد کرده‌اید یا پروژه را حذف کنید. کاربران جدید Google Cloud واجد شرایط برنامه آزمایشی رایگان ۳۰۰ دلاری هستند.

شروع پوسته ابری

اگرچه می‌توان گوگل کلود را از راه دور و از طریق لپ‌تاپ شما مدیریت کرد، اما در این آزمایشگاه کد از Cloud Shell ، یک محیط خط فرمان که در فضای ابری اجرا می‌شود، استفاده خواهید کرد.

فعال کردن پوسته ابری

  1. از کنسول ابری، روی فعال کردن پوسته ابری کلیک کنید 853e55310c205094.png .

3c1dabeca90e44e5.png

اگر این اولین باری است که Cloud Shell را اجرا می‌کنید، یک صفحه میانی برای توضیح آن به شما نمایش داده می‌شود. اگر با یک صفحه میانی مواجه شدید، روی ادامه کلیک کنید.

9c92662c6a846a5c.png

آماده‌سازی و اتصال به Cloud Shell فقط چند لحظه طول می‌کشد.

9f0e51b578fecce5.png

این ماشین مجازی مجهز به تمام ابزارهای توسعه مورد نیاز است. این ماشین یک دایرکتوری خانگی پایدار ۵ گیگابایتی ارائه می‌دهد و در فضای ابری گوگل اجرا می‌شود که عملکرد شبکه و احراز هویت را تا حد زیادی افزایش می‌دهد. بخش عمده‌ای از کار شما در این آزمایشگاه کد، اگر نگوییم همه، را می‌توان با یک مرورگر انجام داد.

پس از اتصال به Cloud Shell، باید ببینید که احراز هویت شده‌اید و پروژه روی شناسه پروژه شما تنظیم شده است.

  1. برای تأیید احراز هویت، دستور زیر را در Cloud Shell اجرا کنید:
gcloud auth list

خروجی دستور

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. دستور زیر را در Cloud Shell اجرا کنید تا تأیید کنید که دستور gcloud از پروژه شما اطلاع دارد:
gcloud config list project

خروجی دستور

[core]
project = <PROJECT_ID>

اگر اینطور نیست، می‌توانید با این دستور آن را تنظیم کنید:

gcloud config set project <PROJECT_ID>

خروجی دستور

Updated property [core/project].

مطمئن شوید که توابع ابری و APIهای ساخت ابری فعال هستند.

دستور زیر را از Cloud Shell اجرا کنید تا مطمئن شوید که توابع ابری و APIهای ساخت ابری فعال هستند:

gcloud services enable \
  cloudfunctions.googleapis.com \
  cloudbuild.googleapis.com

نکته: Cloud Build توسط دستور gcloud functions deploy فراخوانی می‌شود و به طور خودکار کد شما را در یک تصویر کانتینر می‌سازد.

کد منبع را دانلود کنید

از ترمینال Cloud Shell، دستورات زیر را اجرا کنید:

REPO_NAME="codelabs"
REPO_URL="https://github.com/GoogleCloudPlatform/$REPO_NAME"
SOURCE_DIR="cloud-functions-python-http"

git clone --no-checkout --filter=blob:none --depth=1 $REPO_URL
cd $REPO_NAME
git sparse-checkout set $SOURCE_DIR
git checkout
cd $SOURCE_DIR

محتوای دایرکتوری منبع را بررسی کنید:

ls

شما باید فایل‌های زیر را داشته باشید:

main.py  python-powered.png  test_main.py  web_app.py

۳. معرفی توابع ابری HTTP

توابع HTTP Cloud در پایتون به صورت توابع معمولی پایتون نوشته می‌شوند. این تابع باید یک آرگومان flask.Request را بپذیرد که معمولاً request نام دارد.

فایل اصلی.py

import flask


def hello_world(request: flask.Request) -> flask.Response:
    """HTTP Cloud Function.

    Returns:
    - "Hello World! 👋"
    """
    response = "Hello World! 👋"

    return flask.Response(response, mimetype="text/plain")

# ...

می‌توانید فایل را با ویرایشگر خط فرمان دلخواه خود (nano، vim یا emacs) باز کنید. همچنین می‌توانید پس از تنظیم دایرکتوری منبع به عنوان فضای کاری، آن را در ویرایشگر Cloud Shell باز کنید:

cloudshell open-workspace .

بیایید این تابع را به عنوان یک تابع HTTP Cloud با استفاده از دستور gcloud functions deploy مستقر کنیم:

FUNCTION_NAME="hello_world"

gcloud functions deploy $FUNCTION_NAME \
  --runtime python312 \
  --trigger-http \
  --allow-unauthenticated

خروجی دستور:

...
Deploying function (may take a while - up to 2 minutes)...done.
availableMemoryMb: 256
...
entryPoint: FUNCTION_NAME
httpsTrigger:
  url: https://REGION-PROJECT_ID.cloudfunctions.net/FUNCTION_NAME
...

نکاتی در مورد گزینه‌های gcloud functions deploy :

  • --runtime : این زمان اجرای زبان را مشخص می‌کند. برای پایتون، در حال حاضر می‌تواند python37 ، python38 ، python39 ، python310 یا python312 باشد. به Runtimes مراجعه کنید.
  • --trigger-http : به تابع یک نقطه پایانی اختصاص داده می‌شود. درخواست‌های HTTP (POST، PUT، GET، DELETE و OPTIONS) به نقطه پایانی، اجرای تابع را آغاز می‌کنند.
  • --allow-unauthenticated : تابع عمومی خواهد بود و به همه فراخوانی‌کنندگان اجازه می‌دهد بدون بررسی احراز هویت.
  • برای کسب اطلاعات بیشتر، به بخش «توابع gcloud deploy» مراجعه کنید.

برای آزمایش تابع، می‌توانید روی آدرس اینترنتی httpsTrigger.url که در خروجی دستور بالا نمایش داده شده است کلیک کنید. همچنین می‌توانید با استفاده از برنامه‌نویسی، آدرس اینترنتی را بازیابی کرده و تابع را با دستورات زیر فراخوانی کنید:

URL=$(gcloud functions describe $FUNCTION_NAME --format "value(httpsTrigger.url)")
curl -w "\n" $URL

شما باید نتیجه زیر را دریافت کنید:

Hello World! 👋

۴. نوشتن یک تابع HTTP Cloud که آرگومان‌ها را دریافت می‌کند

توابع وقتی آرگومان می‌پذیرند، تطبیق‌پذیرتر هستند. بیایید یک تابع جدید hello_name تعریف کنیم که از پارامتر name پشتیبانی می‌کند:

فایل اصلی.py

# ...

def hello_name(request: flask.Request) -> flask.Response:
    """HTTP Cloud Function.

    Returns:
    - "Hello {NAME}! 🚀" if "name=NAME" is defined in the GET request
    - "Hello World! 🚀" otherwise
    """
    name = request.args.get("name", "World")
    response = f"Hello {name}! 🚀"

    return flask.Response(response, mimetype="text/plain")

# ...

بیایید این تابع جدید را پیاده‌سازی کنیم:

FUNCTION_NAME="hello_name"

gcloud functions deploy $FUNCTION_NAME \
  --runtime python312 \
  --trigger-http \
  --allow-unauthenticated

خروجی دستور:

...
Deploying function (may take a while - up to 2 minutes)...done.
availableMemoryMb: 256
...
entryPoint: FUNCTION_NAME
httpsTrigger:
  url: https://REGION-PROJECT_ID.cloudfunctions.net/FUNCTION_NAME
...

برای آزمایش تابع، می‌توانید روی آدرس اینترنتی httpsTrigger.url که در خروجی دستور بالا نمایش داده شده است کلیک کنید. همچنین می‌توانید با استفاده از برنامه‌نویسی، آدرس اینترنتی را بازیابی کرده و تابع را با دستورات زیر فراخوانی کنید:

URL=$(gcloud functions describe $FUNCTION_NAME --format "value(httpsTrigger.url)")
curl -w "\n" $URL

شما باید نتیجه پیش‌فرض را دریافت کنید:

Hello World! 🚀

شما نتیجه پیش‌فرض را دریافت می‌کنید زیرا آرگومان name تنظیم نشده است. یک پارامتر به URL اضافه کنید:

curl -w "\n" $URL?name=YOUR%20NAME

این بار، پاسخ سفارشی خود را دریافت خواهید کرد:

Hello YOUR NAME! 🚀

مرحله بعدی اضافه کردن تست‌های واحد است تا اطمینان حاصل شود که توابع شما هنگام به‌روزرسانی کد منبع، طبق برنامه کار می‌کنند.

۵. نوشتن تست‌ها

توابع HTTP Cloud در پایتون با استفاده از ماژول unittest از کتابخانه استاندارد آزمایش می‌شوند. نیازی به اجرای شبیه‌ساز یا شبیه‌سازی دیگری برای آزمایش تابع شما نیست - فقط کد پایتون معمولی کافی است.

این هم نمونه‌ای از تست توابع hello_world و hello_name :

test_main.py

import unittest
import unittest.mock

import main


class TestHello(unittest.TestCase):
    def test_hello_world(self):
        request = unittest.mock.Mock()

        response = main.hello_world(request)
        assert response.status_code == 200
        assert response.get_data(as_text=True) == "Hello World! 👋"

    def test_hello_name_no_name(self):
        request = unittest.mock.Mock(args={})

        response = main.hello_name(request)
        assert response.status_code == 200
        assert response.get_data(as_text=True) == "Hello World! 🚀"

    def test_hello_name_with_name(self):
        name = "FirstName LastName"
        request = unittest.mock.Mock(args={"name": name})

        response = main.hello_name(request)
        assert response.status_code == 200
        assert response.get_data(as_text=True) == f"Hello {name}! 🚀"
  1. تست‌های پایتون مانند سایر فایل‌های پایتون نوشته می‌شوند. آن‌ها با مجموعه‌ای از ایمپورت‌ها شروع می‌شوند، سپس کلاس‌ها و توابع را تعریف می‌کنند.
  2. اعلان تست از نوع class TestHello(TestCase) است. این کلاس باید از unittest.TestCase ارث‌بری کند.
  3. کلاس تست دارای متدهایی است که هر کدام باید با test_ شروع شوند، که نشان‌دهنده موارد تست جداگانه هستند.
  4. هر مورد آزمایشی، یکی از توابع ما را با شبیه‌سازی پارامتر request (یعنی جایگزینی آن با یک شیء جعلی با داده‌های خاص مورد نیاز برای آزمایش) آزمایش می‌کند.
  5. پس از فراخوانی هر تابع، تست، پاسخ HTTP را بررسی می‌کند تا مطمئن شود که همان چیزی است که ما انتظار داشتیم.

از آنجایی که main.py به flask وابسته است، مطمئن شوید که فریم‌ورک Flask در محیط تست شما نصب شده است:

pip install flask

نصب Flask نتیجه‌ای مشابه زیر را ارائه می‌دهد:

Collecting flask
...
Successfully installed ... flask-3.0.2 ...

این تست‌ها را به صورت محلی اجرا کنید:

python -m unittest

سه تست واحد باید با موفقیت پشت سر گذاشته شوند:

...
----------------------------------------------------------------------
Ran 3 tests in 0.001s

OK

در مرحله بعد، یک تابع جدید ایجاد خواهید کرد که لوگوی "Python Powered" را برمی‌گرداند.

۶. نوشتن تابع ابری HTTP «قدرت گرفته از پایتون»

بیایید با برگرداندن تصویر "Python Powered" برای هر درخواست، یک تابع جدید را کمی سرگرم‌کننده‌تر کنیم:

a7aaf656b78050fd.png

لیست زیر کد لازم برای انجام این کار را نشان می‌دهد:

فایل اصلی.py

# ...

def python_powered(request: flask.Request) -> flask.Response:
    """HTTP Cloud Function.

    Returns:
    - The official "Python Powered" logo
    """
    return flask.send_file("python-powered.png")

یک تابع جدید python_powered را مستقر کنید:

FUNCTION_NAME="python_powered"

gcloud functions deploy $FUNCTION_NAME \
  --runtime python312 \
  --trigger-http \
  --allow-unauthenticated

خروجی دستور:

...
Deploying function (may take a while - up to 2 minutes)...done.
availableMemoryMb: 256
...
entryPoint: FUNCTION_NAME
httpsTrigger:
  url: https://REGION-PROJECT_ID.cloudfunctions.net/FUNCTION_NAME
...

برای آزمایش عملکرد، روی آدرس httpsTrigger.url که در خروجی دستور بالا نمایش داده شده است کلیک کنید. اگر همه چیز به درستی کار کند، لوگوی "Python Powered" را در یک تب جدید مرورگر مشاهده خواهید کرد!

در مرحله بعد، یک برنامه ایجاد خواهید کرد تا بتوانید قبل از استقرار، تابع خود را به صورت محلی اجرا و امتحان کنید.

۷. اجرای تابع به صورت محلی

شما می‌توانید با ایجاد یک برنامه وب و فراخوانی تابع خود در یک مسیر، یک تابع HTTP را به صورت محلی اجرا کنید. می‌توانید آن را در همان دایرکتوری که تابع شما قرار دارد، اضافه کنید. فایلی به نام web_app.py حاوی محتوای زیر است:

web_app.py

import flask

import main

app = flask.Flask(__name__)


@app.get("/")
def index():
    return main.python_powered(flask.request)


if __name__ == "__main__":
    # Local development only
    # Run "python web_app.py" and open http://localhost:8080
    app.run(host="localhost", port=8080, debug=True)
  1. این فایل یک برنامه Flask ایجاد می‌کند.
  2. این یک مسیر را در URL پایه ثبت می‌کند که با تابعی به نام index() مدیریت می‌شود.
  3. index() index سپس تابع python_powered ما را فراخوانی می‌کند و درخواست فعلی را به آن ارسال می‌کند.

مطمئن شوید که چارچوب Flask در محیط توسعه شما نصب شده است:

pip install flask

نصب Flask نتیجه‌ای مشابه زیر را ارائه می‌دهد:

Collecting flask
...
Successfully installed ... flask-3.0.2 ...

برای اجرای این برنامه به صورت محلی، دستور زیر را اجرا کنید:

python web_app.py

اکنون از پیش‌نمایش وب Cloud Shell برای آزمایش برنامه وب در مرورگر خود استفاده کنید. در Cloud Shell، روی دکمه "پیش‌نمایش وب" کلیک کنید و "پیش‌نمایش روی پورت ۸۰۸۰" را انتخاب کنید:

6c9ff9e5c692c58e.gif

Cloud Shell آدرس اینترنتی پیش‌نمایش را در سرویس پروکسی خود در یک پنجره مرورگر جدید باز می‌کند. پیش‌نمایش وب، دسترسی از طریق HTTPS را فقط به حساب کاربری شما محدود می‌کند. اگر همه چیز به درستی کار کند، باید لوگوی "Python Powered" را ببینید!

8e5c3ead11cfd103.png

۸. تبریک می‌گویم!

b158ce75c3cccd6d.png

شما توابع ابری HTTP را با استفاده از توابع اصطلاحی که درخواست‌های وب را با چارچوب Flask مدیریت می‌کنند، مستقر کرده‌اید.

قیمت‌گذاری توابع ابری بر اساس تعداد دفعات فراخوانی تابع شما است، که شامل یک ردیف رایگان برای توابعی است که زیاد اجرا نمی‌شوند. پس از اتمام آزمایش توابع ابری خود، می‌توانید آنها را با استفاده از gcloud حذف کنید:

gcloud functions delete hello_world --quiet
gcloud functions delete hello_name --quiet
gcloud functions delete python_powered --quiet

همچنین می‌توانید توابع را از کنسول Google Cloud حذف کنید.

امیدواریم از استفاده از توابع ابری در پایتون لذت ببرید!