Phân tích và xử lý lỗi thường gặp trong Spanner Local
Log của Spanner Local được ghi vào console hoặc file log tùy thuộc vào cách khởi động. Khi gặp lỗi, hãy kiểm tra ngay thông báo lỗi để xác định nguyên nhân.
Nguyên nhân phổ biến nhất là xung đột cổng hoặc lỗi định dạng dữ liệu không tương thích với giao thức Spanner.
Để xem log thời gian thực, bạn cần theo dõi đầu ra của tiến trình emulator.
tail -f /var/log/spanner-local.log 2>&1 | grep -i "error\|exception"
Kết quả mong đợi: Bạn sẽ thấy các dòng log chứa từ khóa "error" hoặc "exception" hiện ra ngay lập tức khi có sự cố xảy ra.
Xử lý lỗi cổng bị chiếm dụng (Port Conflict)
Spanner Local mặc định chạy trên cổng 9010. Nếu cổng này đã bị chiếm bởi dịch vụ khác, emulator sẽ không khởi động.
Cách kiểm tra xem cổng 9010 đang bị tiến trình nào chiếm dụng.
sudo lsof -i :9010
Kết quả mong đợi: Nếu có tiến trình, bạn sẽ thấy danh sách PID và tên tiến trình (ví dụ: java, python, hoặc spanner-local).
Giải pháp là thay đổi cổng mặc định khi khởi động emulator bằng tham số --port.
java -jar spanner-local.jar --port 9011
Kết quả mong đợi: Emulator khởi động thành công trên cổng 9011 mà không bị lỗi "Address already in use".
Xử lý lỗi định dạng Timestamp (Invalid Timestamp)
Spanner yêu cầu định dạng thời gian chuẩn RFC3339. Lỗi này xảy ra khi ứng dụng gửi timestamp không đúng định dạng.
Để kiểm tra, hãy xem log lỗi cụ thể trong ứng dụng client hoặc server.
grep "Invalid timestamp" /var/log/spanner-local.log
Kết quả mong đợi: Log hiển thị timestamp không hợp lệ mà ứng dụng đã gửi đi.
Khắc phục bằng cách chuẩn hóa chuỗi thời gian trong code trước khi gửi request.
echo "2024-01-01T12:00:00Z" | xargs -I {} curl -H "Content-Type: application/json" -d '{"timestamp": "{}"}' http://localhost:9010
Kết quả mong đợi: Request được chấp nhận (HTTP 200) thay vì trả về lỗi 400 Bad Request.
Quản lý quyền truy cập và Firewall trên Ubuntu 24.04
Ubuntu 24.04 mặc định sử dụng UFW (Uncomplicated Firewall). Nếu không cấu hình đúng, kết nối từ client sẽ bị chặn.
Đầu tiên, kiểm tra trạng thái hiện tại của firewall.
sudo ufw status verbose
Kết quả mong đợi: Hiển thị trạng thái "active" hoặc "inactive" cùng danh sách các rule đang có.
Để cho phép kết nối đến Spanner Local (mặc định cổng 9010), cần thêm rule cho phép traffic vào.
sudo ufw allow 9010/tcp
Kết quả mong đợi: Thông báo "Rule added" hoặc "Rule added (v6)" nếu IPv6 được kích hoạt.
Cấu hình quyền truy cập file và thư mục
Spanner Local cần quyền ghi vào thư mục lưu trữ dữ liệu (data directory) và thư mục log.
Đảm bảo user hiện tại có quyền sở hữu hoặc quyền ghi vào thư mục dữ liệu.
sudo chown -R $USER:$USER /opt/spanner/data
Kết quả mong đợi: Không có lỗi trả về, quyền sở hữu thư mục đã được chuyển sang user hiện tại.
Đặt quyền đọc/ghi/thực thi cho thư mục này để đảm bảo emulator có thể hoạt động.
sudo chmod -R 755 /opt/spanner/data
Kết quả mong đợi: Thư mục có quyền 755, cho phép owner đọc/ghi/thực thi và user/group khác chỉ đọc/thực thi.
Cấu hình SSL/TLS để bảo mật kết nối
Mặc định Spanner Local chạy trên HTTP không mã hóa. Để bảo mật, cần cấu hình SSL/TLS bằng cách sinh chứng chỉ tự ký (self-signed) hoặc dùng chứng chỉ CA.
Trước tiên, tạo thư mục chứa chứng chỉ nếu chưa có.
mkdir -p /opt/spanner/ssl && cd /opt/spanner/ssl
Kết quả mong đợi: Thư mục ssl được tạo và bạn đang ở trong thư mục đó.
Generat tự ký chứng chỉ CA và Server
Để bảo mật cao, cần tạo một Certificate Authority (CA) riêng và dùng nó để ký cho chứng chỉ server.
Đầu tiên, tạo Private Key và Self-Signed Certificate cho CA.
openssl req -x509 -newkey rsa:4096 -keyout ca-key.pem -out ca-cert.pem -days 365 -nodes -subj "/C=VN/ST=HCMC/L=District 1/O=MyCompany/OU=IT/CN=SpannerCA"
Kết quả mong đợi: Tạo ra 2 file: ca-key.pem (private key) và ca-cert.pem (public certificate) của CA.
Tiếp theo, tạo Private Key và Certificate Signing Request (CSR) cho server.
openssl req -newkey rsa:4096 -keyout server-key.pem -out server-req.pem -nodes -subj "/C=VN/ST=HCMC/L=District 1/O=MyCompany/OU=IT/CN=localhost"
Kết quả mong đợi: Tạo ra server-key.pem và server-req.pem.
Dùng CA để ký cho CSR của server, tạo ra chứng chỉ server hợp lệ.
openssl x509 -req -in server-req.pem -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -days 365
Kết quả mong đợi: File server-cert.pem được tạo ra, đây là chứng chỉ SSL hợp lệ cho localhost.
Khởi động Spanner Local với SSL
Khởi động lại emulator với các tham số chỉ định đường dẫn đến key và certificate vừa tạo.
java -jar spanner-local.jar --port 9010 --tls=true --tls-cert=/opt/spanner/ssl/server-cert.pem --tls-key=/opt/spanner/ssl/server-key.pem
Kết quả mong đợi: Emulator khởi động với thông báo "TLS enabled" trong log.
Để kiểm tra kết nối an toàn, dùng curl với tùy chọn --cacert để chỉ định CA cert.
curl --cacert /opt/spanner/ssl/ca-cert.pem https://localhost:9010
Kết quả mong đợi: Kết nối thành công (HTTP 200) mà không có cảnh báo "certificate unknown" hoặc "SSL handshake failed".
Khắc phục lỗi OutOfMemory với dữ liệu lớn
Spanner Local chạy trên JVM. Khi dữ liệu tăng lên, heap memory mặc định có thể không đủ, gây lỗi OutOfMemoryError.
Kiểm tra giới hạn memory hiện tại của JVM bằng lệnh jstat hoặc xem log lỗi.
grep "OutOfMemoryError" /var/log/spanner-local.log
Kết quả mong đợi: Log hiển thị lỗi "Java heap space" hoặc "GC overhead limit exceeded".
Tăng dung lượng Heap Memory
Giải pháp là tăng tham số -Xmx (Maximum Heap Size) khi khởi động Java.
Giả sử bạn muốn tăng memory lên 8GB, hãy điều chỉnh lệnh khởi động như sau.
java -Xmx8g -Xms8g -jar spanner-local.jar --port 9010
Kết quả mong đợi: Emulator khởi động với giới hạn memory mới, không còn lỗi OutOfMemory khi xử lý dữ liệu lớn.
Để đảm bảo hiệu suất, cũng nên tăng kích thước initial heap (-Xms) bằng với maximum heap (-Xmx).
Điều chỉnh Garbage Collector (GC)
Với dữ liệu rất lớn, GC mặc định có thể gây lag. Hãy chuyển sang G1GC (Garbage First) để tối ưu.
Thêm tham số GC vào lệnh khởi động.
java -Xmx8g -Xms8g -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -jar spanner-local.jar --port 9010
Kết quả mong đợi: Log JVM hiển thị thông báo "Using G1 GC", thời gian dừng (pause time) giảm xuống.
Chiến lược chuyển đổi từ Spanner Local sang Cloud Production
Chuyển đổi từ Local sang Cloud không chỉ là thay đổi endpoint. Cần kiểm tra lại cấu hình, bảo mật và logic code.
Chuẩn bị tài nguyên trên Google Cloud
Trước tiên, tạo Instance và Database trên Google Cloud Spanner thông qua Console hoặc gcloud CLI.
gcloud spanner instances create my-prod-instance --config=regional-us --description="Production Spanner Instance" --num-nodes=3
Kết quả mong đợi: Instance được tạo thành công với 3 nodes.
Tạo database trong instance đó.
gcloud spanner databases create my-prod-db --instance=my-prod-instance
Kết quả mong đợi: Database được tạo và sẵn sàng nhận kết nối.
Chuyển đổi cấu hình kết nối (Connection String)
Trong Local, bạn dùng "localhost:9010". Trong Cloud, cần dùng endpoint của instance.
Lấy endpoint của instance để cấu hình trong ứng dụng.
gcloud spanner instances describe my-prod-instance --format="value(endpoints)"
Kết quả mong đợi: Trả về chuỗi endpoint dạng "us-central1-spanner.googleapis.com:443".
Cập nhật code ứng dụng (Go/Python) để thay thế endpoint và sử dụng Authentication thông qua Service Account.
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account-key.json"
Kết quả mong đợi: Ứng dụng tự động xác thực với Google Cloud khi khởi động.
Migration Schema và Dữ liệu
Dùng công cụ migration hoặc script để chuyển schema từ Local sang Cloud.
Tạo file DDL từ Local và áp dụng lên Cloud.
gcloud spanner databases ddl update my-prod-db --instance=my-prod-instance --ddl="CREATE TABLE Users (Id INT64, Name STRING(100)) PRIMARY KEY (Id);"
Kết quả mong đợi: Bảng Users được tạo trên Cloud Spanner với schema tương tự.
Đối với dữ liệu, sử dụng Cloud Dataflow hoặc script ETL để dump từ Local và import vào Cloud.
gcloud spanner databases import my-prod-db my-prod-instance --gcs-uri="gs://my-bucket/spanner-backup"
Kết quả mong đợi: Dữ liệu từ backup file được import thành công vào database Cloud.
Verify kết quả chuyển đổi
Chạy các test case tự động để đảm bảo ứng dụng hoạt động đúng trên môi trường Cloud.
go test -v ./... -run TestSpannerConnection
Kết quả mong đợi: Tất cả test case passed, không có lỗi kết nối hay schema mismatch.
Điều hướng series:
Mục lục: Series: Triển khai Database NewSQL với Google Spanner và Ubuntu 24.04
« Phần 5: Tối ưu hiệu năng và mở rộng quy mô Spanner trên Ubuntu