Toàn tập Đồ án 2: Xây dựng hệ thống Microservices với Spring Boot & NextJS

Hướng dẫn xây dựng ứng dụng full-stack với Spring Boot và NextJS. Tìm hiểu cách tích hợp backend và frontend hiệu quả cho dự án thực tế.

2025

87
2
0

Phí lưu trữ

30 Point

Tóm tắt

I. Giới thiệu về Đồ án Spring Boot NextJS

Đồ án Spring Boot NextJS là một dự án toàn diện nhằm tìm hiểu và xây dựng ứng dụng full-stack hiện đại. Đây là một kết hợp hoàn hảo giữa backend Spring Bootfrontend NextJS, hai công nghệ hàng đầu trong phát triển ứng dụng web. Đồ án này được thực hiện tại Khoa Công nghệ Phần mềm, Trường Đại học Công nghệ Thông tin, Đại học Quốc gia Thành phố Hồ Chí Minh. Mục tiêu chính của đồ án là giúp sinh viên hiểu sâu về kiến trúc hệ thống phân tán, các nguyên lý thiết kế ứng dụng full-stack và cách tích hợp các công nghệ hiện đại. Thông qua đồ án này, các sinh viên sẽ nắm vững những kỹ năng cần thiết để phát triển các ứng dụng web có khả năng mở rộng cao và hiệu suất tối ưu.

1.1. Mục tiêu của dự án

Mục tiêu chính của đồ án Spring Boot NextJS là cung cấp một nền tảng học tập toàn diện về phát triển ứng dụng full-stack hiện đại. Dự án tập trung vào việc kết hợp Spring Boot cho backend và NextJS cho frontend, giúp sinh viên hiểu rõ quy trình phát triển từ thiết kế hệ thống đến triển khai. Các sinh viên sẽ học cách xây dựng API RESTful, quản lý cơ sở dữ liệu, xử lý xác thực người dùng và tối ưu hóa hiệu suất ứng dụng.

1.2. Tầm quan trọng của công nghệ

Spring Boot là framework Java phổ biến nhất để xây dựng ứng dụng backend, trong khi NextJS là framework React mạnh mẽ cho phía frontend. Sự kết hợp này tạo ra một stack công nghệ hoàn chỉnh, giúp phát triển ứng dụng nhanh chóng và hiệu quả. Những kiến thức này rất cần thiết trong ngành công nghiệp phần mềm hiện đại.

II. Kiến trúc hệ thống và thiết kế

Kiến trúc của ứng dụng full-stack Spring Boot NextJS dựa trên các nguyên lý thiết kế hệ thống hiện đại bao gồm load balancing, caching, và microservices. Hệ thống được chia thành các tầng rõ ràng: tầng presentation (NextJS), tầng business logic (Spring Boot), và tầng data access. Đối với các hệ thống nhỏ, kiến trúc Monolith hoặc N-tier là đủ, nhưng khi hệ thống phát triển, cần áp dụng microservices architecture. Việc thiết kế hệ thống phải đảm bảo các yêu cầu như độ tin cậy, hiệu suất cao, khả năng mở rộng và dễ bảo trì. Hệ thống cần có khả năng xử lý hàng triệu yêu cầu đồng thời thông qua load balancer và các kỹ thuật tối ưu hóa khác.

2.1. Tầng Backend Spring Boot

Spring Boot cung cấp một framework hoàn chỉnh để xây dựng backend mạnh mẽ. Nó bao gồm các thành phần như Spring Data JPA cho quản lý cơ sở dữ liệu, Spring Security cho xác thực và phân quyền, Spring Cache cho caching, và RabbitMQ cho xử lý message queue. Spring Boot cũng hỗ trợ triển khai dễ dàng thông qua DockerKubernetes. Hệ thống có thể sử dụng các công nghệ như MyBatis-Plus, Elasticsearch để tối ưu hóa truy vấn và tìm kiếm.

2.2. Tầng Frontend NextJS

