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

1. مقدمه

b158ce75c3cccd6d.png

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

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

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

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

efb3268e3b74ed4f.png

این لبه کد شما را در ایجاد توابع ابری خود در پایتون راهنمایی می کند.

چیزی که خواهی ساخت

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

a7aaf656b78050fd.png

چیزی که یاد خواهید گرفت

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

2. راه اندازی و الزامات

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

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

fbef9caa1602edd0.png

a99b7ace416376c4.png

5e3ff691252acf41.png

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

Cloud Shell را راه اندازی کنید

در حالی که Google Cloud را می توان از راه دور از لپ تاپ شما کار کرد، در این کد لبه از Cloud Shell استفاده خواهید کرد، یک محیط خط فرمان که در Cloud اجرا می شود.

Cloud Shell را فعال کنید

  1. از Cloud Console، روی Activate Cloud Shell کلیک کنید 853e55310c205094.png .

3c1dabeca90e44e5.png

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

9c92662c6a846a5c.png

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

9f0e51b578fecce5.png

این ماشین مجازی با تمام ابزارهای توسعه مورد نیاز بارگذاری شده است. این یک فهرست اصلی 5 گیگابایتی دائمی ارائه می‌کند و در Google Cloud اجرا می‌شود، که عملکرد و احراز هویت شبکه را بسیار افزایش می‌دهد. بسیاری از کارهای شما، اگر نه همه، در این کد لبه با مرورگر قابل انجام است.

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

  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].

مطمئن شوید که Cloud Functions و Cloud Build APIs فعال هستند

دستور زیر را از Cloud Shell اجرا کنید تا مطمئن شوید که Cloud Functions و Cloud Build APIs فعال هستند:

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

3. معرفی HTTP Cloud Functions

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

main.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) باز کنید. همچنین می توانید پس از تنظیم دایرکتوری منبع به عنوان یک فضای کاری، آن را در ویرایشگر پوسته ابری باز کنید:

cloudshell open-workspace .

بیایید این تابع را به عنوان یک تابع ابری HTTP با استفاده از دستور 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 مراجعه کنید.

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

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

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

Hello World! 👋

4. نوشتن یک تابع ابری HTTP که آرگومان ها را می گیرد

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

main.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
...

برای آزمایش عملکرد، می توانید روی URL httpsTrigger.url که در خروجی فرمان بالا نمایش داده شده است کلیک کنید. همچنین می توانید 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! 🚀

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

5. تست های نوشتاری

توابع ابری HTTP در پایتون با استفاده از واحد 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

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

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

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

python -m unittest

سه آزمون واحد باید قبول شود:

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

OK

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

6. نوشتن تابع Cloud HTTP "Python Powered".

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

a7aaf656b78050fd.png

لیست زیر کدی را برای تحقق آن نشان می دهد:

main.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
...

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

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

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

می توانید با ایجاد یک برنامه وب و فراخوانی تابع خود در مسیر، یک تابع 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() تابع python_powered ما را فراخوانی می‌کند و درخواست فعلی را به آن ارسال می‌کند.

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

pip install flask

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

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

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

python web_app.py

اکنون از Cloud Shell Web Preview برای آزمایش برنامه وب در مرورگر خود استفاده کنید. در Cloud Shell، روی دکمه "Web Preview" کلیک کنید و "Preview on port 8080" را انتخاب کنید:

6c9ff9e5c692c58e.gif

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

8e5c3ead11cfd103.png

8. تبریک می گویم!

b158ce75c3cccd6d.png

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

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

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

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

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