Kiến trúc của ứng dụng Web3


Kiến trúc của các ứng dụng Web 3.0 (hay “DApps”) hoàn toàn khác với các ứng dụng Web 2.0.





Lấy Medium làm ví dụ, đây là một trang blog đơn giản cho phép người dùng xuất bản nội dung của riêng họ và tương tác với nội dung từ người khác.





Một ứng dụng web 2.0 nghe có vẻ đơn giản, nhưng có rất nhiều thứ đi vào cấu trúc của Medium để biến mọi thứ trở nên khả thi:





Đầu tiên, phải có một nơi để lưu trữ dữ liệu cần thiết, chẳng hạn như người dùng, bài đăng, thẻ, bình luận, lượt thích,… Điều này đòi hỏi một cơ sở dữ liệu được cập nhật liên tục.





Thứ hai, backend code (được viết bằng ngôn ngữ như Node.js, Java hoặc Python) phải định nghĩa logic nghiệp vụ của Medium. Ví dụ: Điều gì xảy ra khi người dùng mới đăng ký, xuất bản blog mới hoặc nhận xét trên blog của người khác?





Thứ ba, frontend code (thường được viết bằng JavaScript, HTML và CSS) phải định nghĩa logic giao diện người dùng của Medium. Ví dụ: Trang web trông như thế nào và điều gì sẽ xảy ra khi người dùng tương tác với từng phần tử trên trang?





Kết hợp tất cả lại với nhau, khi bạn viết một bài đăng blog trên Medium, bạn sẽ tương tác với frontend, frontend nói chuyện với backend, backend giao tiếp với cơ sở dữ liệu. Tất cả các code này được lưu trữ trên các máy chủ tập trung và được gửi đến người dùng thông qua trình duyệt internet. 





Dưới đây là tóm tắt về cách hoạt động của hầu hết các ứng dụng Web 2.0 ngày nay.





Cách hoạt động của Web 2.0
Cách hoạt động của Web 2.0




Nhưng mọi thứ đang thay đổi.





Công nghệ blockchain (chuỗi khối) đã mở ra một hướng đi mới thú vị cho các ứng dụng Web 3.0. Trong bài viết này, chúng ta sẽ tập trung vào những gì mà Ethereum blockchain mang lại.





Điều gì làm cho ứng dụng Web 3.0 khác biệt?





Không giống như các ứng dụng Web 2.0 như Medium, ứng dụng Web 3.0 loại bỏ người đứng giữa (middleman). Không có cơ sở dữ liệu tập trung nào lưu trữ trạng thái ứng dụng và không có máy chủ web tập trung nào chứa logic backend.





Thay vào đó, bạn có thể tận dụng blockchain để xây dựng ứng dụng trên một máy trạng thái phi tập trung (decentralized state machine) được duy trì bởi các nút ẩn danh (anonymous node) trên internet.





“Máy trạng thái”, ý tôi là máy duy trì một số trạng thái chương trình nhất định và các trạng thái tương lai được phép trên máy đó. Blockchain là các máy trạng thái được khởi tạo với một số trạng thái ban đầu và có các quy tắc rất nghiêm ngặt (tức là sự đồng thuận) giúp xác định cách trạng thái đó có thể chuyển đổi.





Hơn nữa, không có thực thể nào kiểm soát máy trạng thái phi tập trung này – nó được duy trì chung bởi tất cả mọi người trong mạng.





Vậy còn máy chủ backend thì sao?





Thay vì backend của Medium được kiểm soát ra sao, trong Web 3.0, bạn có thể viết các hợp đồng thông minh xác định logic của các ứng dụng của bạn và triển khai chúng trên máy trạng thái phi tập trung. Điều này có nghĩa là mọi người muốn xây dựng một ứng dụng blockchain sẽ triển khai code của họ trên máy trạng thái được chia sẻ này.





Còn frontend? Nó gần như không thay đổi, với một số ngoại lệ mà chúng tôi sẽ đề cập sau.





Kiến ​​trúc sẽ trông như thế này: 





Kiến trúc Web 3.0
Kiến trúc Web 3.0




Nhìn cận cảnh kiến trúc web 3.0





Bây giờ, chúng ta hãy đi sâu hơn một chút vào cái gì làm cho điều này trở nên khả thi.





1) Blockchain





Ethereum blockchain thường được gọi là “máy tính thế giới”. Đó là bởi vì nó là một máy trạng thái xác định, truy cập toàn cầu được duy trì bởi mạng lưới các nút ngang hàng. Các thay đổi trạng thái trên máy trạng thái này được điều chỉnh bởi các quy tắc đồng thuận mà các nút ngang hàng trong mạng tuân theo.





