Sử dụng Dapr cho kiến trúc phân tán (Phần 2): Demo

Cùng bắt tay xây dựng hai ứng dụng thuần mây đơn giản để hiểu rõ hơn về ưu điểm của Dapr trong việc xây dựng các hệ thống dịch vụ phân tán.

Dapr Demo poster

Đọc thêm: Sử dụng Dapr cho kiến trúc phân tán

phần trước chúng ta đã tìm hiểu tổng quan về Dapr cũng như các khối dựng sẵn (building-block) mà Dapr cung cấp. Trong bài viết này, ta sẽ đi sâu vào tìm hiểu cách sử dụng Dapr trong thực tế qua 2 ứng dụng đơn giản: Ứng dụng tạo Order và Ứng dụng Máy tính (Calculator).

Chuẩn bị

Trước khi bắt đầu, các bạn hãy chắc chắn mình đã cài đặt và thiết lập Dapr như trong phần trước.

Tiếp theo, các bạn lấy mã nguồn dự án quickstarts của Dapr từ github như sau:

git clone https://github.com/dapr/quickstarts --depth=1
cd quickstarts

Trong các phần tiếp theo thì mặc định thư mục làm việc sẽ là thư mục quickstarts này.

Ứng dụng Order

Giới thiệu

Trong ứng dụng này, chúng ta sẽ sử dụng khối Service Invocation của Dapr để trao đổi thông tin của 2 dịch vụ con là Checkout và Process. Kiến trúc ứng dụng này đơn giản như sau:

Kiến trúc của Ứng dụng Order

Kiến trúc của Ứng dụng Order

Bước 1: Khởi tạo Order Processor Service bằng Dapr

Đến thư mục order-processor và khởi chạy ứng dụng Order như sau:

cd service_invocation/go/http/order-processor
dapr run --app-port 6006 --app-id order-processor --app-protocol http --dapr-http-port 3501 -- go run .

Bước 2: Khởi tạo Checkout Service bằng Dapr

Đến thư mục checkout và khởi chạy ứng dụng Checkout như sau:

cd service_invocation/go/http/checkout
dapr run --app-id checkout --dapr-http-port 3500 -- go run .

Kết quả

  • Dịch vụ Checkout tạo ra 20 orders.

Màn hình kết quả khi chạy dịch vụ Checkout

Màn hình kết quả khi chạy dịch vụ Checkout

  • Dịch vụ Order Process nhận được 20 orders và xử lý thành công.

Màn hình kết quả dịch vụ Order nhận đủ đơn hàng

Màn hình kết quả dịch vụ Order nhận đủ đơn hàng

Sử dụng Dapr Multi-App

  • Thông thường khi sử dụng kiến trúc vi dịch vụ (microservices), ta cần phải khởi chạy nhiều ứng dụng hoặc dịch vụ cùng lúc hoặc theo thứ tự cần thiết như trong ví dụ trên. Dapr Multi-App được tạo ra để giúp cho lập trình viên có thể dễ dàng khởi chạy nhiều Service cùng lúc chỉ với 1 dòng lệnh. Thay vì dùng 2 lệnh để khởi tạo Oder Processor và Checkout Service ta chỉ cần chạy lệnh sau: dapr run -f
  • Sau đó, dùng lệnh dapr stop -f . để tắt các dịch vụ đã chạy.

Ứng dụng Máy tính (Calculator)

Giới thiệu

Trong phần này chúng ta sẽ làm 1 ứng dụng Máy tính phức tạp hơn bằng cách sử dụng kết hợp nhiều dịch vụ con và nhiều khối Dapr cùng lúc. Ứng dụng Máy tính trong phần này sẽ bao gồm 1 phần Frontend (bằng React) và 4 phần Backend (Golang cho phần tính cộng, Python cho phần tính nhân, NodeJS cho phần tính chia và .NET Core cho phần tính trừ). Các khối Dapr được sử dụng bao gồm khối Invocation và khối State Mangement.

