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 tốc độ của riêng bạn) nhằm mục đích giúp các nhà phát triển Google App Engine (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 hoạt động di chuyển như vậy liên quan đến việc chuyển từ các dịch vụ đi kèm với thời gian chạy ban đầu vì thời gian chạy thế hệ tiếp theo linh hoạt hơn, mang đến cho người dùng nhiều lựa chọn dịch vụ hơn. 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. Đây cũng là chủ đề của lớp học lập trình này.
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 và không cần di chuyển thêm. Tuy nhiên, Cloud Firestore là kho dữ liệu NoSQL mới nhất, có khả năng mở rộng, tính sẵn sàng cao và có các tính năng của Cơ sở dữ liệu theo thời gian thực của Firebase.
Bạn đã đến đúng nơi nếu là một nhà phát triển muốn dùng Firestore để tận dụng các tính năng của dịch vụ này hoặc ít nhất là đủ quan tâm để tìm hiểu về quy trình di chuyển. Hướng dẫn này hướng dẫn bạn cách di chuyển một ứng dụng App Engine sử dụ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 cơ bản về Python
- Có kiến thức cơ bản về các lệnh Linux thường dùng
- Kiến thức cơ bản về cách phát triển và triển khai các ứ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 lớp học lập trình đó sang Python 3, trước khi bắt đầu lớp học lập trình này (Mô-đun 6).
- Một Ứng dụng App Engine Python 3 Cloud Datastore trong Mô-đun 3 đang hoạt động.
Bản 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 riêng vào năm 2013, Google Cloud Datastore và hiện được các nhà phát triển truy cập bên ngoài App Engine. Năm tiếp theo, Google đã mua lại Firebase. Vào thời điểm đó, Firebase nổi tiếng với cơ sở dữ liệu theo thời gian thực.
Trong vài năm tiếp theo, các 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, dịch vụ này đã được đổi tên 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ể sử dụng Cloud Firestore một cách tự nhiên, trong khi các cơ sở dữ liệu Datastore hiện có đã được chuyển đổi sang Firestore ở chế độ nền và hiện 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 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 không thể chuyển sang Firestore. Tương tự, sau khi chọn chế độ gốc của Firestore, họ sẽ không thể chuyển lại sang Datastore (hoặc đúng hơn là Firestore ở chế độ Datastore). Hãy đọc trang chọn giữa Cloud Firestore ở chế độ Datastore hoặc 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 những điểm khác biệt giữa việc sử dụng Cloud Datastore và Cloud Firestore.
Đây không phải là quy trình di chuyển mà người dùng cần thực hiện, đó là lý do quy trình này là quy 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 có những lợi thế rõ ràng như xác thực máy khách, tích hợp quy tắc Firebase và tất nhiên là 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.
- Bạn không thể chuyển một dự án mà ứng dụng đã thêm các thực thể Datastore sang Firestore ở chế độ gốc
- Tương tự, một dự án đã chọn Firestore ở chế độ gốc sẽ không thể quay lại 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ó trong Firestore.
- Các công cụ xuất và nhập là các trường hợp "nguyên thuỷ" và "tất cả hoặc không có gì".
- Nếu ứng dụng của bạn có nhiều thực thể Datastore, thì 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 nên phân bổ các hoạt động này (trong 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 khoảng thời gian để các bản cập nhật DNS có hiệu lực.
- Datastore và Firestore có các mô hình dữ liệu tương tự nhưng khác nhau, vì vậy, việc di chuyển đòi hỏi bạn phải cập nhật cách hoạt động của ứng dụng/dịch vụ
- Truy vấn đối tượng cấp trên từ Kho dữ liệu hiện là Truy vấn tập hợp của Firestore (mặc định)
- Các truy vấn thuộc loại rộng từ Datastore là Truy vấn nhóm tập hợp của Firestore
- Chỉ mục và cách xử lý khác nhau, v.v.
Tuy nhiên, nếu bạn có một ứng dụng khá đơn giản cần xem xét để di chuyển, chuẩn bị mô phỏng quá trình di chuyển đó hoặc chỉ đơn giản là muốn tìm hiểu về Datastore so với Firestore, thì vui lòng 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ó trong Python 3. Tuy nhiên, vì Cloud Firestore cũng hỗ trợ phiên bản 2.x, nên người dùng có thể suy đoán những điểm khác biệt khi sử dụng. Một ví dụ là các bản ghi Firestore sử dụng chuỗi Unicode (thay vì chuỗi byte), vì vậy, bạn cần có chỉ báo u'' hàng đầu cho các ký tự chuỗi Python 2, tức là hàm 2.x store_visit() 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ự. Vấn đề duy nhất khác cần cân nhắc là thư viện Cloud Firestore 2.x đã "đóng băng" về mặt phát triển, vì vậy, ngày càng có nhiều tính năng mới/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 trong hướng dẫn này:
- Thiết lập/Công việc chuẩn bị
- Thêm thư viện Cloud Firestore
- Cập nhật tệp ứng dụng
3. Thiết lập/Công việc 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ã nguồn rồi triển khai ứng dụng cơ sở để đảm bảo chúng ta bắt đầu bằng mã nguồn hoạt động.
1. Thiết lập dự án
Bạn nên sử dụng lại dự án mà bạn đã dùng để hoàn thành lớp học lập trình 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. Đảm bảo dự án có một tài khoản thanh toán đang hoạt động và App Engine (ứng dụng) được bật.
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à bạn phải có một ứng dụng mẫu hoạt động ở Mô-đun 3. Nếu không có, hãy hoàn tất hướng dẫn về Mô-đun 3 (đường liên kết ở trên) trước khi tiếp tục. Nếu đã quen thuộc với nội dung của lớp học lập trình này, bạn có thể bắt đầu bằng cách lấy mã của Mô-đun 3 bên dưới.
Cho dù bạn dùng mã của mình hay mã của chúng tôi, mã của Mô-đun 3 sẽ là nơi chúng ta BẮT ĐẦU. Lớp học lập trình Mô-đun 6 này sẽ hướng dẫn bạn từng bước và khi hoàn tất, lớp học này sẽ giống với mã ở điểm KẾT THÚC. (Hướng dẫn này chỉ dành cho Python 3.)
- BẮT ĐẦU: Kho lưu trữ Phụ lục 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 trong 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 mà bạn cần thực hiện ngay:
- Làm quen lại với công cụ dòng lệnh
gcloud(nếu cần). - (Triển khai lại) mã Mô-đun 3 vào 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 các bước đó đang hoạt động, chúng ta sẽ tiếp tục trong hướng dẫn này, bắt đầu bằng các tệp cấu hình.
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:grpciovàsetuptools. - Đảm bảo
appengine_config.pyvẫn dùngpkg_resourcesvàgoogle.appengine.ext.vendorđể hướng ứng dụng đến các tài nguyên của bên thứ ba. - Trong phần tiếp theo là cập nhật
requirements.txt, bạn phải sử dụnggoogle-cloud-firestore==1.9.0vì đó 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.txtcủa bạn có một mục chogoogle-cloud-core, hãy giữ nguyên. - Xoá
librồ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 thiết là cập nhật cấu hình, sau đó là các tệp ứng dụng. Đối với trường hợp trước, thay đổi cấu hình duy nhất là một lần hoán đổi gói nhỏ trong tệp requirements.txt của bạn, vì vậy, hãy thực hiện ngay bây giờ.
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; các số phiên bản ở trên là phiên bản mới nhất tại thời điểm viết bài này. Mã trong thư mục FINISH của kho lưu trữ đượ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, main.py, nên mọi thay đổi trong phần này chỉ ảnh hưởng đến tệp đó.
1. Nhập
Việc chuyển đổi 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 tạo Flask, hãy tạo ứng dụng Firestore. Thực hiện thay đổi tương tự như trên nhưng đối với quá trình 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 cách di chuyển từ Cloud NDB sang Cloud Datastore, bạn đã thực hiện những bước quan trọng để chuyển sang Cloud Firestore. Với Datastore, bạn tạo các bản ghi dữ liệu dưới dạng Các thực thể được tạo thành từ các Thuộc tính chung và nhóm chúng theo Khoá. Các bản ghi dữ liệu trong Firestore là các Tài liệu, được tạo thành từ các cặp khoá-giá trị và được nhóm lại với nhau thành các Tập hợp. Việc di chuyển từ Datastore đòi hỏi bạn phải suy nghĩ về những điểm khác biệt này vì chúng sẽ xuất hiện khi bạn tạo bản ghi dữ liệu cũng như truy vấn bản ghi. Kết quả của bạn có thể thay đổi tuỳ thuộc vào độ phức tạp của mã Datastore.
Đối với Datastore, bạn thực hiện các 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 (tương ứng là ds_client hoặc fs_client) và các mục nhập này:
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 được tạo sau 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ự cho Firestore, từ Visit collection:
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, đâ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 việc tạo tài liệu mới tương tự như các thực thể và truy vấn như đã trình bày 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ư 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. Giờ đây, mã của bạn sẽ khớp với mã trong kho lưu trữ Mô-đun 6 (hoặc phiên bản 2.x nếu bạn muốn).
Nếu bạn bắt đầu tham gia loạt bài này mà chưa thực hiện bất kỳ lớp học lập trình nào trước đó, thì bản thân ứng dụng sẽ không thay đổi; ứng dụng này sẽ đăng ký tất cả lượt truy cập vào trang web chính (/) và trông như thế này sau khi bạn truy cập vào trang web đủ số lần:

Chúc mừng bạn đã hoàn thành quy trình di chuyển không bắt buộc này trong Mô-đun 6. Đây có thể là một trong những lần di chuyển cuối cùng (nếu không phải là lần cuối cùng) mà bạn có thể thực hiện đối với việc lưu trữ dữ liệu trên App Engine. Một lựa chọn di chuyển khác mà bạn có thể cân nhắc là đóng gói ứng dụng cho Cloud Run nếu bạn chưa thực hiện (xem Mô-đun 4 và 5, các 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
Bạn có thể dọn dẹp để tránh bị tính phí cho đến khi sẵn sàng chuyển sang lớp học lập trình di chuyển tiếp theo. Là nhà phát triển hiện tại, có thể bạn đã nắm đượ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 sang hướng dẫn tiếp theo, hãy tắt ứng dụng để không bị tính 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 tính năng này. Khi ứng dụng của bạn bị vô hiệu hoá, ứng dụng sẽ không nhận được lưu lượng truy cập nào để phát sinh phí. Tuy nhiên, một khoản phí khác mà bạn có thể phải trả là mức sử dụng Firestore nếu mức này vượt quá hạn mức miễn phí. Vì vậy, hãy xoá đủ để giảm xuống dưới hạn mức đó.
Mặt khác, nếu không muốn tiếp tục di chuyển và muốn xoá hoàn toàn mọi thứ, bạn có thể tắt dự án.
Các bước tiếp theo
Ngoài hướng dẫn này, bạn có thể xem xét một số lớp học lập trình khác về mô-đun di chuyển:
- Module 7: App Engine Push Task Queues (bắt buộc nếu bạn sử dụng Task Queues [push])
- Thêm các tác vụ đẩy
taskqueuecủa App Engine vào ứng dụng Mô-đun 1 - Chuẩn bị cho người dùng di chuyển sang Cloud Tasks trong Mô-đun 8
- Thêm các tác vụ đẩy
- Mô-đun 4: Di chuyển sang Cloud Run bằng Docker
- Đóng gói ứng dụng của bạn vào vùng chứa để 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.
- Module 5: Di chuyển sang Cloud Run bằng Cloud Buildpacks
- Tạo vùng chứa cho ứng dụng để chạy trên Cloud Run bằng Cloud Buildpacks
- Bạn không cần biết gì về Docker, vùng chứa hoặc
Dockerfile. - Yêu cầu ứng dụng của bạn đã di chuyển sang Python 3 (Buildpacks không hỗ trợ Python 2)
7. Tài nguyên khác
Vấn đề/ý kiến phản hồi về 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 kiếm vấn đề của bạn trước khi báo cáo. Đường liên kết để tìm kiếm và tạo vấn đề mới:
Tài nguyên di chuyển
Bạn có thể tìm thấy đường liên kết đến các thư mục repo cho Mô-đun 3 (BẮT ĐẦU) và Mô-đun 6 (KẾT THÚC) trong bảng bên dưới. Bạn cũng có thể truy cập vào kho lưu trữ cho tất cả các hoạt động di chuyển App Engine mà bạn có thể sao chép hoặc tải tệp ZIP xuống.
Lớp học lập trình | Python 2 | Python 3 |
(mã) | ||
Mô-đun 6 | (không áp dụng) |
Tài nguyên App Engine
Dưới đây là các tài nguyên khác liên quan đến quá trình di chuyển cụ thể này:
- Tài liệu tham khảo về Cloud Datastore và Cloud Firestore của Python
- Di chuyển sang Python 3 và thời gian chạy thế hệ tiếp theo của GAE
- Chung