Vì vậy, nói cách khác, nó được thiết kế để trở thành một máy trạng thái mà bất kỳ ai trên thế giới đều có thể truy cập và ghi vào. Do đó, máy này không thuộc sở hữu của bất kỳ thực thể nào – mà là của tất cả mọi người trong mạng.





Một điều nữa cần biết: Dữ liệu chỉ có thể được ghi vào Ethereum blockchain – bạn không bao giờ có thể cập nhật dữ liệu hiện có.





2) Hợp đồng thông minh (Smart Contracts)





Hợp đồng thông minh là một chương trình chạy trên Ethereum blockchain và định nghĩa logic đằng sau những thay đổi trạng thái xảy ra trên blockchain. Hợp đồng thông minh được viết bằng các ngôn ngữ cấp cao, chẳng hạn như Solidity hoặc Vyper.





Hợp đồng thông minh viết bằng ngôn ngữ cấp cao
Hợp đồng thông minh viết bằng ngôn ngữ cấp cao




Vì mã hợp đồng thông minh được lưu trữ trên Ethereum blockchain, nên bất kỳ ai cũng có thể kiểm tra logic ứng dụng của tất cả các hợp đồng thông minh trên mạng lưới.





3) Máy ảo Ethereum (EVM)





Tiếp theo, bạn có Máy ảo Ethereum, giúp thực thi logic được định nghĩa trong các hợp đồng thông minh và xử lý các thay đổi trạng thái xảy ra trên máy trạng thái truy cập toàn cầu này.





EVM không thể hiểu các ngôn ngữ cấp cao như Solidity và Vyper, thường được sử dụng để viết các hợp đồng thông minh. Thay vào đó, bạn phải biên dịch ngôn ngữ cấp cao thành bytecode, để EVM có thể thực thi.





4) Frontend





Cuối cùng, chúng ta có frontend. Như đã đề cập trước đây, nó xác định logic giao diện người dùng, nhưng giao diện người dùng cũng giao tiếp với logic ứng dụng được định nghĩa trong hợp đồng thông minh.





Giao tiếp giữa frontend và hợp đồng thông minh phức tạp hơn một chút so với biểu đồ trên. Hãy xem xét kỹ hơn điều này ở phần tiếp theo





Cách frontend code giao tiếp với các hợp đồng thông minh trên Ethereum?





Chúng ta muốn frontend của mình giao tiếp với các hợp đồng thông minh để chúng có thể gọi các chức năng, nhưng hãy nhớ lại rằng Ethereum là một mạng phi tập trung. Mỗi nút trong mạng Ethereum đều giữ một bản sao của tất cả các trạng thái trên máy trạng thái Ethereum, bao gồm mã và dữ liệu được liên kết với mọi hợp đồng thông minh.





Khi chúng ta muốn tương tác với dữ liệu và mã trên blockchain, chúng ta cần tương tác với một trong những nút này. Đó là vì bất kỳ nút nào cũng có thể phát đi (broadcast) yêu cầu thực hiện giao dịch trên EVM. Sau đó, một miner sẽ thực hiện giao dịch và ‘tuyên truyền’ sự thay đổi trạng thái kết quả tới phần còn lại của mạng.





Có hai cách để phát đi một giao dịch mới:





  1. Thiết lập nút của riêng bạn để chạy phần mềm Ethereum blockchain
  2. Sử dụng các nút được cung cấp bởi các dịch vụ của bên thứ ba như Infura, AlchemyQuicknode




Nếu bạn sử dụng dịch vụ của bên thứ ba, bạn sẽ không phải đối mặt với tất cả các vấn đề đau đầu khi tự mình chạy một nút. Trên hết, việc thiết lập một nút Ethereum mới trên máy chủ của riêng bạn có thể mất nhiều ngày. (Có rất nhiều dữ liệu để đồng bộ hóa – Nó thậm chí có thể chiếm nhiều băng thông và bộ nhớ hơn so với một máy tính xách tay thông thường có thể xử lý.)





Hơn nữa, chi phí lưu trữ toàn bộ Ethereum blockchain sẽ tăng lên khi DApp của bạn mở rộng và bạn cần thêm nhiều nút hơn để mở rộng cơ sở hạ tầng của mình. Đó là lý do tại sao, khi cơ sở hạ tầng của bạn trở nên phức tạp hơn, bạn sẽ cần các kỹ sư DevOps toàn thời gian. Họ sẽ giúp bạn duy trì cơ sở hạ tầng để đảm bảo thời gian hoạt động và thời gian phản hồi nhanh chóng.