NextJS là framework React mạnh mẽ cho phía client, cung cấp server-side rendering (SSR) và static generation (SSG) để cải thiện hiệu suất và SEO. NextJS cho phép xây dựng giao diện người dùng đẹp mắt, tương tác cao và có trải nghiệm người dùng tuyệt vời. Framework này hỗ trợ định tuyến, API routes, và tối ưu hóa hình ảnh tự động, giúp ứng dụng tải nhanh hơn.

III. Công nghệ cấp cao và triển khai

Đồ án Spring Boot NextJS áp dụng các công nghệ cấp cao để xây dựng hệ thống có khả năng mở rộng cao. Các khái niệm như Service Discovery, API Gateway, Distributed Transactions, và Consensus algorithms (Raft) được sử dụng để quản lý hệ thống phân tán. Load Balancer giúp phân phối lưu lượng truy cập, trong khi Caching cải thiện hiệu suất bằng cách giảm tải cơ sở dữ liệu. Triển khai được thực hiện thông qua DockerKubernetes để đảm bảo tính linh hoạt và khả năng mở rộng. ELK Stack (Elasticsearch, Logstash, Kibana) được sử dụng cho giám sát log, trong khi PrometheusSpring Boot Admin giúp theo dõi hiệu suất ứng dụng. Spring Cloud cung cấp các công cụ như Eureka cho service discovery và Feign cho giao tiếp giữa các service.

3.1. Microservices và Service Discovery

Kiến trúc Microservices chia ứng dụng thành các service nhỏ, độc lập, mỗi service quản lý một chức năng cụ thể. Service Discovery như Eureka cho phép các service tự động phát hiện nhau mà không cần cấu hình tĩnh. API Gateway hoạt động như một điểm vào duy nhất cho tất cả các request từ client, giúp quản lý định tuyến, xác thực và cân bằng tải. Cách tiếp cận này cải thiện tính linh hoạt, khả năng mở rộng và khả năng bảo trì của hệ thống.

3.2. Caching và Load Balancing

Caching là kỹ thuật quan trọng để cải thiện hiệu suất ứng dụng bằng cách lưu trữ dữ liệu thường xuyên sử dụng. Spring Cache hỗ trợ caching ở tầng ứng dụng, trong khi Reverse Proxy Cache caching ở tầng network. Load Balancer phân phối lưu lượng truy cập giữa nhiều instance, tăng availability và hiệu suất. Các pattern như LRU cache eviction được sử dụng để quản lý bộ nhớ cache hiệu quả.

IV. Ứng dụng thực tế và kết quả

Đồ án Spring Boot NextJS kết hợp tất cả các kiến thức lý thuyết để xây dựng một ứng dụng full-stack hoàn chỉnh. Ứng dụng này áp dụng các best practices trong thiết kế hệ thống, bao gồm fault tolerance, scalability, và maintainability. Qua đồ án này, sinh viên không chỉ nắm vững các framework như Spring BootNextJS, mà còn hiểu sâu về các nguyên lý kiến trúc cơ bản. Kỹ năng phát triển full-stack là một yêu cầu quan trọng trong ngành công nghiệp phần mềm hiện đại. Sinh viên sẽ có khả năng thiết kế, phát triển và triển khai các ứng dụng web quy mô lớn, có khả năng mở rộng cao và hiệu suất tối ưu. Những kiến thức này sẽ giúp các sinh viên chuẩn bị tốt cho sự nghiệp phát triển phần mềm chuyên nghiệp.

4.1. Công nghệ sử dụng trong dự án

Dự án sử dụng các công nghệ hiện đại bao gồm Spring Boot, NextJS, Docker, Kubernetes, RabbitMQ, Elasticsearch, PostgreSQL, và Redis. OAuth2JWT được sử dụng cho xác thực an toàn. Spring Security cung cấp các tính năng bảo mật toàn diện. PrometheusGrafana giúp theo dõi hiệu suất, trong khi ELK Stack quản lý log tập trung. Những công nghệ này tạo thành một stack công nghệ hiện đại, đáp ứng mọi yêu cầu của ứng dụng quy mô lớn.

4.2. Kết quả và ý nghĩa

