1. บทนำ
Python เป็นภาษาโปรแกรมโอเพนซอร์สยอดนิยมที่ใช้โดยนักวิทยาศาสตร์ข้อมูล นักพัฒนาเว็บแอปพลิเคชัน ผู้ดูแลระบบ และอื่นๆ
Cloud Functions เป็นแพลตฟอร์มการประมวลผลแบบ Serverless ที่ขับเคลื่อนด้วยเหตุการณ์ Cloud Functions ช่วยให้คุณเขียนโค้ดได้โดยไม่ต้องกังวลเกี่ยวกับการจัดสรรทรัพยากรหรือการปรับขนาดเพื่อจัดการกับข้อกำหนดที่เปลี่ยนแปลง
Cloud Function มี 2 ประเภทดังนี้
- ฟังก์ชัน HTTP จะตอบสนองต่อคำขอ HTTP คุณจะต้องสร้าง 2 เวอร์ชันใน Codelab นี้
- ฟังก์ชันเบื้องหลังจะทำงานเมื่อเหตุการณ์เกิดขึ้น เช่น ข้อความที่เผยแพร่ไปยัง Cloud Pub/Sub หรือไฟล์ที่อัปโหลดไปยัง Cloud Storage เราไม่ได้แก้ไขปัญหานี้ในห้องทดลองนี้ แต่คุณสามารถอ่านข้อมูลเพิ่มเติมได้ในเอกสารประกอบ
Codelab นี้จะอธิบายการสร้าง Cloud Functions ของคุณเองใน Python
สิ่งที่คุณจะสร้าง
ใน Codelab นี้ คุณจะเผยแพร่ Cloud Function ที่เมื่อเรียกใช้ผ่าน HTTP จะมีสถานะ "Python ขับเคลื่อนโดย" โลโก้
สิ่งที่คุณจะได้เรียนรู้
- วิธีเขียน HTTP Cloud Function
- วิธีเขียน HTTP Cloud Function ซึ่งใช้อาร์กิวเมนต์
- วิธีทดสอบ HTTP Cloud Function
- วิธีเรียกใช้เซิร์ฟเวอร์ Python HTTP ในเครื่องเพื่อลองใช้ฟังก์ชันนี้
- วิธีเขียน HTTP Cloud Function ที่จะแสดงผลรูปภาพ
2. การตั้งค่าและข้อกำหนด
การตั้งค่าสภาพแวดล้อมตามเวลาที่สะดวก
- ลงชื่อเข้าใช้ Google Cloud Console และสร้างโปรเจ็กต์ใหม่หรือใช้โปรเจ็กต์ที่มีอยู่ซ้ำ หากยังไม่มีบัญชี Gmail หรือ Google Workspace คุณต้องสร้างบัญชี
- ชื่อโครงการคือชื่อที่แสดงของผู้เข้าร่วมโปรเจ็กต์นี้ เป็นสตริงอักขระที่ Google APIs ไม่ได้ใช้ โดยคุณจะอัปเดตวิธีการชำระเงินได้ทุกเมื่อ
- รหัสโปรเจ็กต์จะไม่ซ้ำกันในทุกโปรเจ็กต์ของ Google Cloud และจะเปลี่ยนแปลงไม่ได้ (เปลี่ยนแปลงไม่ได้หลังจากตั้งค่าแล้ว) Cloud Console จะสร้างสตริงที่ไม่ซ้ำกันโดยอัตโนมัติ ปกติแล้วคุณไม่สนว่าอะไรเป็นอะไร ใน Codelab ส่วนใหญ่ คุณจะต้องอ้างอิงรหัสโปรเจ็กต์ (โดยปกติจะระบุเป็น
PROJECT_ID
) หากคุณไม่ชอบรหัสที่สร้างขึ้น คุณสามารถสร้างรหัสแบบสุ่มอื่นได้ หรือคุณจะลองดำเนินการเองแล้วดูว่าพร้อมให้ใช้งานหรือไม่ คุณจะเปลี่ยนแปลงหลังจากขั้นตอนนี้ไม่ได้และจะยังคงอยู่ตลอดระยะเวลาของโปรเจ็กต์ - สำหรับข้อมูลของคุณ ค่าที่ 3 คือหมายเลขโปรเจ็กต์ ซึ่ง API บางตัวใช้ ดูข้อมูลเพิ่มเติมเกี่ยวกับค่าทั้ง 3 ค่าได้ในเอกสารประกอบ
- ถัดไป คุณจะต้องเปิดใช้การเรียกเก็บเงินใน Cloud Console เพื่อใช้ทรัพยากร/API ของระบบคลาวด์ การใช้งาน Codelab นี้จะไม่มีค่าใช้จ่ายใดๆ หากมี หากต้องการปิดทรัพยากรเพื่อหลีกเลี่ยงการเรียกเก็บเงินที่นอกเหนือจากบทแนะนำนี้ คุณสามารถลบทรัพยากรที่คุณสร้างหรือลบโปรเจ็กต์ได้ ผู้ใช้ Google Cloud ใหม่มีสิทธิ์เข้าร่วมโปรแกรมช่วงทดลองใช้ฟรี$300 USD
เริ่มต้น Cloud Shell
แม้ว่าคุณจะดำเนินการ Google Cloud จากระยะไกลได้จากแล็ปท็อป แต่คุณจะใช้ Cloud Shell ใน Codelab ซึ่งเป็นสภาพแวดล้อมบรรทัดคำสั่งที่ทำงานในระบบคลาวด์
เปิดใช้งาน Cloud Shell
- คลิกเปิดใช้งาน Cloud Shell
จาก Cloud Console
หากเริ่มต้นใช้งาน Cloud Shell เป็นครั้งแรก คุณจะเห็นหน้าจอตรงกลางที่อธิบายว่านี่คืออะไร หากระบบแสดงหน้าจอตรงกลาง ให้คลิกต่อไป
การจัดสรรและเชื่อมต่อกับ Cloud Shell ใช้เวลาเพียงไม่กี่นาที
เครื่องเสมือนนี้โหลดด้วยเครื่องมือการพัฒนาทั้งหมดที่จำเป็น โดยมีไดเรกทอรีหลักขนาด 5 GB ถาวรและทำงานใน Google Cloud ซึ่งช่วยเพิ่มประสิทธิภาพของเครือข่ายและการตรวจสอบสิทธิ์ได้อย่างมาก งานส่วนใหญ่ใน Codelab นี้สามารถทำได้โดยใช้เบราว์เซอร์
เมื่อเชื่อมต่อกับ Cloud Shell แล้ว คุณควรเห็นข้อความตรวจสอบสิทธิ์และโปรเจ็กต์ได้รับการตั้งค่าเป็นรหัสโปรเจ็กต์แล้ว
- เรียกใช้คำสั่งต่อไปนี้ใน 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`
- เรียกใช้คำสั่งต่อไปนี้ใน 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 API แล้ว
เรียกใช้คำสั่งต่อไปนี้จาก Cloud Shell เพื่อตรวจสอบว่าได้เปิดใช้ Cloud Functions และ Cloud Build API แล้ว
gcloud services enable \ cloudfunctions.googleapis.com \ cloudbuild.googleapis.com
หมายเหตุ: คำสั่ง gcloud functions deploy
เรียกใช้ Cloud Build และจะสร้างโค้ดลงในอิมเมจคอนเทนเนอร์โดยอัตโนมัติ
ดาวน์โหลดซอร์สโค้ด
จากเทอร์มินัล 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 Cloud Functions ใน Python จะมีการเขียนเป็นฟังก์ชัน Python ปกติ ฟังก์ชันดังกล่าวต้องยอมรับอาร์กิวเมนต์ 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) คุณเปิดไดเรกทอรีดังกล่าวใน Cloud Shell Editor ได้หลังจากตั้งค่าไดเรกทอรีแหล่งที่มาเป็นพื้นที่ทำงานแล้ว โดยทำตามขั้นตอนดังนี้
cloudshell open-workspace .
มาทำให้ฟังก์ชันนี้ใช้งานได้เป็น HTTP Cloud Function โดยใช้คำสั่ง 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
: ระบุรันไทม์ของภาษา สำหรับ Python ค่านี้อาจเป็นpython37
,python38
,python39
,python310
หรือpython312
ดูรันไทม์--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 Cloud Function เพื่อรับอาร์กิวเมนต์
ฟังก์ชันจะทำงานได้หลากหลายกว่าเมื่อยอมรับอาร์กิวเมนต์ ลองกำหนดฟังก์ชันใหม่ 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! 🚀
ขั้นตอนถัดไปคือการเพิ่มการทดสอบ 1 หน่วยเพื่อให้แน่ใจว่าฟังก์ชันของคุณยังคงทำงานได้ตามที่ตั้งใจไว้เมื่อมีการอัปเดตซอร์สโค้ด
5. ข้อสอบการเขียน
ฟังก์ชันระบบคลาวด์ HTTP ใน Python ได้รับการทดสอบโดยใช้โมดูล unittest
จากไลบรารีมาตรฐาน คุณไม่จำเป็นต้องเรียกใช้โปรแกรมจำลองหรือการจำลองอื่นๆ เพื่อทดสอบฟังก์ชัน เพียงแต่ใช้โค้ด Python ปกติเท่านั้น
การทดสอบสำหรับฟังก์ชัน 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}! 🚀"
- การทดสอบ Python จะเขียนในลักษณะเดียวกับไฟล์ Python อื่นๆ โดยเริ่มจากชุดการนำเข้า จากนั้นจึงกำหนดคลาสและฟังก์ชัน
- การประกาศการทดสอบอยู่ในรูปแบบ
class TestHello(TestCase)
โดยต้องเป็นคลาสที่รับค่าจากunittest.TestCase
- คลาสการทดสอบมีเมธอด ซึ่งแต่ละแบบต้องขึ้นต้นด้วย
test_
ซึ่งแสดงถึงกรอบการทดสอบแต่ละรายการ - กรอบการทดสอบแต่ละรายการจะทดสอบฟังก์ชันใดฟังก์ชันหนึ่งของเราโดยจำลองพารามิเตอร์
request
(เช่น แทนที่ด้วยออบเจ็กต์ปลอมด้วยข้อมูลที่เจาะจงที่จำเป็นสำหรับการทดสอบ) - หลังจากเรียกใช้แต่ละฟังก์ชันแล้ว การทดสอบจะตรวจสอบการตอบสนอง HTTP เพื่อให้แน่ใจว่าเป็นสิ่งที่เราคาดหวัง
เนื่องจาก main.py
ขึ้นอยู่กับ flask
โปรดตรวจสอบว่าได้ติดตั้งเฟรมเวิร์ก Flask ในสภาพแวดล้อมการทดสอบแล้ว ดังนี้
pip install flask
การติดตั้ง Flask จะแสดงผลลัพธ์ที่คล้ายกับข้อความต่อไปนี้
Collecting flask ... Successfully installed ... flask-3.0.2 ...
เรียกใช้การทดสอบเหล่านี้ในเครื่อง
python -m unittest
หน่วยการทดสอบ 3 หน่วยควรผ่าน:
... ---------------------------------------------------------------------- Ran 3 tests in 0.001s OK
ถัดไป คุณจะต้องสร้างฟังก์ชันใหม่ซึ่งส่งคืนฟังก์ชัน "Python ขับเคลื่อนโดย" โลโก้
6. การเขียน "Python ขับเคลื่อนโดย" ฟังก์ชัน HTTP Cloud
มาสร้างฟังก์ชันใหม่ให้สนุกยิ่งขึ้นโดยการส่งคืน "Python ขับเคลื่อนโดย" รูปภาพสำหรับทุกคำขอ:
รายชื่อต่อไปนี้จะแสดงรหัสที่จะทำให้เกิดขึ้นจริง
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 ขับเคลื่อนโดย" โลโก้ในแท็บใหม่ของเบราว์เซอร์
ถัดไป คุณจะต้องสร้างแอปเพื่อให้สามารถเรียกใช้และลองใช้ฟังก์ชันในเครื่องก่อนทำให้ใช้งานได้
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)
- ไฟล์นี้จะสร้างแอปพลิเคชัน Flask
- โดยจะบันทึกเส้นทางใน URL ฐาน ซึ่งจัดการด้วยฟังก์ชันชื่อ
index()
- จากนั้นฟังก์ชัน
index()
จะเรียกฟังก์ชันpython_powered
และส่งต่อคำขอปัจจุบัน
ตรวจสอบว่าได้ติดตั้งเฟรมเวิร์ก Flask ในสภาพแวดล้อมการพัฒนาแล้ว ดังนี้
pip install flask
การติดตั้ง Flask จะแสดงผลลัพธ์ที่คล้ายกับข้อความต่อไปนี้
Collecting flask ... Successfully installed ... flask-3.0.2 ...
หากต้องการเรียกใช้แอปพลิเคชันนี้ในเครื่อง ให้เรียกใช้คำสั่งต่อไปนี้
python web_app.py
ใช้ Cloud Shell Web Preview เพื่อทดสอบเว็บแอปในเบราว์เซอร์ ใน Cloud Shell ให้คลิก "ตัวอย่างเว็บ" แล้วเลือก "ดูตัวอย่างบนพอร์ต 8080"
Cloud Shell จะเปิด URL ตัวอย่างบนบริการพร็อกซีในหน้าต่างเบราว์เซอร์ใหม่ ตัวอย่างเว็บจะจำกัดให้บัญชีผู้ใช้ของคุณเข้าถึงผ่าน HTTPS เท่านั้น หากทุกอย่างถูกต้อง คุณควรเห็นหน้าต่าง "Python ขับเคลื่อนโดย" โลโก้
8. ยินดีด้วย
คุณได้ทำให้ Cloud Functions ของ HTTP ใช้งานได้โดยใช้ฟังก์ชันที่ไม่ซ้ำกันที่จัดการคำขอเว็บด้วยเฟรมเวิร์ก Flask
ราคาของ Cloud Functions จะอิงตามความถี่ที่เรียกใช้ฟังก์ชัน รวมถึงรุ่นฟรีสำหรับฟังก์ชันที่ไม่ได้เรียกใช้บ่อย เมื่อทดสอบ Cloud Functions เสร็จสิ้นแล้ว คุณลบฟังก์ชันได้โดยใช้ gcloud
gcloud functions delete hello_world --quiet gcloud functions delete hello_name --quiet gcloud functions delete python_powered --quiet
นอกจากนี้ คุณยังลบฟังก์ชันออกจากคอนโซล Google Cloud ได้ด้วย
เราหวังว่าคุณจะสนุกกับการใช้ Cloud Functions ใน Python