Tất cả những điều này để nói rằng, tránh được những vấn đề đau đầu này là lý do mà nhiều DApp chọn sử dụng các dịch vụ như Infura hoặc Alchemy để quản lý cơ sở hạ tầng nút cho họ. Tất nhiên, có một sự đánh đổi vì điều này tạo ra một điểm nghẽn tập trung (centralized chokepoint), nhưng chúng ta hãy nói về cái hang thỏ đó vào một ngày khác. 😉





Tiếp tục, hãy nói về các nhà cung cấp. Các nút mà bạn kết nối khi cần tương tác với blockchain (dù bạn tự thiết lập chúng hay sử dụng các nút hiện có từ các dịch vụ của bên thứ ba) thường được gọi là “nhà cung cấp”.





Nhà cung cấp trên ứng dụng web 3.0
Nhà cung cấp trên ứng dụng web 3.0




Mọi Ethereum client (tức là nhà cung cấp) đều triển khai đặc tả JSON-RPC. Điều này đảm bảo rằng có một bộ phương pháp thống nhất khi các ứng dụng frontend muốn tương tác với blockchain. Nếu bạn chưa biết về JSON-RPC, thì đó là một giao thức gọi thủ tục từ xa (RPC) không trạng thái, nhẹ, giúp xác định một số cấu trúc dữ liệu và quy tắc xử lý. Đây là giao thức bất khả tri (transport-adnostic), vì vậy, các khái niệm có thể được sử dụng trong cùng một quy trình, qua socket, qua HTTP hoặc trong nhiều môi trường truyền thông báo khác nhau. Nó sử dụng JSON (RFC 4627) làm định dạng dữ liệu.





Khi bạn kết nối với blockchain thông qua một nhà cung cấp, bạn có thể đọc trạng thái được lưu trữ trên blockchain. Nhưng nếu bạn muốn viết lên trạng thái, vẫn còn một việc nữa bạn cần làm trước khi có thể gửi giao dịch tới blockchain – “ký” giao dịch bằng khóa cá nhân của bạn.





Ví dụ: hãy tưởng tượng chúng ta có DApp cho phép người dùng đọc hoặc xuất bản các bài đăng trên blog lên blockchain. Bạn có thể có một nút trên giao diện người dùng cho phép bất kỳ ai truy vấn các bài đăng trên blog được viết bởi một người dùng cụ thể. (Hãy nhớ rằng việc đọc từ blockchain không yêu cầu người dùng phải ký một giao dịch.)





Tuy nhiên, khi người dùng muốn xuất bản một bài đăng mới lên chuỗi, DApp sẽ yêu cầu người dùng “ký” vào giao dịch bằng khóa riêng của họ – chỉ sau đó DApp mới chuyển giao giao dịch đó sang blockchain. Nếu không, các nút sẽ không chấp nhận giao dịch.





Việc “ký” giao dịch này là nơi mà Metamask xuất hiện.





Ký giao dịch bằng Metamask
Ký giao dịch bằng Metamask




Metamask là một công cụ giúp các ứng dụng dễ dàng xử lý việc quản lý khóa và ký kết giao dịch. Nó đơn giản thế này: Metamask lưu trữ các khóa riêng của người dùng trong trình duyệt và bất cứ khi nào giao diện người dùng cần người dùng ký giao dịch, nó sẽ gọi đến Metamask.





Metamask cũng cung cấp kết nối với blockchain (như một “nhà cung cấp”) bởi nó đã có kết nối với các nút do Infura cung cấp vì nó cần nó ký giao dịch. Theo cách này, Metamask vừa là nhà cung cấp vừa là người ký. 🤯





Lưu trữ trên Blockchain





Tất nhiên, kiến ​​trúc này có ý nghĩa nếu bạn đang xây dựng một ứng dụng nơi tất cả các hợp đồng thông minh và dữ liệu hoàn toàn sống trên Ethereum blockchain. Nhưng bất kỳ ai đã xây dựng ứng dụng trên Ethereum đều biết rằng việc lưu trữ mọi thứ trên blockchain trở nên rất tốn kém.





Hãy nhớ rằng, với Ethereum, người dùng trả tiền mỗi khi họ thêm dữ liệu mới vào blockchain. Đó là bởi vì việc thêm một trạng thái vào máy trạng thái phi tập trung sẽ làm tăng chi phí cho các nút đang duy trì máy trạng thái đó.