Hoàn thành đồ án Spring Boot NextJS cho phép sinh viên hiểu rõ về quy trình phát triển ứng dụng full-stack từ đầu đến cuối. Sinh viên sẽ có kỹ năng thực tiễn, tự tin xây dựng các ứng dụng web phức tạp. Đồ án cũng giúp sinh viên hiểu về các thách thức trong distributed systems và cách giải quyết chúng, chuẩn bị tốt cho các dự án thực tế trong công việc.

28/12/2025

Trích đoạn nội dung tài liệu

Chương 1: Tổng quan về thiết kế hệ thống 1. Thiết kế trong các hệ thống nhỏ và trong các hệ thống lớn Thiết kế hệ thống sử dụng các khái niệm trong lĩnh vực mạng máy tính (Computer Networking), tính toán song song (Parallerl Computing) và hệ thống phân tán (Distributed systems) để xây dựng những hệ thống có khả năng mở rộng và hiệu suất cao. Thiết kế hệ thống có mục đích xây dựng những hệ thống có độ tin cậy (reliable), hiệu quả, và dễ bảo trì cùng với những đặc điểm khác. Hệ thống hiệu quả là hệ thống đáp ứng tất cả các nhu cầu của người dùng và yêu cầu kinh doanh.

Hệ thống đáng tin cậy là hệ thống có khả năng xử lý lỗi, sự cố và sai sót. Hệ thống dễ bảo trì là hệ thống linh hoạt và dễ dàng mở rộng hoặc thu nhỏ. Khả năng thêm tính năng mới cũng nằm trong phạm vi của tính dễ bảo trì. Với các hệ thống nhỏ và tương đối đơn giản, thiết kế và kiến trúc của hệ thống không phải là một vấn đề quá phức tạp, do bản thân các hệ thống này tương đối dễ tổ chức, dễ vận hành, dễ bảo trì và nhờ đó nên không có nhiều thành phần phức tạp.

Điển hình về các hệ thống ở quy mô này là các hệ thống quản lý kho, hệ thống quản lý hồ sơ, quản lý sản phẩm của riêng một công ty, tổ chức; hệ thống quản lý thư viện địa phương. Với các hệ thống này, có rất nhiều mô hình phát triển phần mềm đủ đáp ứng yêu cầu: kiến trúc Monolith, kiến trúc N-tier, mô hình 3 lớp, clean architecture, Hexagonal architecture, Các mô hình kiến trúc này đều dựa trên một cơ sở để thực hiện là kiến trúc Client-server. Tuy nhiên, với các hệ thống có quy mô lớn hơn, mô hình nghiệp vụ phức tạp hơn, nhiều người sử dụng hơn, các mô hình kiến trúc kể trên không đủ khả năng để cung cấp dịch vụ kịp thời, chính xác và ổn định. Điều này do giới hạn phần cứng của một server không thể nào đáp ứng được một nghìn, mười nghìn, thậm chí là cả triệu yêu cầu tại một thời điểm.

Do đó các hệ thống lớn cần phải áp dụng những kiến trúc phức tạp, đặc biệt hơn để đáp ứng nhu cầu chịu tải lớn, đảm bảo độ ổn định, độ chính xác và có khả năng chịu lỗi. Một hệ thống có các nhu cầu trên thông thường sẽ sử dụng nhiều server, mỗi server song song chạy chương trình và nhiều database để đáp ứng nhu cầu lưu trữ. Các nguyên lý thiết kế hệ thống 1. Scalability Scalability là khả năng mở rộng của hệ thống quy trình hay mạng lưới với nhu cầu gia tăng về số lượng công việc tăng theo thời gian của mô hình kinh doanh.

Mô hình kinh doanh có thể mở rộng quy mô vì nhiều lý do như: Gia tăng khối lượng dữ liệu lưu trữ. Gia tăng về số lượng yêu cầu và khối lượng công việc. Có 2 cách để scale một hệ thống là vertical scaling và horizontal scaling. Vertical scaling là tăng trưởng hệ thống bằng cách nâng cấp các thành phần vật lý của server như nâng cấp CPU, nâng cấp RAM, nâng ổ cứng,.