Kiến trúc của Ứng dụng này như sau:

Kiến trúc của ứng dụng Máy tính đơn giản

Kiến trúc của ứng dụng Máy tính đơn giản

Chuẩn bị môi trường local

  • Cài đặt Dapr CLI

  • Cài đặt Golang 1.20

  • Cài đặt Python 3

  • Cài đặt .NET SDK 7

  • Cài đặt NodeJS

  • Trong windows ta có thể dùng winget để đơn giản hoá quá trình cài đặt như sau:

    winget install Dapr.CLI -e && winget install GoLang.Go -e && winget install Python.Python.3.10 -e && winget install Microsoft.DotNet.SDK.7 -e && winget install OpenJS.NodeJS.LTS
    

    Nếu chưa lấy source thì các bạn hãy theo hướng dẫn ở phần trước để lấy source code về nhé

Khởi tạo các app trên môi trường local

Khởi chạy app Add như sau:

  • Đến thư mục go/ và chạy lệnh để cài thư viện gorilla: go get -u github.com/gorilla/mux
  • Chạy Dapr: dapr run --app-id addapp --app-port 6000 --dapr-http-port 3503 go run app.go

Khởi chạy app Subtract như sau:

  • Thiết lập biến môi trường set ASPNETCORE_URLS=http://localhost:7001
  • Đến thư mục csharp/ và chạy lệnh build: dotnet build
  • Đến thư build bin/Debug/netcoreapp7.0 và chạy Dapr: dapr run --app-id subtractapp --app-port 7001 --dapr-http-port 3504 dotnet Subtract.dll

Khởi chạy app Divide như sau:

  • Đến thư mục node/ và chạy lệnh build: npm install
  • Chạy Dapr: dapr run --app-id divideapp --app-port 4000 --dapr-http-port 3502 node app.js

Khởi chạy app Multiply như sau:

  • Thiết lập biến môi trường set FLASK_RUN_PORT=5001
  • Đến thư mục python/ và cài thư viện flask: pip3 install wheel python-dotenv flask_cors flask
  • Chạy Dapr: dapr run --app-id multiplyapp --app-port 5001 --dapr-http-port 3501 flask run
  • Trong trường hợp bị lỗi khởi động flask trong môi trường CLI thì cần thiết lập thêm biến môi trường như sau rồi chạy lại: set FLASK_RUN_FROM_CLI=true

Khởi chạy app front-end như sau:

  • Đến thư mục react-calculator/ và chạy lệnh build

    npm install
    npm run buildclient
    
  • Chạy Dapr: dapr run --app-id frontendapp --app-port 8080 --dapr-http-port 3507 node server.js

  • Mở trình duyệt tại địa chỉ http://localhost:8080/ bạn sẽ thấy ứng dụng Calc như sau:

Giao diện ứng dụng máy tính đơn giản

Giao diện ứng dụng máy tính đơn giản

  • Tắt các app đã tạo:

    dapr stop --app-id addapp
    dapr stop --app-id subtractapp
    dapr stop --app-id divideapp
    dapr stop --app-id multiplyapp
    dapr stop --app-id frontendapp
    

Vai trò của Dapr