Yêu cầu người dùng trả thêm tiền để sử dụng DApp của bạn mỗi khi giao dịch của họ yêu cầu thêm trạng thái mới không phải là trải nghiệm người dùng tốt nhất. Một cách để chống lại điều này là sử dụng giải pháp lưu trữ ngoài chuỗi phi tập trung, như IPFS hoặc Swarm.





IPFS là một hệ thống tệp phân tán để lưu trữ và truy cập dữ liệu. Vì vậy, thay vì lưu trữ dữ liệu trong cơ sở dữ liệu tập trung, hệ thống IPFS phân phối và lưu trữ dữ liệu trong một mạng ngang hàng. Điều này giúp bạn dễ dàng lấy ra khi cần.





IPFS cũng có một lớp khuyến khích (incentive layer) được gọi là “Filecoin”. Lớp này khuyến khích các nút trên khắp thế giới lưu trữ và truy xuất dữ liệu này. Bạn có thể sử dụng nhà cung cấp như Infura (cung cấp cho bạn nút IPFS) hoặc Pinata (cung cấp dịch vụ dễ sử dụng, nơi bạn có thể “ghim” các tệp của mình vào IPFS và lấy mã băm IPFS và lưu trữ trên blockchain) .





Swarm tương tự ở chỗ là mạng lưu trữ phi tập trung, nhưng có một điểm khác biệt đáng chú ý. Trong khi Filecoin là một hệ thống riêng biệt, hệ thống khuyến khích của Swarm được tích hợp sẵn và thực thi thông qua các hợp đồng thông minh trên Ethereum blockchain để lưu trữ và truy xuất dữ liệu.





Bây giờ, với IPFS hoặc Swarm, kiến ​​trúc ứng dụng của chúng ta trông giống như sau:





IPFS hoặc Swarm trên Kiến trúc ứng dụng
IPFS hoặc Swarm trên Kiến trúc ứng dụng




Những độc giả tinh ý cũng có thể nhận thấy trong sơ đồ bên dưới rằng frontend code không được lưu trữ trên blockchain. Chúng ta có thể lưu trữ mã này trên AWS như chúng ta thường làm trong Web 2.0, nhưng điều đó tạo ra một điểm giới hạn tập trung cho DApp của bạn. Điều gì sẽ xảy ra nếu AWS gặp sự cố? Điều gì sẽ xảy ra nếu nó kiểm duyệt ứng dụng của bạn?





Đó là lý do tại sao, nếu bạn muốn xây dựng một ứng dụng phi tập trung thực sự, bạn có thể chọn lưu trữ giao diện người dùng của mình trên một giải pháp lưu trữ phi tập trung, như IPFS hoặc Swarm.





Vì vậy, bây giờ kiến trúc ứng dụng của bạn trông giống như sau:





Lưu trữ Frontend trên IPFS hoặc Swarm
Lưu trữ Frontend trên IPFS hoặc Swarm




Truy vấn blockchain





Tới lúc này, chúng ta đã nói về cách ghi vào blockchain bằng cách ký các giao dịch và sau đó gửi chúng đến blockchain. Nhưng còn việc đọc dữ liệu từ các hợp đồng thông minh trên blockchain thì sao? Có hai cách chính để làm điều này:





1) Sự kiện hợp đồng thông minh (Smart Contract Events)





Bạn có thể sử dụng thư viện Web3.js để truy vấn và nghe các sự kiện hợp đồng thông minh. Bạn có thể nghe các sự kiện cụ thể và chỉ định một lệnh gọi lại mỗi khi sự kiện được kích hoạt. Ví dụ: nếu bạn có một hợp đồng thông minh gửi một luồng thanh toán liên tục từ người A đến người B mỗi khối, thì bạn có thể tạo ra một sự kiện mỗi khi một khoản thanh toán mới được thực hiện cho người B. Frontend code của bạn có thể lắng nghe các sự kiện đang được kích hoạt bằng hợp đồng thông minh và thực hiện các hành động cụ thể dựa trên hợp đồng đó.





2) Biểu đồ (Graph)





Cách tiếp cận trên mặc dù ổn, nhưng nó có một số hạn chế. Ví dụ: điều gì sẽ xảy ra nếu bạn triển khai một hợp đồng thông minh và sau đó nhận ra rằng bạn cần một sự kiện được phát ra mà ban đầu bạn không bao gồm? Rất tiếc, bạn phải triển khai lại hợp đồng thông minh mới với sự kiện và dữ liệu đó. Hơn nữa, việc sử dụng các lệnh gọi lại để xử lý các logic giao diện người dùng khác nhau trở nên rất phức tạp.