Ngược lại, horizontal scaling là cách thêm nhiều server hơn vào hệ thống, dùng các server phối hợp nhau để xử lý nguồn tải lớn bằng cách chia đều tải (cân bằng tải) cho mỗi server. Thực tế sẽ khó áp dụng vertical scaling để scale một hệ thống do hạn chế về phần cứng và chi phí cho việc vertical scaling thường đắt đỏ. Song, horizontal scaling cũng phức tạp hóa mô hình kiến trúc của hệ thống do phải điều phối hoạt động của nhiều server riêng biệt và vận hành như một bộ máy duy nhất. Kiến trúc này được biết đến với tên gọi Hệ thống phân tán (Distributed system) và là cơ sở cho ra đời một họ các mô hình kiến trúc sau này như Distributed monolith, Microservices cùng với đó là rất nhiều vấn đề cực kỳ phức tạp và khó giải quyết khác.

Khi nhắc đến scalability, hầu hết ta luôn muốn nói đến khả năng horizontal scaling của hệ thống. Availability Tính khả dụng là một chỉ số đo lường phần trăm thời gian mà một dịch vụ hoặc một hệ thống nào đó có thể truy cập được bởi khách hàng và hoạt động trong điều kiện bình thường. Nó đo lường mức độ hoạt động và xử lý của hệ thống ở trạng thái bình thường trong suốt một khoảng thời gian nhất định. Chẳng hạn, nếu một dịch vụ có khả dụng 100%, điều đó có nghĩa rằng dịch vụ đó luôn sẵn sàng hoạt động, xử lý và phản hồi các yêu cầu.

Trong toán học, tính khả dụng A được biểu thức dưới dạng tỉ lệ. Tỉ lệ A càng cao càng tốt. Chúng ta cũng có thể biểu thức điều này bằng một công thức: A = MTBF/(MTBF + MTTR) [Mean Time To Repair, Mean Time Between Failures] Chúng ta đo lường mức độ khả dụng (availability) bằng cách sử dụng số lượng "9". Cụ thể, số lượng "9" thể hiện mức độ chính xác của khả dụng và cho biết bao nhiêu thời gian ngừng hoạt động được phép trong khoảng thời gian nhất định.

Dưới đây là một bảng thể hiện mức độ khả dụng tương ứng với số lượng "9" và thời gian ngừng hoạt động được phép: 1. Consistency Tính nhất quán (Consistency) là một thuộc tính quan trọng trong hệ thống phân tán, đảm bảo rằng tất cả các máy chủ (server) trong cụm (cluster) luôn duy trì cùng một trạng thái và dữ liệu vào một thời điểm cố định, bất kể client nào đã thực hiện cập nhật dữ liệu. Tính nhất quán cao có nghĩa là hệ thống phân tán sẽ đồng thuận đến một trạng thái duy nhất và cho phép client luôn đọc được dữ liệu mới nhất. Tính nhất quán của hệ thống phụ thuộc vào việc nó tuân theo định lý CAP – định lý nêu rằng một hệ thống phân tán (distributed system) không thể thỏa mãn cả ba yếu tố CAP: Consistency: Tính nhất quán, các máy chủ trong một hệ thống phải có dữ liệu đồng nhất.

Availability: Khả năng sẵn sàng, hệ thống vẫn hoạt động được khi một số máy chủ bị chết hoặc không sẵn sàng. Partition Tolerance: Khả năng chịu đựng phân vùng, hệ thống vẫn hoạt động cho dù kết nối giữa các máy chủ trong hệ thống bị đứt. Nói cách khác, khi mạng bị phân vùng (network partition), thì một hệ thống chỉ có thể đảm bảo được một trong hai tính chất - Consistency hoặc Availability. Khi không có phân vùng mạng, thì hệ thống có thể đảm bảo cả hai tính chất.

Có nhiều mô hình về yêu cầu tính nhất quán của một hệ thống: Strong consistency: là mô hình nhất quán mạnh nhất, cam kết rằng mọi thao tác được thực hiện lên dữ liệu đều được phản ảnh ngay lập tức bởi tất cả server trong cluster và do đó client luôn quan sát được dữ liệu mới nhất. Mô hình này hy sinh availability để đảm bảo sự nhất quán giữa các server. Weak consistency (hoặc Eventual consistency): các thao tác sau khi thực hiện có thể chưa được phản ánh bởi các server trong cluster, yêu cầu đọc của client có thể chưa nhìn thấy dữ liệu mới nhất, trả về dữ liệu cũ. Mô hình này không đảm bảo tính nhất quán cao nhưng đổi lại availability cao.

