1. Tổng quan
Loạt lớp học lập trình này (hướng dẫn thực hành theo tiến độ riêng) nhằm giúp các nhà phát triển Google App Engine (Tiêu chuẩn) hiện đại hoá ứng dụng của họ bằng cách hướng dẫn họ thực hiện một loạt quy trình di chuyển. Phần lớn các quá trình di chuyển như vậy đều liên quan đến việc ngừng sử dụng các dịch vụ thời gian chạy ban đầu đi kèm vì môi trường thời gian chạy thế hệ mới linh hoạt hơn, mang đến cho người dùng nhiều lựa chọn dịch vụ hơn. Đó là chủ đề của lớp học lập trình này, còn có một cách khác để hiện đại hoá ứng dụng, đó là nâng cấp lên một sản phẩm mới hơn.
Những người dùng App Engine truy cập vào Datastore bằng thư viện ứng dụng Cloud NDB hoặc Cloud Datastore đều có thể sử dụng được và không cần phải di chuyển thêm nữa. Tuy nhiên, Cloud Firestore là kho dữ liệu NoSQL mới nhất, có thể mở rộng và có khả năng hoạt động cao, đi kèm với các tính năng từ cơ sở dữ liệu theo thời gian thực của Firebase.
Bạn đến đúng nơi nếu bạn là nhà phát triển cảm thấy buộc phải sử dụng Firestore để tận dụng các tính năng của ứng dụng này, hoặc ít nhất là có đủ sự quan tâm để tìm hiểu những yêu cầu của việc di chuyển này. Hướng dẫn này chỉ cho bạn cách di chuyển ứng dụng App Engine bằng Cloud Datastore sang Cloud Firestore.
Bạn sẽ tìm hiểu cách
- Nhận biết sự khác biệt giữa Datastore và Firestore
- Di chuyển từ Cloud Datastore sang Cloud Firestore
Bạn cần có
- Một dự án Google Cloud Platform có:
- Kỹ năng Python cơ bản
- Kiến thức thực hành về các lệnh Linux phổ biến
- Kiến thức cơ bản về việc phát triển và triển khai ứng dụng App Engine
- Bạn nên hoàn thành lớp học lập trình Mô-đun 3, bao gồm cả việc chuyển mô-đun này sang Python 3, trước khi bắt đầu lớp học này (Mô-đun 6).
- Một Ứng dụng App Engine Python 3 của Mô-đun 3 Cloud Datastore đang hoạt động.
Khảo sát
Bạn sẽ sử dụng lớp học lập trình này như thế nào?
2. Thông tin khái quát
Datastore của App Engine đã trở thành sản phẩm của riêng mình vào năm 2013 là Google Cloud Datastore và hiện có thể truy cập được vào các nhà phát triển bên ngoài App Engine. Năm tiếp theo, Google mua lại Firebase. Vào thời điểm đó, nền tảng này nổi tiếng với cơ sở dữ liệu theo thời gian thực.
Trong vài năm tới, nhóm Firebase và Cloud Datastore đã nỗ lực tích hợp một số tính năng của Firebase vào Datastore. Do đó, vào năm 2017, thế hệ tiếp theo của Cloud Datastore đã được phát hành. Để phản ánh việc kế thừa một số tính năng của Firebase, chúng tôi đã đổi tên ứng dụng thành Cloud Firestore.
Cloud Firestore đã trở thành cơ chế lưu trữ NoSQL mặc định cho các dự án trên Google Cloud. Các ứng dụng mới có thể vận dụng Cloud Firestore một cách nguyên gốc, trong khi các cơ sở dữ liệu hiện có của Datastore được chuyển đổi sang Firestore chuyên sâu và giờ đây hoạt động dưới dạng "Firestore ở chế độ Datastore" để duy trì khả năng tương thích với các thao tác của Datastore. Do đó, các ứng dụng chỉ có thể vận hành Cloud Firestore ở một trong các chế độ đó và không thể thay đổi sau khi đã thiết lập.
Hiện tại, khi tạo dự án mới và chọn một giải pháp NoSQL, người dùng sẽ được nhắc chọn Firestore ở chế độ Datastore hoặc Firestore ở chế độ gốc. Sau khi thêm các thực thể Datastore, người dùng sẽ không thể chuyển thành Firestore. Tương tự, sau khi chọn chế độ gốc Firestore, người dùng sẽ không thể chuyển về Datastore nữa (hay nói đúng hơn là Firestore ở chế độ Datastore) nữa. Hãy đọc bài viết chọn giữa Cloud Firestore ở chế độ Datastore hoặc trang chế độ Firestore gốc trong tài liệu để biết thêm thông tin chi tiết. Để di chuyển một ứng dụng sang Firestore, bạn phải tạo một dự án mới, xuất Datastore rồi nhập vào Firestore. Mục đích của hướng dẫn này là giúp nhà phát triển nắm được sự khác biệt giữa việc sử dụng Cloud Datastore và Cloud Firestore.
Quá trình di chuyển này không phải là quá trình chúng tôi mong đợi người dùng thực hiện. Đó là lý do tại sao đây là quá trình di chuyển không bắt buộc. Mặc dù việc sử dụng Cloud Firestore một cách tự nhiên mang lại những lợi thế rõ ràng như xác thực ứng dụng khách, tích hợp quy tắc Firebase và tất nhiên là cả cơ sở dữ liệu theo thời gian thực của Firebase, nhưng các bước di chuyển lại "bất tiện":
- Bạn phải sử dụng một dự án khác với dự án của ứng dụng hiện tại.
- Không thể chuyển đổi dự án trong đó ứng dụng đã thêm thực thể Datastore sang Firestore ở chế độ gốc
- Tương tự như vậy, một dự án đã chọn Firestore ở chế độ gốc sẽ không thể chuyển về Firestore ở chế độ Datastore.
- Không có công cụ di chuyển nào có thể truyền trực tuyến dữ liệu từ dự án này sang dự án khác.
- Một số tính năng quan trọng của Datastore, bao gồm cả không gian tên và tốc độ ghi cao hơn (>10 nghìn/giây), không có trên Firestore.
- Các công cụ xuất và nhập ở trạng thái "gốc" và "tất cả hoặc không có gì" trong trường hợp cụ thể.
- Nếu ứng dụng của bạn có nhiều thực thể Datastore, có thể mất nhiều giờ để xuất rồi nhập vào Firestore.
- Trong thời gian này, ứng dụng/dịch vụ của bạn sẽ không thể ghi/cập nhật dữ liệu.
- Các hoạt động di chuyển được tính vào mức sử dụng thông thường; bạn có thể muốn chia đều (cho hạn mức hàng ngày nếu có thể) để giảm thiểu chi phí.
- Vì dịch vụ mới của bạn chạy trong một dự án khác, nên bạn sẽ cần một cửa sổ để phổ biến bản cập nhật DNS.
- Datastore và Firestore có các mô hình dữ liệu tương tự nhau nhưng khác nhau, nên việc di chuyển yêu cầu bạn phải cập nhật cách hoạt động của ứng dụng/dịch vụ
- Truy vấn của đối tượng cấp trên từ Datastore hiện là Truy vấn thu thập của Firestore (mặc định)
- Các truy vấn loại rộng từ Datastore là các truy vấn của nhóm thu thập Firestore
- Chỉ mục và cách xử lý không giống nhau, v.v.
Dù vậy, nếu bạn có một ứng dụng khá đơn giản để cân nhắc việc di chuyển, chuẩn bị mô phỏng quá trình di chuyển này, hoặc chỉ đơn giản là tìm hiểu về Datastore so với Firestore, thì bạn hãy tiếp tục!
Người dùng Python 2: Lớp học lập trình di chuyển không bắt buộc này chỉ được trình bày bằng Python 3. Tuy nhiên, vì Cloud Firestore cũng hỗ trợ 2.x nên người dùng có thể nội suy sự khác biệt khi sử dụng. Một ví dụ là bản ghi Firestore sử dụng chuỗi Unicode (thay vì chuỗi byte), vì vậy, bạn bắt buộc phải có chỉ báo hàng đầu u''
cho giá trị cố định chuỗi Python 2, nghĩa là hàm store_visit()
2.x sẽ có dạng như sau:
def store_visit(remote_addr, user_agent):
doc_ref = fs_client.collection(u'Visit')
doc_ref.add({
u'timestamp': datetime.now(),
u'visitor': u'{}: {}'.format(remote_addr, user_agent),
})
Ngoài ra, thư viện ứng dụng sẽ hoạt động tương tự như vậy. Vấn đề duy nhất khác cần xem xét là thư viện Cloud Firestore 2.x bị "đóng băng" Trong quá trình phát triển, các tính năng ngày càng nhiều/mới hơn sẽ chỉ có trong thư viện ứng dụng Firestore 3.x.
Tiếp tục quá trình di chuyển này, sau đây là các bước chính của hướng dẫn này:
- Thiết lập/Chuẩn bị
- Thêm thư viện Cloud Firestore
- Cập nhật tệp ứng dụng
3. Thiết lập/Chuẩn bị
Trước khi bắt đầu phần chính của hướng dẫn, hãy thiết lập dự án, lấy mã, sau đó triển khai ứng dụng cơ sở để biết rằng mình đã bắt đầu làm việc với mã nguồn.
1. Thiết lập dự án
Bạn nên sử dụng lại chính dự án mà bạn đã sử dụng để hoàn thành Lớp học lập trình về Mô-đun 3. Ngoài ra, bạn có thể tạo một dự án hoàn toàn mới hoặc sử dụng lại một dự án hiện có khác. Hãy đảm bảo dự án này có một tài khoản thanh toán đang hoạt động và đã bật App Engine (ứng dụng).
2. Tải ứng dụng mẫu cơ sở
Một trong những điều kiện tiên quyết của lớp học lập trình này là phải có một ứng dụng mẫu của Mô-đun 3 hoạt động được. Nếu bạn chưa có tài khoản, hãy hoàn tất hướng dẫn Học phần 3 (đường liên kết ở trên) trước khi tiếp tục thực hiện tại đây. Hoặc nếu đã quen với nội dung của khoá học, bạn có thể bắt đầu bằng cách lấy mã Mô-đun 3 dưới đây.
Cho dù bạn sử dụng mã của bạn hay mã của chúng tôi, mã Mô-đun 3 là nơi chúng ta sẽ BẮT ĐẦU. Lớp học lập trình của Mô-đun 6 này sẽ hướng dẫn bạn qua từng bước và khi hoàn tất, nó sẽ giống với đoạn mã ở điểm Finish. (Hướng dẫn này chỉ có sẵn cho Python 3.)
- BẮT ĐẦU: Kho lưu trữ mô-đun 3
- HOÀN TẤT: Kho lưu trữ mô-đun 6
- Toàn bộ kho lưu trữ (sao chép hoặc tải tệp ZIP xuống)
Thư mục của các tệp Mô-đun 3 (của bạn hoặc của chúng tôi) sẽ có dạng như sau:
$ ls
README.md main.py templates
app.yaml requirements.txt
3. (Triển khai lại) ứng dụng Mô-đun 3
Các bước chuẩn bị còn lại để thực hiện ngay:
- Làm quen lại bằng công cụ dòng lệnh
gcloud
(nếu cần). - (Triển khai lại mã Mô-đun 3 cho App Engine (nếu cần)
Sau khi bạn thực hiện thành công các bước đó và xác nhận rằng mô hình đã hoạt động, chúng tôi sẽ chuyển sang phần hướng dẫn này, bắt đầu với các tệp cấu hình.
Các yêu cầu đối với Python 2
- Đảm bảo
app.yaml
(vẫn) tham chiếu đến các gói đi kèm của bên thứ ba:grpcio
vàsetuptools
. - Đảm bảo rằng
appengine_config.py
vẫn sử dụngpkg_resources
vàgoogle.appengine.ext.vendor
để trỏ ứng dụng đến tài nguyên của bên thứ ba. - Trong phần tiếp theo cập nhật
requirements.txt
, bạn phải sử dụnggoogle-cloud-firestore==1.9.0
vì đó là phiên bản cuối cùng tương thích với 2.x của thư viện ứng dụng Python Firestore.- Nếu
requirements.txt
của bạn có một mục nhập chogoogle-cloud-core
, hãy giữ nguyên mục nhập này. - Xoá
lib
rồi cài đặt lại bằngpip install -t lib -r requirements.txt
.
- Nếu
4. Cập nhật tệp cấu hình (thêm thư viện Cloud Firestore)
Ngoài việc thiết lập, các bước tiếp theo cần thực hiện là cập nhật cấu hình, theo sau là các tệp ứng dụng. Trước đây, thay đổi duy nhất về cấu hình là hoán đổi gói nhỏ trong tệp requirements.txt
, vì vậy hãy thực hiện việc đó ngay.
Thay thế dòng google-cloud-datastore
bằng google-cloud-firestore
trong requirements.txt
để có dạng như sau:
Flask==1.1.2
google-cloud-firestore==2.0.2
Bạn nên sử dụng phiên bản mới nhất của mỗi thư viện; số phiên bản ở trên là số mới nhất tại thời điểm viết bài này. Mã trong thư mục repo complete được cập nhật thường xuyên hơn và có thể có phiên bản mới hơn.
Không có thay đổi nào khác về cấu hình, vì vậy, app.yaml
và templates/index.html
vẫn giữ nguyên.
5. Cập nhật tệp ứng dụng
Chỉ có một tệp ứng dụng là main.py
, vì vậy, tất cả thay đổi trong phần này chỉ ảnh hưởng đến tệp đó.
1. Nhập
Việc chuyển đổi tính năng nhập gói là một thay đổi nhỏ từ datastore
sang firestore
:
- TRƯỚC KHI:
from google.cloud import datastore
- SAU:
from google.cloud import firestore
2. Quyền truy cập vào Firestore
Sau khi khởi chạy Flask, hãy tạo ứng dụng Firestore của bạn. Thực hiện thay đổi tương tự như trên nhưng để khởi chạy ứng dụng:
- TRƯỚC KHI:
app = Flask(__name__)
ds_client = datastore.Client()
- SAU:
app = Flask(__name__)
fs_client = firestore.Client()
Bằng việc di chuyển từ Cloud NDB sang Cloud Datastore, bạn đã thực hiện xong phần công việc khó khăn để truy cập Cloud Firestore. Với Datastore, bạn tạo các bản ghi dữ liệu dưới dạng Thực thể được tạo thành từ các Thuộc tính phổ biến và nhóm các bản ghi đó theo Khoá. Bản ghi dữ liệu trong Firestore là Tài liệu, được tạo thành từ các cặp khoá-giá trị và được nhóm với nhau thành Bộ sưu tập. Để di chuyển từ Datastore, bạn cần suy nghĩ về những điểm khác biệt này vì chúng sẽ hiện ra khi bạn tạo bản ghi dữ liệu cũng như truy vấn chúng. Kết quả có thể khác nhau tuỳ thuộc vào độ phức tạp của mã Datastore.
Đối với Datastore, bạn sẽ truy vấn dựa trên loại Thực thể cùng với tiêu chí lọc và sắp xếp. Đối với Firestore, việc truy vấn dữ liệu cũng tương tự. Hãy xem một ví dụ nhanh, giả sử các giá trị truy vấn, ứng dụng (ds_client
hoặc fs_client
tương ứng) này và dữ liệu nhập:
from datetime import datetime
from firestore.Query import DESCENDING
OCT1 = datetime(2020, 10, 1)
LIMIT = 10
Đối với Datastore, hãy truy vấn 10 thực thể Visit
gần đây nhất mới hơn ngày 1 tháng 10 năm 2020 theo thứ tự giảm dần:
query = ds_client.query(kind='Visit')
query.add_filter('timestamp', '>=', datetime(2020, 10, 1))
query.order = ['-timestamp']
return query.fetch(limit=LIMIT)
Làm tương tự với Firestore, trong bộ sưu tập Visit
:
query = fs_client.collection('Visit')
query.where('timestamp', '>=', datetime(2020, 10, 1))
query.order_by('timestamp', direction=DESCENDING)
return query.limit(LIMIT).stream()
Truy vấn ứng dụng mẫu đơn giản hơn (không có mệnh đề "WHERE"). Để xem lại, sau đây là mã Cloud Datastore:
- TRƯỚC KHI:
def store_visit(remote_addr, user_agent):
entity = datastore.Entity(key=ds_client.key('Visit'))
entity.update({
'timestamp': datetime.now(),
'visitor': '{}: {}'.format(remote_addr, user_agent),
})
ds_client.put(entity)
def fetch_visits(limit):
query = ds_client.query(kind='Visit')
query.order = ['-timestamp']
return query.fetch(limit=limit)
Khi di chuyển sang Firestore, bạn sẽ thấy cách tạo tài liệu mới tương tự như thực thể và truy vấn như đã trình bày ở phần trước.
- SAU:
def store_visit(remote_addr, user_agent):
doc_ref = fs_client.collection('Visit')
doc_ref.add({
'timestamp': datetime.now(),
'visitor': '{}: {}'.format(remote_addr, user_agent),
})
def fetch_visits(limit):
visits_ref = fs_client.collection('Visit')
visits = (v.to_dict() for v in visits_ref.order_by('timestamp',
direction=firestore.Query.DESCENDING).limit(limit).stream())
return visits
Hàm chính root()
vẫn giữ nguyên như trong tệp mẫu index.html
. Kiểm tra kỹ các thay đổi, lưu, triển khai và xác minh.
6. Tóm tắt/Dọn dẹp
Triển khai ứng dụng
Triển khai lại ứng dụng bằng gcloud app deploy
và xác nhận rằng ứng dụng hoạt động bình thường. Mã của bạn bây giờ phải khớp với nội dung trong Kho lưu trữ mô-đun 6 (hoặc phiên bản 2.x nếu đó là lựa chọn ưu tiên của bạn).
Nếu bạn đã xem loạt video này mà không thực hiện bất kỳ lớp học lập trình nào trước đó thì ứng dụng sẽ không thay đổi; trang này sẽ ghi lại tất cả lượt truy cập vào trang web chính (/
) và có dạng như sau khi bạn đã truy cập đủ số lần vào trang web:
Chúc mừng bạn đã hoàn tất việc di chuyển Phụ lục 6 (không bắt buộc) này. Đây có thể là một trong những di chuyển cuối cùng mà bạn có thể thực hiện cho đến khi lưu trữ dữ liệu của App Engine. Một cách di chuyển khác mà bạn có thể cân nhắc là sử dụng vùng chứa ứng dụng cho Cloud Run nếu chưa thực hiện (xem Mô-đun 4 và 5, lớp học lập trình được liên kết bên dưới).
Không bắt buộc: Dọn dẹp
Còn việc dọn dẹp để tránh bị tính phí cho đến khi bạn sẵn sàng chuyển sang lớp học lập trình di chuyển tiếp theo thì sao? Là nhà phát triển hiện tại, có thể bạn đã nắm bắt được thông tin về giá của App Engine.
Không bắt buộc: Tắt ứng dụng
Nếu bạn chưa sẵn sàng chuyển đến hướng dẫn tiếp theo, hãy vô hiệu hoá ứng dụng để tránh phát sinh phí. Khi đã sẵn sàng chuyển sang lớp học lập trình tiếp theo, bạn có thể bật lại lớp học này. Mặc dù bị vô hiệu hoá, ứng dụng của bạn sẽ không bị tính phí. Tuy nhiên, một điều khác bạn có thể bị tính phí là mức sử dụngFirestore nếu vượt quá hạn mức miễn phí, vì vậy, hãy xoá đủ để nằm trong giới hạn đó.
Mặt khác, nếu không định tiếp tục quá trình di chuyển và muốn xoá hoàn toàn mọi thứ, thì bạn có thể ngừng cung cấp dự án của mình.
Các bước tiếp theo
Ngoài hướng dẫn này, bạn có thể tham khảo một số lớp học lập trình khác về mô-đun di chuyển:
- Mô-đun 7: Hàng đợi tác vụ đẩy của App Engine (bắt buộc nếu bạn sử dụng Hàng đợi tác vụ [push])
- Thêm các tác vụ đẩy
taskqueue
của App Engine vào ứng dụng Mô-đun 1 - Giúp người dùng chuẩn bị để di chuyển sang Cloud Tasks trong Mô-đun 8
- Thêm các tác vụ đẩy
- Học phần 4: Di chuyển sang Cloud Run bằng Docker
- Trong vùng chứa để ứng dụng chạy trên Cloud Run bằng Docker
- Quá trình di chuyển này cho phép bạn tiếp tục sử dụng Python 2.
- Học phần 5: Di chuyển sang Cloud Run bằng các gói bản dựng trên đám mây
- Trong vùng chứa của ứng dụng để chạy trên Cloud Run bằng Cloud Buildpacks
- Bạn không cần phải biết gì về Docker, vùng chứa hoặc
Dockerfile
. - Yêu cầu ứng dụng của bạn phải chuyển sang Python 3 (Gói bản dựng không hỗ trợ Python 2)
7. Tài nguyên khác
Vấn đề/phản hồi trong lớp học lập trình mô-đun di chuyển App Engine
Nếu bạn gặp vấn đề với lớp học lập trình này, vui lòng tìm vấn đề của bạn trước khi gửi. Đường liên kết để tìm kiếm và báo cáo vấn đề mới:
Tài nguyên di chuyển
Bạn có thể tìm thấy các đường liên kết đến các thư mục repo cho Mô-đun 3 (START) và Mô-đun 6 (Finish) trong bảng bên dưới. Bạn cũng có thể truy cập vào các tệp này từ kho lưu trữ dành cho tất cả quá trình di chuyển App Engine. Bạn có thể sao chép hoặc tải tệp ZIP xuống.
Codelab | Python 2 | Python 3 |
(mã) | ||
Học phần 6 | (không áp dụng) |
Tài nguyên của App Engine
Dưới đây là các thông tin khác liên quan đến việc di chuyển cụ thể này:
- Tài liệu tham khảo về Python Cloud Datastore và Cloud Firestore
- Di chuyển sang Python 3 và thời gian chạy thế hệ mới của GAE
- Chung