Đây là lúc “Biểu đồ” xuất hiện.





Biểu đồ là một giải pháp lập chỉ mục ngoài chuỗi giúp truy vấn dữ liệu trên Ethereum blockchain dễ dàng hơn. Biểu đồ cho phép bạn xác định các hợp đồng thông minh nào cần lập chỉ mục, các sự kiện và lệnh gọi hàm nào cần nghe và cách chuyển các sự kiện tiếp theo thành các thực thể mà logic frontend của bạn (hoặc bất kỳ thứ gì đang sử dụng API) có thể sử dụng. Nó sử dụng GraphQL làm ngôn ngữ truy vấn, mà nhiều frontend engineer yêu thích vì cách nó biểu đạt so với các API REST truyền thống.





Bằng cách lập chỉ mục dữ liệu blockchain, Biểu đồ cho phép chúng ta truy vấn dữ liệu trên chuỗi trong logic ứng dụng với độ trễ thấp.





Bây giờ, kiến ​​trúc DApp của bạn trông giống như sau:





The Graph
The Graph




Chúng ta gần xong rồi, nhưng vẫn còn một chủ đề chính: mở rộng quy mô.





Mở rộng DApp





Như bạn có thể đã nghe qua, Ethereum không mở rộng – ít nhất là chưa.





Giá gas trung bình của Ethereum
Gas Price trung bình của Ethereum




Phí giao dịch trung bình
Phí giao dịch trung bình




Kích thước khối trung bình
Kích thước khối trung bình




Rõ ràng, chúng ta có một vấn đề ở đây. Việc xây dựng DApp trên Ethereum với phí gas cao và các khối đầy đủ dẫn đến trải nghiệm người dùng rất tệ. Rất may, có một số giải pháp đang được phát triển.





Một giải pháp chia tỷ lệ phổ biến là Polygon, một giải pháp chia mở rộng L2. Thay vì thực hiện các giao dịch trên blockchain chính, Polygon có các “sidechains” xử lý và thực hiện các giao dịch. Một sidechain là một chuỗi khối thứ cấp giao tiếp với chuỗi chính. Sidechain thường xuyên gửi tổng hợp các khối mới nhất của nó trở lại chuỗi chính.





Sidechain và Blockchain
Sidechain và Blockchain




Ý tưởng là: Các giải pháp L2 thực hiện giao dịch (tức là phần chậm) ngoài chuỗi, với dữ liệu giao dịch được lưu trên chuỗi. Điều này cho phép chúng ta mở rộng quy mô chuỗi khối vì chúng ta không phải thực hiện mọi giao dịch trên chuỗi. Điều này cũng làm cho các giao dịch nhanh hơn và rẻ hơn – và chúng vẫn có thể giao tiếp với chuỗi khối Ethereum chính khi cần thiết.





Giải pháp L2
Giải pháp L2




Gom tất cả lại





Nếu tất cả những điều này khiến bạn quay cuồng, thì không chỉ mỗi bạn đâu. Việc kết hợp tất cả các công cụ này lại với nhau rất phức tạp và có thể dẫn đến trải nghiệm khó khăn cho nhà phát triển. Nhưng đừng lo – chúng ta đang bắt đầu thấy các framework mới thực sự cải thiện trải nghiệm cho các nhà phát triển.





Ví dụ: Hardhat là một framework dành cho nhà phát triển giúp các nhà phát triển Ethereum xây dựng, triển khai và thử nghiệm các hợp đồng thông minh của họ dễ dàng hơn. Hardhat cung cấp “Mạng Hardhat”, mà các nhà phát triển có thể sử dụng để triển khai các hợp đồng thông minh của họ trên một mạng cục bộ – mà không cần phải xử lý các môi trường trực tiếp. Hơn thế nữa, nó cung cấp một hệ sinh thái plugin tuyệt vời giúp cuộc sống của các nhà phát triển dễ dàng hơn nhiều. Hardhat cũng cung cấp chức năng console.log (), tương tự như javascript, cho mục đích gỡ lỗi.





Tất nhiên, đây chỉ là khởi đầu. Tôi hy vọng rằng chúng ta tiếp tục thấy công cụ dành cho nhà phát triển tốt hơn trong tương lai.





Nguồn: Preethikasireddy


Tags:web 3.0