Trong ví dụ này ta đã giả lập một môi trường phát triển phần mềm phức tạp bao gồm nhiều ngôn ngữ lập trình khác nhau (C#, golang, nodejs, python) cùng giao tiếp qua REST API. Đối với một hệ thống kiến trúc vi dịch vụ, việc sử dụng nhiều ngôn ngữ lập trình hoặc công nghệ khác nhau (polyglot programming) giúp phát huy thế mạnh của từng loại ngôn ngữ cũng như cho phép các nhóm phát triển phần mềm sử dụng công cụ mà họ thành thạo nhất. Ở đây, Dapr được sử dụng như phương tiện để giúp lập trình viên đơn giản hoá việc lập trình đa ngôn ngữ, giúp tự động khám phá dịch vụ (service discovery) và quản lý trạng thái (state management) trong một hệ thống vi kiến trúc.

Tiếp theo ta sẽ đi sâu vào chi tiết cách sử dụng Dapr trong ví dụ này.

Đầu tiên, trong file server.js của phần front-end ta có thể thấy service này chỉ cần biết địa chỉ URL của Dapr Invocation và sau đó có thể gọi đến các dịch vụ Cộng, Trừ, Nhân, Chia tương ứng mà không cần biết địa chỉ IP của dịch vụ này.

Cấu hình địa chỉ dịch vụ đơn giản

Cấu hình địa chỉ dịch vụ đơn giản

Ở đây Dapr đóng vai trò trung gian tự động khám phá dịch vụ bằng cách sử dụng giao thức mDNS để phân giải tên thành địa chỉ IP. Các bạn có thể tìm hiểu thêm phần Service Invocation của Dapr tại đây.

Tiếp theo, đối với phần quản lý trạng thái, ta chỉ cần khai báo sử dụng Dapr State Management trong file server.js như sau:

Cấu hình địa chỉ Quản lý Trạng thái trên Dapr

Cấu hình địa chỉ Quản lý Trạng thái trên Dapr

Sau đó phần client có thể dễ dàng gọi đến các API có sẵn để thay đổi trạng thái như trong file App.js

Thay đổi Trạng thái trên Dapr

Thay đổi Trạng thái trên Dapr

Việc sử dụng State như trên giúp lập trình viên có thể tập trung xây dựng tính năng cho phần mềm thay vì phải đau đầu chọn lựa giữa nhiều loại bộ nhớ đệm (cache) khác nhau như Redis, Memcached, Couchbase,...

Sử dụng k8s

Trong thực tế, việc khởi tạo 1 ứng dụng với nhiều dịch vụ khác nhau cần rất nhiều bước thiết lập và cũng dễ xảy ra sai sót. Vì vậy ta cần dùng 1 kịch bản tạo sẵn để đơn giản hoá những công việc lặp đi lặp lại như trên.

  • Để chuẩn bị cho phần này, bạn cần thiết lập Dapr với Kubernetes (k8s) bằng cách chạy lệnh dapr init -k
  • Kiểm tra Dapr trên k8s bằng cách chạy lệnh: kubectl get pods --namespace dapr-system

Các dịch vụ Dapr chạy trên Kubernetes

Các dịch vụ Dapr chạy trên Kubernetes

  • Vào thư mục deploy/ và triển khai các app cần thiết như sau: kubectl apply -f .
  • Sau khi các app đã được khởi tạo thành công, kiểm tra lại bằng lệnh kubectl get pods

Kiểm tra các dịch vụ Calculator được khởi chạy

Kiểm tra các dịch vụ Calculator được khởi chạy

  • Để chạy ứng dụng ta cần mở Port của ứng dụng front-end qua k8s như sau: kubectl port-forward service/calculator-front-end 8000:80
  • Mở trình duyệt tại địa chỉ http://localhost:8000/ để sử dụng ứng dụng Máy Tính
  • Nếu sử dụng Docker Desktop, ta có thể xem danh sách các Containers đang chạy của Dapr:

Danh sách Containers của Dapr

Danh sách Containers của Dapr

  • Trước khi kết thúc ta cần chạy lệnh: kubectl delete -f . để xoá các tài nguyên đã tạo.

Kết luận

Trong bài viết này, ta đã tìm hiểu cách sử dụng Dapr để tạo các ứng dụng tương tự như trong thực tế cũng như áp dụng k8s cùng với Dapr để nhanh chóng triển khai hệ thống vi dịch vụ lên các môi trường phát triển khác nhau. Hi vọng bài viết này sẽ giúp các bạn hiểu thêm về cách hoạt động của Dapr và dễ dàng áp dụng nền tảng này vào trong kiến trúc phân tán.

Tài liệu tham khảo thêm

Trang tham khảo tài liệu của Dapr

Dự án quickstarts của Dapr

Atekco - Home for Authentic Technical Consultants