Các khái niệm về fault tolerance Failure: cả hệ thống bị gián đoạn, không hoạt động Fault: một phần của hệ thống không hoạt động Node fault: sự cố tại một server node Crash-stop: server sập và dừng hoàn toàn, không hồi phục Crash-recovery: server sập và sau đó hồi phục trở lại Byzantine fault: server gặp sự cố và hoạt động không theo chương trình, xử lý một cách ngẫu nhiên, không đáng tin cậy. Byzantine fault có thể do trục trặc trong các thiết bị điện tử chứ không nhất thiết phải do sự can thiệp của tác nhân có ý đồ xấu. Network fault: sự cố về đường truyền, kết nối mạng, chẳng hạn như message bị mất hoặc delay, tắc nghẽn,. Fault tolerance: khả năng chống fault - hệ thống vẫn tiếp tục hoạt động khi có fault (số lượng fault dưới một ngưỡng tối đa) Single point of failure: khi fault ở một node dẫn tới failure trên toàn hệ thống 1.

Byzantine fault Lỗi Byzantine (Byzantine fault), hay còn gọi là Vấn đề các vị tướng Byzantine, là một tình trạng của một hệ thống, đặc biệt là hệ thống phân tán, trong đó các thành phần có thể bị lỗi và không có thông tin chính xác về việc liệu thành phần đó có bị lỗi hay không. Thuật ngữ này lấy tên từ một câu chuyện ngụ ngôn, "Vấn đề các vị tướng Byzantine", được phát triển để mô tả một tình huống trong đó, để tránh sự sụp đổ của hệ thống, các tác nhân của hệ thống phải đồng ý về một chiến lược phối hợp, nhưng một số tác nhân này là không đáng tin cậy. Một server trong một cluster có thể bị lỗi vì nhiều lý do, mà khiến cho server hoạt động không đúng theo chương trình, lệch khỏi chương trình, khiến cho mọi phản hồi từ server này trở nên không đáng tin cậy. Không có cách nhất định để phát hiện lỗi Byzantine, do các server bị lỗi hoàn toàn có thể phản hồi lại các yêu cầu một cách bình thường nhưng thực chất không thực hiện yêu cầu theo đúng chương trình.

Node bị lỗi còn có thể phản hồi thông tin khác nhau với mỗi thiết bị quan sát khác nhau. Do đó, các cơ chế phát hiện lỗi (fault detection) thông thường không thể nhận biết được liệu một node có bị lỗi Byzantine hay không. Tên gọi Byzantine xuất phát từ một sự so sánh rằng tình trạng này giống với một trận đánh mà các tướng quân đang quyết định có đánh chiếm thành Byzantine không. Các tướng quân cần thống nhất một kế hoạch đánh hay rút lui, nhưng trong số các vị tướng có một số kẻ phản bội, chúng có thể biểu quyết đánh nhưng sau đó lại rút lui.

Trong một cluster có 3 node, nếu một node bị lỗi Byzantine, cả cluster sẽ không thể cung cấp dịch vụ do không thể đạt thống nhất về trạng thái và cũng không tìm ra được node bị lỗi. Lỗi Byzantine chỉ có thể giải được trong một cluster có số node bị lỗi ít hơn ⅓ tổng số node. Lỗi Byzantine cũng có ảnh hưởng đến các thuật toán đồng thuận (Consensus). Chương 2: Load balancer 2.

Load balancer là một thành phần quan trọng trong kiến trúc hệ thống phân tán, chịu trách nhiệm phân phối lưu lượng mạng hoặc khối lượng công việc đều cho nhiều máy chủ hoặc tài nguyên khác nhằm đảm bảo hiệu suất và độ tin cậy cao của ứng dụng. Bộ cân bằng tải là điểm tiếp xúc đầu tiên trong một trung tâm dữ liệu sau khi yêu cầu vượt qua tường lửa.

Nội dung được bảo vệ bản quyền — Tải xuống đầy đủ