#149 - Kiến trúc JVM
Những bài viết hay
Máy ảo Java JVM là một máy ảo cho phép chạy các chương trình Java cũng như các chương trình khác được viết bằng các ngôn ngữ khác mà được biên dịch sang mã byte Java. Java là một ngôn ngữ lập trình hướng đối tượng rất phổ biến, vậy nên có lẽ JVM không còn quá xa lạ với các lập trình viên. Tuy nhiên, có lẽ không nhiều người hiểu rõ về kiến trúc của JVM. Qua bài viết này, tác giả giúp chúng ta hiểu rõ hơn về thiết kế và cấu trúc của JVM.
Kiến trúc JVM được chia thành ba phần chính: Class Loader Subsystems, Runtime Data Area, Execution Engine.
Class Loader Subsystem tải các class vào JVM. Một class được tải trong hai trường hợp, khi một mã bytecode mới được thực thi và khi một mã bytecodes tạo tham chiếu tĩnh đến một class. Có 3 loại class loader: Boostrap Class Loader, Extensions Class Loader, System/Application Class Loader. Java Class loader có 3 nguyên tắc:
Delegation principle: Nguyên tắc này chuyển tiếp một yêu cầu tải class tới trình tải của parent class. Nó chỉ tải class nếu parent class không tìm thấy hoặc tải một class.
Visibility principle: Nguyên tắc này chỉ cung cấp khả năng hiển thị cho trình nạp của class con để xem tất cả các class được tải bởi một parent class, chứ không phải ngược lại.
Uniqueness principle: Mỗi class sẽ chỉ được tải một lần
The Runtime Area được chia thành Method Area, Heap Area, Stack Area, PC Registers, Native Method Stacks:
Method Area: chứa đựng toàn bộ thông tin về class như parent name, class name, methods và các biến …Ngoài ra, các phần tử được sử dụng trong class, khởi tạo các Objects hoặc Interfaces cũng được lưu tại đây. Mỗi JVM sẽ có một Method Area được chia sẻ chung giữa các Thread.
Java Heap: JVM lưu tất cả đối tượng được tạo bởi toán tử “new”, vào vùng nhớ Heap tại thời điểm chạy. Heap Area được chia ra thành Young Generation, Old Generation và Permanent Generation.
Java Stack: Các phương thức và tham chiếu tới đối tượng địa phương được lưu trữ trong Stack. Mỗi Thread quản lý một stack. Khi phương thức được gọi, nó được đưa vào đỉnh của Stack. Stack lưu trữ trạng thái của phương thức bao gồm: dòng code thực thi, tham chiếu tới đối tượng địa phương. Khi phương thức chạy xong, vùng nhớ (dòng code thực thi, tham chiếu tới đối tượng địa phương) được đẩy ra khỏi stack và tự động giải phóng.
PC Register: lưu trữ địa chỉ của lệnh thực thi hiện tại của một thread. Mỗi thread có một PC Register.
Native Method Stack: lưu trữ các method được viết bởi ngôn ngữ khác Java.
The Execution Engine: thực thi từng dòng code trong các file bytecode có đuôi .class. Execution Engine được phân loại thành: interpreter, Just In Time compiler và Garbage Collector.
A Seven-Step Guide to API-First Integration — www.infoq.com
Trong các enterprise systems một API có thể được sử dụng bởi nhiều applications hoặc third-party khác nhau, do đó việc thay đổi API dưới dạng "breaking change" là điều cấm kỵ.
Có hai hướng tiếp cận phổ biến khi xây dựng API: integration-first và API-first
Integration-first:
Dựa vào yêu cầu dự án, back-end xây dựng business services và APIs
Front-end sử dụng các APIs được cung cấp bởi back-end team để phát triển web application
Front-end sau đó nhận ra APIs chưa đáp ứng hết nhu cầu cho nên nhờ back-end thay đổi
Back-end tiếp nhận yêu cầu thay đổi (change request - CR) và tiến hành sửa đổi API
Quá trình nãy tiếp tục diễn ra cho tới khi cả Front-end và Back-end đồng ý API contract cho từng tính năng
API-first
Dựa vào yêu cầu dự án, Front-end và Back-end ngồi lại để thiết kế APIs
Sau khi thống nhất APIs, back-end và front-end bắt tay vào xây dựng hệ thống song song (back end có thể dựng mock service để hỗ trợ front-end hoặc front-end có thể tự mock API dựa vào APIs contract đã thống nhất bên trên)
Khi backend đã hoàn thành, front-end có thể sử dụng real implementation
Ở một góc độ nào đó, APIs được xem như hợp đồng kinh doanh. Khi chúng ta muốn thực hiện một mối làm ăn quan trọng, chúng ta không bắt đầu hợp tác kinh doanh cho đến khi hợp đồng đã thoả mãn các bên. Tương tự như vậy, trong các trường hợp tích hợp các hệ thống với nhau, trước tiên ta cần hoàn thành thiết kế APIs để có sự thống nhất giữa các bên để tránh các thay đổi không đáng có.
Ở hướng tiếp cận API-first, chúng ta sẽ thực hiện 7 bước,
Đầu tiên xác định yêu cầu dự án: bằng cách ngồi lại với các bên liên quan để xác định các yêu cầu, xác định mục tiêu của dự án
Tìm hiểu hệ thống hiện tại: hệ thống hiện tại gồm những services nào, dữ liệu được xử lý như thế nào...
Xác định điểm tích hợp khả dĩ của hệ thống hiện tại: sau khi nắm bắt được hệ thống hiện tại, ta có thể xác định services nào cần tương tác
Xác định khả năng tích hợp cần thiết: sau khi đã hiểu được yêu cầu và mục tiêu cũng như nắm bắt được hệ thống hiện tại, chúng ta có thể quyết định các khả năng tích hợp cần thiết như API và service hosting, Routing, Protocol, kết hợp các services khác nhau để có được kết quả cuối cùng ...
Thiết kế API (edge API) mà front-end/third-party sẽ tương tác với back-end
Xây dựng utility API và domain APIs: sau khi đã thống nhất edge API, back-end team bắt đầu xây dựng utility APIs và domain APIs để trả về dữ cho edge API
Xây dựng front-end và back-end: sau khi tất cả các công việc trên đã hoàn thành, back-end và front-end có thể tiến hành xây dựng hệ thống song song mà ít hoặc không phụ thuộc lẫn nhau.
6 Tips and Best Practices for a Scalable React Project | by Nathan Sebhastian | Bits and Pieces — blog.bitsrc.io
Xây dựng React application có khả năng mở rộng cao là điều không dễ dàng, bài viết sau tác giả chia sẻ một số kinh nghiệm thực tiễn để giúp bạn đạt được điều này:
Sử dụng local state hay global state? Thay vì sử dụng redux để lưu tất cả các trạng thái của component, tốt hơn bạn nên sử dụng local state (component state) cho một số tác vụ cơ bản ví dụ như isLoading, isDisplay<Something> ...
Viết test ngay từ đầu sẽ mang lại nhiều lợi ích về sau
Tận dụng các công cụ để giúp bạn scale dễ dàng, một số tools hữu ích như Prettier, EsLint, Bit, formik...
Tổ chức files rõ ràng
Xây dựng component library để sử dụng lại cho những project khác
Tách logic code ra khỏi component bằng cách sử dụng hooks
Chi tiết về các tips trên, mời bạn đọc thêm ở nội dung gốc tại đây.
Góc Database
Các database truyền thống trước giờ thường được thiết kế theo hướng sử dụng đĩa cứng (hard-disk) như là cơ chế lưu trữ chính, kèm theo đó sẽ là bộ phận buffer pool trên Ram dùng để cache lại các dữ liệu thường truy cập để hạn chế phải đọc xuống đĩa do tốc độ truy xuất đĩa sẽ chậm gấp nhiều lần việc đọc trên memory.
Trong một số tình huống tải hệ thống tăng quá cao, một số hệ thống còn bổ sung thêm một tầng distributed cache để giảm tải cho database.
Tuy nhiên, trong quá trình tìm kiếm những giải pháp để nâng cao hiệu suất hơn nữa, một nhóm tác giả đã thử đặt lại câu hỏi là nếu chúng ta biến RAM thành nơi lưu trữ chính, còn đĩa cứng trở thành nơi lưu trữ dữ liệu phụ thì có tốt hơn ko? Câu hỏi này đã dẫn đến đề xuất cho một kiến trúc mới gọi là anti-caching. Đối với kiến trúc này, dữ liệu sẽ được lưu chính phần lớn ở trên RAM, còn dữ liệu ít sử dụng (cold data) sẽ được di chuyển dần sang đĩa. Các tác giả đã xây dựng một bản prototype của hệ thống anti-caching này và thực hiện một số thử nghiệm để so sánh với các hệ thống lưu trữ chính trên đĩa. Kết quả thử nghiệm cho thấy kiến trúc này có thể mang đến hiệu suất cao gấp nhiều lần cho các hệ thống truyền thống.
Mời các bạn đọc bài báo để hiểu thêm về kiến trúc này: Link bài báo
Code & Tools
This Week Sponsor
Established in 2012, Chotot.com is the leading online classified website in Vietnam with more than 1,2 billion monthly page views, 10 million monthly users, 3,6 million transactions in 2019. With the motto “Muốn Là Có” (“A Way to Your Wants”), Chotot.com provides an effective online marketplace for Vietnamese to buy and sell various types of products easily. For more information, please visit www.chotot.com.
Góc Tuyển Dụng
Cho Tot creates products using a variety of open source and cloud native technologies, to name some: Kubernetes, Kafka, Elastic Search, PostgreSQL, MongoDB, TimescaleDB. We utilize Google Cloud Platform services such as Google Kubernetes, AI Platform, Cloud Composer, Data Catalog, BigQuery, Google Analytics for our infrastructure needs while running our heavy workloads on our own on-premises infrastructure. Visit careers.chotot.com to learn more about our vacancies and company culture.
Quotes
One of the best programming skills you can have is knowing when to walk away for awhile.
- Oscar Godson