Bạn có thể triển khai nhiều bản sao của một dịch vụ trên nhiều container để đáp ứng nhu cầu về khả năng mở rộng.Tích hợp dễ dàng: Docker có tích hợp với các công cụ quản lý kiến trúc Mic
TỔNG QUAN VỀ CƠ SỞ THỰC TẬP
Giới thiệu về cơ sở thực tập
1.1 Lịch sử hình thành và phát triển
1.2 Sứ mệnh và giá trị cốt lõi
CƠ SỞ LÝ THUYẾT
Kiến trúc Microservices
Microservices, hay còn gọi là kiến trúc dịch vụ vi mô, là một phương pháp thiết kế ứng dụng dưới dạng một tập hợp các dịch vụ nhỏ, độc lập và chạy độc lập Mỗi dịch vụ này thực hiện một chức năng cụ thể và giao tiếp với các dịch vụ khác thông qua API.
Một số đặc điểm nổi bật của Microservices: Độc lập: Mỗi dịch vụ có thể được phát triển, triển khai, và quản lý một cách độc lập.
Khả năng mở rộng: Dễ dàng mở rộng một dịch vụ cụ thể mà không ảnh hưởng đến toàn bộ hệ thống.
Ngôn ngữ độc lập: Các dịch vụ có thể được viết bằng ngôn ngữ lập trình khác nhau, tùy thuộc vào yêu cầu cụ thể của dịch vụ đó.
Dễ dàng thay thế và nâng cấp: Một dịch vụ cụ thể có thể được thay thế hoặc nâng cấp mà không làm gián đoạn toàn bộ hệ thống.
Khả năng phục hồi cao: Khi một dịch vụ gặp sự cố, nó không ảnh hưởng đến hoạt động của các dịch vụ khác.
Mặc dù kiến trúc Microservices có nhiều lợi ích, nhưng nó cũng đi kèm với một số nhược điểm và thách thức:
Phức tạp trong việc quản lý: Có nhiều dịch vụ nhỏ cần được quản lý, triển khai và mở rộng Điều này đòi hỏi một hệ thống quản lý phức tạp và chất lượng.
Thách thức trong việc kiểm thử và gỡ lỗi: Mỗi dịch vụ cần được kiểm thử và gỡ lỗi riêng biệt, điều này có thể làm gia tăng công sức và thời gian cần thiết cho quá trình phát triển.
Tăng chi phí vận hành: Việc triển khai và duy trì nhiều dịch vụ khác nhau có thể đòi hỏi tài nguyên và chi phí vận hành lớn hơn so với kiến trúc Monolithic.
Bảo mật và quản lý truy cập phức tạp hơn: Kiến trúc Microservices đưa ra thách thức về bảo mật vì cần quản lý xác thực và ủy quyền cho nhiều dịch vụ khác nhau.
So sánh giữa kiến trúc Monolithic và Microservices
1.2 Docker và vai trò trong việc phát triển Microservices
Docker là một nền tảng ảo hóa hàng đầu cho việc đóng gói và triển khai các ứng dụng trong môi trường container Containers là một cách tiếp cận ảo hóa mà bạn có thể đóng gói ứng dụng cùng với tất cả các phụ thuộc của nó (thư viện, cài đặt, cấu hình) vào một container độc lập Điều này giúp đảm bảo rằng ứng dụng sẽ chạy đúng cách trên mọi môi trường Docker mà không cần phải lo lắng về các sự khác biệt trong hệ thống hoặc môi trường.
Vai trò của Docker trong kiến trúc Microservices: Đóng gói độc lập: Docker cho phép đóng gói mỗi dịch vụ Microservices vào một container độc lập Điều này giúp đảm bảo tính độc lập và tách biệt giữa các dịch vụ.
Quản lý phụ thuộc: Containers Docker chứa tất cả các phụ thuộc cần thiết, bao gồm thư viện và cài đặt, giúp đơn giản hóa việc quản lý phụ thuộc và xác định chính xác các yêu cầu về môi trường.
Khả năng mở rộng dễ dàng: Docker cho phép triển khai và mở rộng dịch vụ
Microservices một cách dễ dàng Bạn có thể triển khai nhiều bản sao của một dịch vụ trên nhiều container để đáp ứng nhu cầu về khả năng mở rộng.
Tích hợp dễ dàng: Docker có tích hợp với các công cụ quản lý kiến trúc Microservices như Kubernetes, Docker Swarm và Mesos, giúp quản lý và triển khai các dịch vụ một cách hiệu quả.
Lợi ích của việc sử dụng Docker trong Microservices:
Tích hợp và triển khai dễ dàng: Việc triển khai các dịch vụ trở nên đơn giản và tự động hóa hơn, giúp tiết kiệm thời gian và nguồn lực.
Môi trường đồng nhất: Docker đảm bảo rằng ứng dụng sẽ chạy đúng cách trên mọi môi trường Docker, từ máy tính cá nhân đến các môi trường sản xuất.
Tách biệt và độc lập: Mỗi container Docker là một đơn vị độc lập, giúp tách biệt sự cố và sự thay đổi giữa các dịch vụ.
Ngôn ngữ lập trình và công nghệ sử dụng
Java là một ngôn ngữ lập trình đa mục tiêu và đối tượng, được phát triển ban đầu bởi James Gosling và nhóm làm việc tại Sun Microsystems vào những năm 1990 Với sự linh hoạt, độ bảo mật cao và khả năng chạy trên nhiều nền tảng, Java đã trở thành một trong những ngôn ngữ lập trình phổ biến nhất trên thế giới.
Những điểm chính của Java: Độc lập với nền tảng (Platform-Independent): Mã nguồn Java được biên dịch thành bytecode, một dạng mã trung gian, và sau đó chạy trên Java Virtual Machine (JVM) Điều này cho phép mã Java chạy trên nhiều hệ điều hành và môi trường mà không cần sửa đổi. Đối tượng hóa (Object-Oriented): Java là một ngôn ngữ lập trình đối tượng, nghĩa là mọi thứ trong Java đều là đối tượng Điều này thúc đẩy việc tổ chức và tái sử dụng mã một cách hiệu quả.
Bảo mật (Security): Java được thiết kế với lớp bảo mật mạnh mẽ Các ứng dụng Java
9 chạy trong môi trường có kiểm soát để đảm bảo rằng chúng không gây hại cho hệ thống.
Dễ học và đọc (Readability): Java có cú pháp sáng sủa và tương tự tiếng Anh, giúp người lập trình dễ dàng học và hiểu.
Quản lý bộ nhớ tự động (Automatic Memory Management): Java sử dụng garbage collector để quản lý bộ nhớ, giúp ngăn ngừa lỗi gặp phải trong quản lý bộ nhớ. Một số ứng dụng của Java:
Phát triển ứng dụng máy tính cá nhân: Java thường được sử dụng để phát triển ứng dụng máy tính cá nhân và desktop.
Phát triển ứng dụng web và di động: Java được sử dụng trong việc phát triển ứng dụng web (sử dụng Java EE hoặc Spring Framework) và ứng dụng di động (sử dụng Android).
Phát triển ứng dụng máy chủ: Java là một trong những ngôn ngữ lập trình phổ biến cho việc phát triển ứng dụng máy chủ và dịch vụ web.
Lập trình nhúng (Embedded Programming): Java Embedded cho phép phát triển ứng dụng cho các thiết bị nhúng và IoT.
Phát triển trò chơi: Java cũng được sử dụng cho việc phát triển trò chơi máy tính.
Spring Boot là một framework dựa trên Spring, được thiết kế để đơn giản hóa quá trình tạo và triển khai ứng dụng Spring Nó loại bỏ yêu cầu của việc cấu hình XML truyền thống và giúp ứng dụng trở nên độc lập, có thể "chạy ngay" mà không cần nhiều bước cấu hình phức tạp. Những đặc điểm nổi bật của Spring Boot:
Tự động cấu hình: Spring Boot tự động cấu hình ứng dụng dựa trên các thư viện bạn đã thêm vào classpath, giúp loại bỏ nhu cầu cấu hình XML hoặc Java truyền thống.
Starter POMs: Những templates này giúp giảm thiểu việc quản lý phụ thuộc và cung cấp một bộ thư viện tối ưu và cấu hình mặc định.
Actuator: Cung cấp các công cụ giám sát và quản lý ứng dụng, giúp bạn có cái nhìn sâu rộng về trạng thái và hoạt động của ứng dụng.
Embedded Server: Spring Boot đi kèm với các máy chủ ứng dụng nhúng như Tomcat và Jetty, cho phép bạn tạo ra ứng dụng standalone mà không cần một máy chủ ứng dụng bên ngoài.
Opinionated Defaults: Spring Boot cung cấp một bộ cấu hình mặc định dựa trên "best practices", giúp bạn bắt đầu một cách nhanh chóng.
Lợi ích khi sử dụng Spring Boot:
Tăng tốc độ phát triển: Với các cấu hình mặc định và tự động cấu hình, bạn có thể tập trung vào việc phát triển tính năng chính của ứng dụng. Độc lập: Ứng dụng Spring Boot có thể chạy độc lập, giúp việc triển khai và chạy ứng dụng trở nên dễ dàng và linh hoạt.
Tích hợp dễ dàng: Hỗ trợ sâu rộng cho nhiều công nghệ và dịch vụ, từ cơ sở dữ liệu, bảo mật đến các dịch vụ điện toán đám mây.
Trong khi Spring Framework cung cấp một nền tảng mạnh mẽ cho việc phát triển ứng dụng
Java, Spring Boot mang lại sự đơn giản và tốc độ, giúp phát triển và triển khai ứng dụng trở nên dễ dàng hơn.
Tiếp theo là những Framework được tích hợp cùng Spring Boot:
- Spring Security: là một Framework mạnh mẽ và linh hoạt dành cho Java, giúp bảo vệ ứng dụng web, dịch vụ và ứng dụng doanh nghiệp trước các mối đe dọa và tấn công Được xây dựng dưới dạng một dự án con của Spring, Spring Security cung cấp các giải pháp bảo mật toàn diện cho ứng dụng Java.
Những đặc điểm nổi bật của Spring Security:
Xác thực và Ủy quyền: Spring Security hỗ trợ một loạt các nguồn xác thực, từ cơ sở dữ liệu, LDAP đến OAuth2 Nó cung cấp một cơ chế ủy quyền mạnh mẽ, cho phép bạn kiểm soát truy cập đến các tài nguyên dựa trên vai trò, quyền hoặc các thuộc tính khác của người dùng.
Bảo vệ trước các Mối đe dọa Web: Spring Security cung cấp các giải pháp bảo vệ trước các mối đe dọa web phổ biến như CSRF, XSS và Session Fixation.
Tích hợp dễ dàng: Được thiết kế để dễ dàng tích hợp với các ứng dụng Spring khác, từ Spring MVC đến Spring Data.
Mô hình dựa trên Java và XML: Cấu hình bảo mật có thể được định nghĩa thông qua XML hoặc Java Config, tùy thuộc vào sở thích của bạn.
OAuth2 và JWT: Hỗ trợ sẵn sàng cho OAuth2 và JWT, giúp bạn xây dựng và bảo vệ dịch vụ RESTful và Single-Page Applications (SPA).
Lợi ích khi sử dụng Spring Security:
Bảo mật toàn diện: Từ xác thực người dùng đến bảo vệ API, Spring Security đảm bảo rằng ứng dụng của bạn được bảo vệ trước mọi mối đe dọa.
Tích hợp mượt mà: Spring Security được thiết kế để hoạt động mượt mà với các thành phần khác của hệ sinh thái Spring.
Cộng đồng mạnh mẽ: Với một cộng đồng lớn và tích cực, bạn có thể dễ dàng tìm kiếm sự hỗ trợ và tài nguyên khi gặp vấn đề hoặc cần tư vấn.
Authentication flow trong Spring Security
Spring Security là một trong những giải pháp bảo mật hàng đầu cho ứng dụng Java Với một loạt các tính năng và cấu hình linh hoạt, nó giúp đảm bảo rằng ứng dụng của bạn không chỉ an toàn trước các mối đe dọa nhưng còn cung cấp trải nghiệm người dùng mượt mà và an toàn.
NỘI DUNG THỰC TẬP
Tổng quan về đề tài
Xây dựng một nền tảng chia sẻ hình ảnh trực tuyến, mang lại trải nghiệm tương tự như Pinterest, nơi người dùng có thể tải lên, chia sẻ và khám phá hình ảnh từ cộng đồng.
1.2 Ý tưởng Ứng dụng sẽ sử dụng những công nghệ sau:
React: Được chọn làm khung xây dựng chính cho giao diện người dùng, giúp tạo ra một trải nghiệm người dùng mượt mà và tương tác.
TailwindCSS: Một thư viện CSS tiện ích giúp tạo ra giao diện người dùng hiện đại và đáp ứng nhanh chóng.
Spring Boot: Làm nền tảng chính cho việc phát triển backend, giúp tạo ra các dịch vụ RESTful hiệu quả và dễ dàng tích hợp.
Spring Cloud: Hỗ trợ việc xây dựng và tích hợp các dịch vụ phân tán, giúp ứng dụng có khả năng mở rộng và độ tin cậy cao.
Spring Security: Đảm bảo an ninh cho ứng dụng, bao gồm xác thực người dùng và quản lý quyền truy cập.
MySQL: Được sử dụng để lưu trữ thông tin người dùng, metadata của hình ảnh và các dữ liệu liên quan khác.
MinIO: Là giải pháp lưu trữ đối tượng, chịu trách nhiệm lưu trữ các hình ảnh thực tế mà người dùng tải lên.
Truyền thông giữa các dịch vụ:
Apache Kafka: Đóng vai trò như một message broker, giúp các dịch vụ trong hệ thống giao tiếp với nhau một cách hiệu quả và đáng tin cậy.
1.3 Các chức năng chính Ứng dụng sẽ có các chức năng chính sau: Đăng ký & Đăng nhập:
Tạo tài khoản mới. Đăng nhập vào tài khoản hiện có.
Cập nhật thông tin cá nhân (hình đại diện, tên, mô tả ). Đổi mật khẩu.
Xem và chỉnh sửa danh sách theo dõi và người theo dõi.
Tải lên hình ảnh mới.
Thêm mô tả, tiêu đề cho hình ảnh.
Xóa hoặc chỉnh sửa hình ảnh đã tải lên.
Tạo và quản lý bộ sưu tập hình ảnh.
Tìm kiếm hình ảnh theo từ khóa.
Khám phá hình ảnh phổ biến hoặc mới nhất từ cộng đồng.
Tương tác với hình ảnh:
Theo dõi người dùng khác để nhận cập nhật từ họ.
Xem hình ảnh từ người dùng mình theo dõi.
Nhận thông báo khi có người tương tác với hình ảnh của bạn hoặc khi có người theo dõi bạn.
Thiết kế cơ sở dữ liệu và kho lưu trữ
2.1 Thiết kế cơ sở dữ liệu với MySQL
Dưới đây là sơ đồ quan hệ thực thể (Entity Relationship Diagram) cho cơ sở dữ liệu:
Sơ đồ này bao gồm các thực thể sau:
User: Đại diện cho người dùng của ứng dụng Bao gồm thông tin như id, tên người dùng, mật khẩu, email và URL ảnh đại diện.
Image: Đại diện cho hình ảnh được tải lên Bao gồm URL, mô tả, ngày tải lên và id người dùng đã tải lên.
Collection: Đại diện cho bộ sưu tập hình ảnh mà người dùng tạo ra Bao gồm tên, mô tả và id người dùng tạo ra.
ImageCollection: Mối quan hệ nhiều-nhiều giữa Image và Collection, cho phép một hình ảnh thuộc nhiều bộ sưu tập và một bộ sưu tập chứa nhiều hình ảnh.
Comment: Đại diện cho bình luận của người dùng trên một hình ảnh Bao gồm văn bản,ngày và id của người dùng và hình ảnh liên quan.
Like: Mối quan hệ giữa người dùng và hình ảnh mà họ thích.
Follow: Mối quan hệ theo dõi giữa các người dùng.
2.2 Thiết kế kho lưu trữ hình ảnh với MinIO
Dưới đây là sơ đồ quan hệ thực thể (ERD) mô tả cách hình ảnh được lưu trữ trong MinIO:
Image: Đại diện cho hình ảnh trong ứng dụng.
MinIO_Storage: Đại diện cho kho lưu trữ MinIO Mỗi hình ảnh sẽ được lưu trữ dưới dạng một đối tượng trong MinIO với một object_key duy nhất.
Thiết kế ứng dụng
3.1 Sơ đồ kiến trúc tổng quan
3.2 Chi tiết về các dịch vụ
3.2.1 API Gateway: Đi m truy c p trung tâm cho t t c các d ch vể ậ ấ ả ị ụ
API Gateway là trái tim của hệ thống, điều tiết và định hướng tất cả các yêu cầu đến các dịch vụ thích hợp.
Công nghệ và công cụ:
Spring Cloud Gateway: Chúng tôi sử dụng Spring Cloud Gateway, một thành phần của Spring Cloud, để triển khai API Gateway Spring Boot cung cấp nền móng cho việc triển khai nhanh chóng và dễ dàng cấu hình
Cấu hình và định nghĩa các routes cho tất cả các dịch vụ.
Tích hợp JWT để xác thực và ủy quyền yêu cầu từ người dùng.
Tải cân bằng giữa các instances của dịch vụ để đảm bảo hiệu suất và độ tin cậy.
3.2.2 Service Registry: Đăng ký và phát hi n d ch vệ ị ụ
Service Registry đóng vai trò như một sổ địa chỉ cho hệ thống, cho phép các dịch vụ biết về nhau và tương tác một cách linh hoạt.
Công nghệ và công cụ:
Spring Cloud Gateway: Sử dụng Spring Cloud Eureka Server để triển khai Service Registry, giúp các dịch vụ tự động đăng ký và tìm kiếm nhau.
Cấu hình và khởi chạy Eureka Server. Đảm bảo rằng tất cả các dịch vụ đều tự động đăng ký khi khởi động và tự bỏ đăng ký khi tắt.
3.2.3 Config Server: Qu n lý c u hình trung tâm cho các d ch vả ấ ị ụ
Config Server giúp quản lý cấu hình trung tâm, giúp các dịch vụ có thể thay đổi cấu hình mà không cần khởi động lại.
Công nghệ và công cụ:
Spring Cloud Config Server: Sử dụng Spring Cloud Config Server để cung cấp thông tin cấu hình cho tất cả các dịch vụ từ một kho lưu trữ trung tâm (ví dụ: Git Repository). Các nhiệm vụ chính:
Cấu hình Config Server và liên kết nó với kho lưu trữ cấu hình. Đảm bảo tất cả các dịch vụ có thể truy xuất và cập nhật cấu hình một cách trơn tru.
3.2.4 Circuit Breaker: C ch b o v d ch v kh i tình tr ng quá t iơ ế ả ệ ị ụ ỏ ạ ả
Circuit Breaker giúp hệ thống đáp ứng linh hoạt trước các sự cố, ngăn chặn việc lan truyền lỗi và bảo vệ hệ thống khỏi tình trạng quá tải.
Công nghệ và công cụ:
Spring Boot & Resilience4j: Trong dự án này, chúng tôi đã quyết định sử dụng Resilience4j, một thư viện lightweight và dễ mở rộng, tối ưu cho Java 8 và hỗ trợ tích hợp sâu với Spring Boot Sử dụng Resilience4j cung cấp một lựa chọn hiệu suất cao và linh hoạt cho việc triển khai cơ chế Circuit Breaker.
Tích hợp Resilience4j vào dịch vụ và cấu hình các ngưỡng và chiến lược cho Circuit Breaker.
Thiết lập các cơ chế fallback và recovery để xử lý các yêu cầu khi Circuit Breaker được kích hoạt, giảm thiểu gián đoạn đối với người dùng.
Thực hiện các bài kiểm thử tải để đánh giá và tinh chỉnh cấu hình, đảm bảo hệ thống hoạt động ổn định và hiệu quả.
3.2.5 User Service: Qu n lý ngả ườ i dùng
User Service là một dịch vụ quan trọng chịu trách nhiệm quản lý thông tin và hành động liên quan đến người dùng.
Công nghệ và công cụ:
Spring Boot: Được sử dụng như là nền tảng chính để xây dựng ứng dụng Spring Boot giúp tôi dễ dàng khởi tạo và triển khai dịch vụ mà không cần phải lo lắng về việc cấu hình chi tiết.
JWT (JSON Web Token): Được sử dụng như một giải pháp xác thực và ủy quyền Khi người dùng đăng nhập thành công, họ sẽ nhận được một token Token này sau đó sẽ được sử dụng trong các yêu cầu tiếp theo để xác thực và xác định quyền truy cập của người dùng.
MySQL: Là hệ quản trị cơ sở dữ liệu được chọn để lưu trữ thông tin người dùng Tôi đã tham gia vào việc thiết kế bảng, tối ưu truy vấn, và quản lý các mối quan hệ giữa các bảng.
Thiết kế và cài đặt các API liên quan đến người dùng như đăng ký, đăng nhập, xem và cập nhật thông tin cá nhân.
Xác thực & phân quyền người dùng sử dụng JWT và Spring Security.
Xử lý và quản lý các lỗi và ngoại lệ phát sinh từ dịch vụ.
3.2.6 Image Service: Qu n lý tài nguyên nhả ả
Image Service chịu trách nhiệm lưu trữ, quản lý và phân phối hình ảnh cũng như các bộ ảnh cho người dùng Đối với một ứng dụng yêu cầu cao về hình ảnh, việc quản lý chúng một cách hiệu quả và bảo mật là rất quan trọng.
Công nghệ và công cụ:
Spring Boot: Là nền tảng chính được sử dụng để xây dựng dịch vụ, giúp tăng tốc độ phát triển và triển khai dễ dàng.
MinIO: Là kho lưu trữ đối tượng được sử dụng để lưu giữ dữ liệu hình ảnh thực tế, cung cấp khả năng lưu trữ hiệu quả và truy cập nhanh chóng.
MySQL: Cơ sở dữ liệu này chứa thông tin liên quan đến hình ảnh, bao gồm metadata, người tải lên, ngày giờ tải lên và các thuộc tính khác liên quan đến hình ảnh.
Các nhiệm vụ chính tôi đã tham gia:
Thiết kế và cài đặt các API cho việc tải lên, chỉnh sửa, xóa và truy xuất hình ảnh cũng như bộ ảnh sử dụng Spring Boot.
Tích hợp MinIO để lưu trữ dữ liệu hình ảnh và đảm bảo đồng bộ giữa dữ liệu trên MinIO và thông tin lưu trữ trên MySQL.
Xây dựng tính năng tạo và quản lý bộ ảnh, cho phép người dùng tổ chức và phân loại hình ảnh của họ một cách dễ dàng.
3.2.7 Rating Service: D ch v đánh giáị ụ
Rating Service là dịch vụ chịu trách nhiệm quản lý, thu thập và phân tích đánh giá từ người dùng, tạo nên một phản hồi quan trọng cho cả hệ thống và người dùng khác.
Công nghệ và công cụ:
ExpressJS: Đây là một framework nhẹ và linh hoạt trên nền tảng Node.js, cho phép xây dựng các ứng dụng web và API một cách nhanh chóng và hiệu quả.
MongoDB: Một cơ sở dữ liệu không SQL, giúp lưu trữ và quản lý dữ liệu dưới dạng tài liệu JSON Với khả năng mở rộng và linh hoạt của MongoDB, việc lưu trữ và truy vấn dữ liệu đánh giá trở nên dễ dàng và hiệu quả.
Các nhiệm vụ chính tôi đã tham gia:
Thiết kế và cài đặt các API cho việc tạo, chỉnh sửa, xóa và truy xuất đánh giá sử dụng ExpressJS.
Tích hợp MongoDB để lưu trữ dữ liệu đánh giá và thực hiện các thao tác truy vấn hiệu quả.
Xây dựng logic phân tích để tính toán điểm đánh giá trung bình và số lượng đánh giá cho mỗi sản phẩm hoặc dịch vụ.
Xây dựng giao diện người dùng
4.1 Thiết kế giao diện người dùng
Sau đây là thiết kế Giao diện người dùng (UI) theo trang:
Mục tiêu: Cung cấp giao diện cho người dùng đăng nhập vào hệ thống.
Cung cấp trường nhập cho tên đăng nhập hoặc email và mật khẩu.
Nút 'Đăng nhập' để xác thực thông tin và truy cập hệ thống.
Thông tin đăng nhập phải được mã hóa khi truyền qua mạng.
Mật khẩu người dùng phải được bảo mật và không được lưu trữ dưới dạng văn bản thuần túy trong cơ sở dữ liệu.
Mục tiêu: Hiển thị danh sách hình ảnh từ tất cả người dùng theo dạng lưới động. Yêu cầu chức năng:
Thanh tìm kiếm cho phép người dùng tìm kiếm hình ảnh theo từ khóa.
Hình ảnh tự động tải thêm khi người dùng cuộn xuống cuối trang.
Mục tiêu: Hiển thị hình ảnh và thông tin cơ bản của người dùng.
Hiển thị tất cả hình ảnh mà người dùng đã tạo và lưu.
- Trang chi tiết hình ảnh:
Mục tiêu: Hiển thị chi tiết về một hình ảnh cụ thể.
Hiển thị hình ảnh ở kích thước đầy đủ.
Hiển thị thông tin về tác giả, mô tả, và bình luận từ cộng đồng.
- Trang tải lên hình ảnh:
Mục tiêu: Cho phép người dùng tải lên hình ảnh mới.
Cung cấp trường nhập mô tả, chọn danh mục và đặt từ khóa cho hình ảnh.
Hỗ trợ kéo và thả để tải lên hình ảnh.
4.2 Xây dựng giao diện với React và TailwindCSS
Sau đây là giao diện sau khi đã xây dựng sử dụng React và TailwindCSS:
Giao diện trang đăng nhập bao gồm:
Logo: Ở phía trên cùng của Form đăng nhập, logo của dự án được đặt ở trung tâm, giúp tăng cường nhận diện thương hiệu. Ô nhập tên đăng nhập: Một trường nhập dữ liệu rộng, người dùng có thể nhập tên đăng nhập (sử dụng địa chỉ email) của họ để đăng nhập. Ô nhập mật khẩu: Trường này cho phép người dùng nhập mật khẩu của họ Có một biểu tượng mắt nhỏ ở góc phải, cho phép người dùng hiển thị hoặc ẩn mật khẩu khi nhập.
Nút 'Đăng nhập': Nút lớn và rõ ràng, được thiết kế để nổi bật trên trang, giúp người dùng dễ dàng nhấp vào và đăng nhập.
Nút "Đăng nhập với Google": Ngay dưới trường nhập mật khẩu, có một nút đăng nhập bằng Google Nút này có biểu tượng của Google và mô tả rõ ràng, giúp người dùng dễ dàng đăng nhập bằng tài khoản Google của họ mà không cần tạo tài khoản mới.Thiết kế phông nền: Sử dụng một nền trắng tối giản giúp người dùng tập trung vào form đăng nhập.
Giao diện trang chính bao gồm:
Thanh tìm kiếm: Đặt ở trên cùng của trang, thanh tìm kiếm cho phép người dùng nhập từ khóa để tìm kiếm nội dung cụ thể.
Dạng lưới "Masonry": Phía dưới thanh tìm kiếm là một dạng lưới Masonry hiển thị hình ảnh từ cộng đồng Hình ảnh có kích thước khác nhau về chiều cao nhưng giữ chiều rộng cố định, tạo ra một cảm giác liên tục và động.
Nút "Đăng hình": Hiển thị dưới dạng dấu cộng được đặt ở góc trên bên phải, nút này cho phép người dùng dễ dàng tải lên hình ảnh mới mà họ muốn chia sẻ.
Thanh điều hướng: Ở cạnh trái của trang, thanh này chứa các liên kết tới các phần khác như trang chủ, trang cá nhân và mục lục ảnh theo chủ đề.
Tương tác hình ảnh: Mỗi hình ảnh trên lưới có khả năng tương tác, cho phép người dùng nhấp để xem chi tiết hơn, thích, bình luận hoặc lưu vào bộ sưu tập cá nhân của họ.
Phân trang và Lazy Loading: Khi người dùng cuộn xuống dưới cùng, hệ thống tự động tải thêm hình ảnh mới, giúp trải nghiệm duyệt web trở nên mượt mà và liên tục. Ô hình ảnh:
Mỗi ô hình ảnh bao gồm những thành phần sau:
Nút “Tải xuống”: Được hiển thị ở góc trên bên trái hình ảnh, dưới dạng mũi tên kéo xuống Khi bấm vào, hình ảnh sẽ tự động tải xuống.
Nút “Lưu ảnh”: Được hiển thị ở góc trên bên phải hình ảnh, có màu đỏ nổi bật Khi bấm vào, hình ảnh sẽ được lưu về khu vực “Đã lưu” ở trang cá nhân.
Link đính kèm: Được hiển thị ở góc dưới bên trái hình ảnh, thường được dùng để lưu nguồn của hình ảnh hoặc trích dẫn Khi bấm vào, người dùng sẽ tự động chuyển hướng đến link đính kèm.
Giao diện trang đăng nhập bao gồm: Ảnh bìa: Được đặt ở nửa phần trên của giao diện. Ảnh đại diện và tên người dùng: Ở giữa trang, ảnh đại diện của người dùng được hiển thị ở kích thước lớn, kết hợp với tên đầy đủ và tên người dùng Điều này giúp tạo ra một ấn tượng mạnh mẽ và nhận diện cá nhân.
Khu vực ảnh đã chia sẻ: Phần chính của trang là một lưới hiển thị tất cả hình ảnh mà người dùng đã chia sẻ Giống như trang chính, hình ảnh được hiển thị theo dạng lưới
Masonry, tạo ra một trải nghiệm duyệt hình ảnh liên tục và trực quan.
Khu vực ảnh đã lưu: Phần chính của trang là một lưới hiển thị tất cả hình ảnh mà người dùng đã chia lưu, cũng được hiển thị theo dạng lưới Masonry.
Nút “Created” và “Saved”: Được đặt ở ngay dưới phần ảnh đại diện và tên người dùng, được dùng để chuyển đổi giữa khu vực ảnh đã chia sẻ và khu vực ảnh đã lưu.
- Trang tải lên hình ảnh:
Giao diện trang tải lên hình ảnh bao gồm:
Khu vực kéo và thả: Ở trung tâm của trang, một khu vực rộng lớn cho phép người dùng kéo và thả hình ảnh từ máy tính của họ Khi hình ảnh được chọn, nó sẽ được hiển thị ngay lập tức trong khu vực này.
Chọn hình ảnh từ thiết bị: Nếu người dùng không muốn sử dụng chức năng kéo và thả, họ có thể nhấp vào nút "Chọn hình ảnh" để duyệt và chọn hình ảnh từ thiết bị của họ.
Triển khai giao diện lập trình ứng dụng (API)
Đây là hệ thống phức tạp cần phải quản lý nhiều loại dữ liệu khác nhau như người dùng, hình ảnh, và đánh giá Để quản lý việc truy xuất và thao tác với dữ liệu một cách hiệu quả, ta sử dụng mẫu thiết kế Generic Repository Pattern.
Generic Repository Pattern là một mẫu thiết kế phổ biến trong lập trình, cho phép chúng ta tạo ra một lớp truy xuất dữ liệu chung mà có thể tái sử dụng cho nhiều loại đối tượng khác nhau Bằng cách này, chúng ta có thể tối ưu hóa và giảm lượng mã lặp lại, tăng cường bảo mật và tính đồng nhất cho việc truy xuất dữ liệu.
Với mẫu thiết kế này, chúng ta có thể đảm bảo rằng mỗi dịch vụ, dù là quản lý người dùng, hình ảnh, hay đánh giá, đều tuân theo cùng một quy trình và chuẩn mực khi thao tác với cơ sở dữ liệu Điều này không chỉ giúp việc bảo trì và mở rộng dễ dàng hơn mà còn giảm thiểu rủi ro về lỗi và vấn đề bảo mật.
5.1.1 T o User Service b ng Spring Boot s d ng MySQLạ ằ ử ụ
User Service sẽ chịu trách nhiệm quản lý thông tin người dùng, bao gồm việc đăng ký, đăng nhập và cập nhật hồ sơ. Đầu tiên, để kết nối đến MySQL, ta cần những cấu hình sau:
Server.port: Là Expose port của ứng dụng khi chạy
Spring.applicaion.name: Tên của ứng dụng.
Spring.datasource: Những thông tin để kết nối đến datasource
Spring.jpa: Cấu hình cho Spring Data JPA để thao tác với Datasource một cách chính xác
Tiếp theo, ta khởi tạo Entity như đã mô tả trong ERD:
5.1.2 T o Image Service b ng Spring Boot s d ng MySQL và MinIOạ ằ ử ụ
Chúng ta khởi tạo tương tự như với User Service.
Tiếp theo, để kết nối với MinIO, ta cần import thư viện MinIO vào pom.xml:
Tiếp theo, ta sẽ cấu hình để kết nối Image Service đến MinIO.
Tiếp theo, khởi tạo các Entity như đã mô tả trên ERD:
5.1.3.ạ T o Rating Service b ng ExpressJS s d ng MongoDBằ ử ụ Đầu tiên, tạo một thư mục với tên là rating-service.
Sau đó, ta tạo ứng dụng Node.Js và cài đặt các thư viện cần thiết:
Express: Framework web cho Node.js
Mongoose: Là thư viện ODM dành cho MongoDB, tương tự như Hibernate của Spring Boot
Tiếp theo, ta cấu hình để ứng dụng kết nối đến MongoDB:
41Tiếp theo, ta khởi tạo các Entity như đã mô tả trong ERD:
5.2.1 Xác th c và y quy n ngự ủ ề ườ i dùng
Ta xác thực người dùng sử dụng JWT Dưới đây là luồng xác thực:
Người dùng gửi thông tin đăng nhập (tên người dùng và mật khẩu) đến API.
Hệ thống kiểm tra thông tin đăng nhập và tạo một JWT (JSON Web Token) và một refresh token.
JWT và refresh token được gửi trở lại cho người dùng.
2, Người dùng gửi yêu cầu với JWT:
Người dùng gửi yêu cầu đến API và đính kèm JWT trong header của yêu cầu.
Hệ thống kiểm tra tính hợp lệ của JWT.
Nếu JWT hợp lệ, yêu cầu được xử lý và dữ liệu được gửi trở lại người dùng. Nếu JWT không hợp lệ hoặc đã hết hạn, yêu cầu bị từ chối.
3, Refresh token khi JWT hết hạn:
Khi JWT hết hạn, người dùng gửi refresh token đến API để yêu cầu một JWT mới.
Hệ thống kiểm tra tính hợp lệ của refresh token.
Nếu refresh token hợp lệ, một JWT mới được tạo và gửi trở lại người dùng. Nếu refresh token không hợp lệ hoặc đã hết hạn, người dùng sẽ phải đăng nhập lại. Sau đây là một số cấu hình dành cho JWT:
Lấy và xử lý Token từ request:
Cài dặt chức năng đăng ký:
Cài đặt chức năng đăng nhập:
Cài đặt chức năng Refresh Token:
Tiếp theo, ta phân quyền người dùng dựa trên mô hình RBAC:
Mô hình RBAC (Role-Based Access Control) là một mô hình phân quyền dựa trên vai trò người dùng trong hệ thống Dưới đây là cách mô hình RBAC thường được triển khai trong một ứng dụng web, như một ứng dụng Spring Boot:
1, Định nghĩa Vai trò và Quyền:
Các vai trò (Roles) được định nghĩa trong hệ thống (ví dụ: Admin, User, Manager, etc.)
Các quyền (Permissions) được định nghĩa (ví dụ: read, write, delete, etc.) Mỗi vai trò được gán một hoặc nhiều quyền.
2, Gán Vai trò cho Người dùng:
Mỗi người dùng được gán một hoặc nhiều vai trò.
Người dùng kế thừa tất cả quyền của vai trò được gán cho họ.
3, Kiểm tra Quyền khi Truy cập Tài nguyên:
Khi người dùng cố gắng truy cập một tài nguyên hoặc thực hiện một hành động, hệ thống kiểm tra xem người dùng có quyền thích hợp không dựa trên vai trò của họ. Nếu người dùng có quyền, họ được phép truy cập hoặc thực hiện hành động. Nếu không, truy cập bị từ chối.
4, Quản lý Vai trò và Quyền:
Các quản trị viên có thể thêm, xóa, hoặc chỉnh sửa vai trò và quyền.
Các quản trị viên có thể gán hoặc loại bỏ vai trò từ người dùng.
Dưới đây là một số cài đặt phân quyền: Định nghĩa Permissions: Định Nghĩa Role:
Tích hợp Role và Permission vào Entity:
5.2.2 Các chi n lế ượ c b o m t cho ng d ngả ậ ứ ụ
Trong ứng dụng Spring Boot sử dụng Spring Security, SecurityFilterChain đóng vai trò chính trong quá trình xác thực và ủy quyền yêu cầu đến ứng dụng Dưới đây là giải thích chi tiết và cách hoạt động.
SecurityFilterChain là một chuỗi các bộ lọc (filters) được sắp xếp theo một thứ tự nhất định Khi một yêu cầu HTTP đến, nó sẽ được xử lý qua chuỗi bộ lọc này Mỗi bộ lọc trong chuỗi có thể thực hiện một nhiệm vụ bảo mật cụ thể, chẳng hạn như xác thực người dùng, kiểm tra token, ủy quyền,
Khi một yêu cầu đến, Spring Security sẽ đi qua SecurityFilterChain từ bộ lọc đầu tiên đến cuối cùng Mỗi bộ lọc sẽ thực hiện nhiệm vụ của mình và sau đó chuyển yêu cầu đến bộ lọc tiếp theo trong chuỗi Nếu một bộ lọc quyết định yêu cầu không được phép truy cập (ví dụ: token không hợp lệ), nó có thể gửi phản hồi ngay lập tức mà không cần chuyển qua các bộ lọc tiếp theo.
3, Các bộ xử lý quan trọng trong SecurityFilterChain
Dưới đây là một số bộ lọc quan trọng thường gặp:
UsernamePasswordAuthenticationFilter: Xử lý yêu cầu xác thực dựa trên tên người dùng và mật khẩu.
AuthenticationProvider: Xử lý xác thực (tùy chỉnh).
SessionCreationPolicy: Quản lý chính sách tạo Session.
Trong một số trường hợp, bạn có thể muốn tùy chỉnh SecurityFilterChain để thêm, loại bỏ hoặc sắp xếp lại bộ lọc theo nhu cầu riêng Dưới đây là SecurityFilterChain đã được tạo:
5.3 Tích hợp Apache Kafka Đầu tiên, ta cần phải cài đặt Apache Kafka Điều này bao gồm việc tải xuống Kafka, cài đặt và khởi động nó cùng với ZooKeeper (dịch vụ hỗ trợ phân tán được Kafka sử dụng).
Ta sẽ cài đặt Apache Kafka và Zookeeper sử dụng Docker Compose:
Tiếp theo, ta tích hợp Kafka với User Service và Image Service Sau đây là cấu hình:
Tiếp theo, chúng ta sẽ tạo các KafkaProducer (Để gửi tin nhắn) và KafkaConsumer (Để nhận tin nhắn):
Giới thiệu luồng chia sẻ ảnh:
1, Khi người dùng điền đủ thông tin và bấm tải ảnh lên, Client sẽ gửi một request đến Image Service để tải ảnh lên kho lưu trữ (Upload Object lên MinIO)
2, Sau khi tải ảnh, kho lưu trữ sẽ trả về ImageURL và UploadDate ImageServiceProducer khi đó sẽ gửi một tin nhắn lên Kafka bao gồm 2 thông tin trên.
3, UserServiceConsumer khi đó sẽ nghe và nhận tin nhắn Sau đó User Service sẽ tạo một message mới bao gồm các thông tin của ảnh (tên, mô tả, người chia sẻ, …) và gửi lên Kafka.