เกี่ยวกับ Codelab นี้
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 ระบบคลาวด์
มาสร้างฟังก์ชันใหม่ให้สนุกยิ่งขึ้นโดยการส่งคืน "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