Giải đáp những thắc mắc kĩ thuật quan trọng về Microservices

AMA (Ask Me Anything) là 1 sự kiện Q&A (Hỏi đáp trực tiếp) diễn ra đều đặn trên fanpage của TopDev vào thứ 6 hằng tuần. AMA đón nhận sự xuất hiện của anh Nguyễn Minh Khôi CTO – DKT Technology giúp các bạn trẻ đam mê IT giải đáp những thắc mắc liên quan đến Microservices & xây dựng kiến thức hệ thống.

Trước tiên, chúng ta hãy tìm hiểu 1 chút về quá trình công tác của anh Khôi nhé!

  • 8/2007 – 9/2009: anh là developer của FPT
  • 5/2009 đến nay: anh đồng hành cùng DTK trong vai trò CTO
  • Anh đã từng góp mặt tại các sự kiện công nghệ hàng đầu tại Việt Nam với vai trò Speaker, điển hình như sự kiện Vietnam Web Summit vừa qua.

Q: Chào anh, Anh có thể chia sẻ về việc sử dụng esb trong esb và các cách liên lạc giữa các service cũng như API Gateway được không a.

A: ESB là khái niệm trong SOA, microservice không dùng cái đó. Bản thân các service khi gọi nhau phải hiểu được giao thức & format dữ liệu của nhau. Đơn giản nhất là các microservice gọi nhau qua Rest API sử dụng Json.

Còn API Gateway đóng vai trò như 1 cửa ngõ chung để các ứng dụng bên ngoài gọi vào các microservice bên trong. Các microservice gọi trực tiếp nhau không thông qua API Gateway. Vấn đề là làm thế nào để các microservice (và cả API Gateway) biết được thông tin của microservice khác để gọi. Khi đó trong hệ thống cần có 1 thành phần gọi là Service Discovery.

Q: Câu hỏi của mình đây (và có thể là câu hỏi mong muốn của nhiều bạn): áp dụng microserver có điểm gì dở nhất cho việc phát triển một hệ thống phần mềm, và ngoài kiểu Rest call giữa các microservice, thì còn kiểu nào nữa? Mỗi kiểu áp dụng cho trường hợp nào?

A: Mình xin trả lời nhé:

Về điểm dở của Microservices đó là việc phát triển ứng dụng khó hơn, vận hành & xử lý lỗi cũng khó hơn nhiều. Stack công nghệ cũng thay đổi rất nhiều so với làm ứng dụng Monolithic.

Bạn cần xác định trước 1 số yếu tố khi triển khai microservice:
1. Đây có phải là sản phẩm phát triển lâu dài hay không?
2. Mức độ scale của hệ thống có lớn không (scale về lượng người dùng hoặc về dữ liệu)?
3. Team có sẵn sàng đối đầu với những khó khăn khi chuyển sang mô hình này không?

Khi bọn mình bắt đầu làm cho sản phẩm Bizweb thì 2 câu hỏi đầu đã xác định được luôn rồi. Câu số 3 thì cũng ko gặp vấn đề gì vì cả team đều rất máu chiến, mặc dù lúc đó chưa biết gì.

Microservice có một số mô hình phát triển:
1 là dùng Restful thuần túy, sử dụng format JSON (hoặc Protobuf, Avro…). Các service gọi service khác đồng bộ hoặc bất đồng bộ.
2 là theo mô hình message queue, sử dụng các hệ thống message như RabbitMQ, Kafka… để tương tác giữa các microservice. Cách này là bất đồng bộ hoàn toàn.
3 là dùng Event Sourcing Pattern, phân tách phần đọc & ghi. Mô hình này thì bên mình chưa triển khai.

Độ khó thì tăng dần từ mô hình 1 -> 3

Theo mình cái dở (ý không phải cái khó) có nghĩa khác. Cái dở – cũng là cái hay của microservice chính là vì nó tách rời dữ liệu và logic các module của hệ thống, lỏng lẻo hơn, chỉ liên quan đến nhau bởi các API được define để giao tiếp nhau theo quy tắc định trước, nó không đề cao tính integrity về dữ liệu lẫn đồng nhất chức năng của cả hệ thống, để có được tính uyển chuyển độc lập cao hơn giữa các module, ví dụ trong quản lý khách hàng và hợp đồng dịch vụ kiểu monolithic, thì thường cùng 1 DB, các entitty hay các bảng thường có ràng buộc bởi khoá ngoài với nhau để đảm bảo đồng nhất dữ liệu, và cũng gắn với nhau về quy trình, ví dụ không bao giờ có chuyện tạo ra hợp đồng dịch vụ web rồi mới tạo ra bản ghi khách hàng của hợp đồng đó, phải đúng thứ tự bởi mỗi bước sẽ bị kiểm tra tính chất này.

Với microservice thì có thể nếu module quản lý hợp đồng và module quản lý khách hàng là 2 service độc lập, hợp đồng có thể tạo trước, và gắn mã khách hàng sau đó 1 quy trình độc lập khác, chả có gì ngăn cản lập trình viên không làm điều đó cả, và người thiết kế phần mềm phải tính toán các trường hợp ngoại lệ như thế như là 1 đặc tính phải có.
Đây chính là đặc điểm khiến cho microservice không phù hợp để áp dụng cho một số bài toán cần sự đồng nhất cao của dữ liệu và cần chặt chẽ của logic, nếu nó quá phức tạp, như bài toán cần tính chất transaction chắc chắn như banking, hoặc hệ thống thanh toán điện tử.

Ý kiến vậy thôi.

Sorry mình giờ mới trao đổi tiếp. Đúng như bạn nói, bản thân kiến trúc microservices là tách thành các module nhỏ. Và theo nguyên lý CAP (Consistency, Availability, Partition tolerance) thì chỉ 2 trong 3 yếu tố trên là đc đảm bảo trong 1 ứng dụng. Microservices thường đáp ứng 2 yếu tố A & P, còn yếu tố C về tính nhất quán thì ko đảm bảo dc. Nhưng nếu yêu cầu nghiệp vụ hệ thống chấp nhận Eventual Consistency – tức là cho phép độ trễ trong việc đồng bộ dữ liệu thì microservices vẫn đáp ứng đc. Với cách giải quyết phù hợp thì mình nghĩ microservices vẫn có thể áp dụng được vào các bài toán banking hoặc thanh toán điện tử. Ngoài ra một số hệ thống banking mình biết còn áp dụng mô hình CQRS – tách biệt phần ghi & phần đọc dữ liệu, cho phép có độ trễ nhỏ khi hiển thị thông tin thanh toán cho ng dùng.

Q:  Em chào anh Khôi ạ, hiện tại em có một dự án về bán hoa online tuy nhiên bên client yêu cầu kích thước của ứng dụng siêu nhỏ, vậy làm sao để dữ liệu không bị phân tán quá mức cần thiết ạ.

A: Anh chưa rõ câu hỏi của em lắm. Ứng dụng của e là ứng dụng web hay mobile, dữ liệu hiện tại phân tán như thế nào (lưu cả ở client lẫn server)? Em bổ sung thêm a sẽ tư vấn đc

Q: Anh có thể chia sẻ về những kinh nghiệm gặp khó khăn cũng như những giải pháp mà anh đã từng trải trong suốt quá trình sử dụng microservice. Có bài học nào a nhớ nhất k?

A: Khó khăn thì có nhiều đó em, a chia sẻ lại mấy cái gặp phải khi phát triển Bizweb:
– Thay đổi tư duy từ close source sang open source: trước đó team chỉ làm ASP.NET + SQL Server + Windows Server, còn lại gần như không áp dụng công nghệ gì khác. Sau đó thay đổi 180 độ sang các giải pháp open source: Java Spring, Netflix OSS, MongoDB, Nginx, Linux, Kafka, Docker…Mà trước đó gần như cả team chưa biết gì, tự học từ đầu hết. Sau 6 tháng ra được bản demo sản phẩm, 8 tháng ra mắt phiên bản chính thức.

– Việc vận hành, phát hiện & xử lý lỗi khó hơn nhiều: trước kia mô hình đơn giản, vận hành rất dễ, chỉ cần monitor mỗi con máy chủ web + máy chủ db là xong. Nhưng khi chuyển sang microservices thì nó là 1 hệ thống phân tán, phải xử lý mấy chục service, chạy trên nhiều máy chủ (vật lý & ảo hóa) khác nhau. Nói thật là nhiều khi gặp lỗi mất nguyên 1 ngày mới tìm ra được nguyên nhân 😀 Việc xây dựng hệ thống monitor dịch vụ là cần thiết và nên được đầu tư sớm.

– Phải luôn luôn học hỏi, nâng cao kỹ năng của dev & test: món này ko dành cho bạn nào lười học hỏi, các bạn sẽ nản ngay vì nó khá phức tạp. Anh nhận thấy sau 2 năm các bạn trong team kỹ năng phát triển rất nhanh & giỏi.

Q: Chào anh, anh chia sẻ giúp e những tài liệu hay về Microservices vs anh. Thank anh nhiều

A: Có 1 số nguồn e có thể tham khảo nhé:
http://microservices.io/
https://martinfowler.com/articles/microservices.html
http://www.slideshare.net/juminchoi/bizweb-microservices-architecture
https://www.nginx.com/blog/introduction-to-microservices/

Kinh nghiệm của a khi triển khai là cứ làm mô hình ban đầu đơn giản rồi upgrade nó dần dần.

Q: Anh Khôi cho em hỏi, làm thế nào để quản lý việc cập nhật dữ liệu một cách đồng bộ với nhiều bảng trong cơ sở dữ liệu trung tâm ạ ?

A: Ý em muốn nói đến là thực hiện distributed transaction trong microservices hả? Bên anh hiện tại đang tránh việc đó, nói chung đó là 1 cái khó. Anh Nghĩa bên Tiki có 1 buổi chia sẻ về distributed transaction thứ 7 vừa rồi, slide đây em: http://www.slideshare.net/NghiaLeMinh1/distributed-transaction-lastest-version

Q: Anh ơi, muốn test 1 service nhỏ trong khối microservice thì đôi khi phải yêu cầu chạy các services khác vì các services phụ thuộc dây chuyền với nhau. Vậy nên việc test sẽ trở nên rất khó khăn và anh có thể chia sẻ 1 vài hướng giải quyết được không ạ? Và nếu 1 mắt xích trong khối microservice thay đổi thì các mắt xích khác có thay đổi theo không? Và đến đây việc testing có còn khả thi?

A: Đúng là việc test trong hệ thống microservices là khá khó khăn. Về vấn đề môi trường thì cần phải có đủ các service chạy mới test được nên để test trên máy của dev là khá phức tạp. Bọn anh có 1 máy chủ dev ở công ty, trên đó chạy đủ các service (service discovery, api gateway, redis, kafka…). Các bạn có thể cấu hình project trên máy của dev sử dụng lại các tài nguyên đó, hoặc nếu máy bạn nào cấu hình tốt thì chạy full service.

Khi 1 service thay đổi thì các service liên quan cũng cần update theo, nó không khác gì việc phát triển ứng dụng thông thường. Tuy nhiên trong thiết kế thì bên anh tránh tối đa việc gọi chéo giữa các microservices. Để làm được thế thì việc phân tách Bounded Context cần đảm bảo.

Bên a cũng đang áp dụng automation test để test API. Test từng API 1 thì dễ, nhưng để test theo quy trình (gọi service A, lấy kết quả làm tham số đầu vào gọi sang service B, C) thì chưa tìm ra được công cụ nào làm việc đó. Thế nên chỉ còn 1 cách là sử dụng Selenium Webdriver để lập trình automation test thôi.

Q: anh cho e hỏi là từ dev lên CTO, mình cần “update” bản thân những mảng nào hay kĩ năng nào đặc biệt quan trọng k anh?

A: Căn bản 1 công ty cũng chỉ có 1 ông gọi là CTO nên câu hỏi này khó trả lời quá😀. Từ ngày DKT mới thành lập thì a đã là CTO rồi.
Nhưng nếu nói về hướng phát triển của 1 dev thì có thể đi theo 2 hướng:
– Trở thành chuyên gia: ít nhất là của 1 lĩnh vực nào đó, ví dụ DB Expert (MySql, SQL Server, Oracle), Software Architect, Enterprise Architect, Cloud Solution Architect. Cái này a nghĩ cần cày cuốc nhiều & cũng cần có tố chất chút.
– Trở thành quản lý: trưởng nhóm, trưởng phòng. Cần có các kỹ năng mềm về quản lý & giám sát công việc, xây dựng team.

CTO ở VN có lẽ là tổng hòa của cả 2 cái trên (R&D, định hướng công nghệ, hỗ trợ các đội giải quyết các vấn đề khó cả nhân sự lẫn kỹ thuật, xây dựng quy trình, giải đáp thắc mắc tâm sinh lý)

Q: Anh có thể giải thích nếu các dịch vụ nhỏ thiết kế phục thuộc vào nhau theo chuỗi. A gọi B, B gọi C, C gọi D. Nếu một mắt xích có giao tiếp API thay đổi, liệu các mắt xích khác có phải thay đổi theo không vậy anh ?

A: Về thiết kế microservices thì đây là 1 việc nên tránh:
Thứ 1 là nó tăng sự phức tạp của hệ thống lên nhiều (khó phát triển, khó debug), tăng sự phụ thuộc giữa các microservices. Để tránh việc đó thì cần phân tích bài toán nghiệp vụ thật kỹ để chia hệ thống ra các domain khác nhau, gọi là Bounded Context. Mỗi 1 microservices là 1 Bounded Context, và hầu hết mọi thao tác xử lý sẽ nằm trong microservices đó, ko phải gọi qua thằng khác.
Thứ 2 là ảnh hưởng performance do gọi chéo nhiều quá (tăng network latency)
Thứ 3 là khi thay đổi 1 microservices e sẽ phải sửa những microservices có gọi đến nó. Như vậy là mất đi khá nhiều ý nghĩa của việc triển khai microservices (loose coupling)

Q: Anh ơi, liệu Microservices có đúng trong đa số trường hợp bài toán? Có ngoại lệ nào hay không?

A: Ko có cái gì gọi là “one size fits all” cả em. Thế nên microservices cũng chỉ phù hợp với 1 số bài toán & cần đội ngũ phát triển có kỹ năng tương đối.
Áp dụng microservices sẽ giúp ích nhiều khi cần quan tâm 1 số vấn đề như:
1. Sản phẩm phát triển lâu dài
2. Xử lý lượng người dùng hoặc dữ liệu lớn
3. Scale team phát triển
4. Bảo mật mã nguồn
5. Đảm bảo phát triển liên tục (CI/CD), update tính năng này ko làm downtime tính năng kia

Ngoài ra thì đội ngũ phát triển cũng cần có kỹ năng khá & ham học hỏi.

Q: Chào anh, hiện tại thì làm thế nào để kiểm soát danh tính người dùng trong Microservice một cách đơn giản mà không bị phân tán dữ liệu ?

A:  Dữ liệu danh tính người dùng thì chỉ lưu ở 1 nơi thôi em, khi nào cần xác thực thì truy vấn vào đó.

Có 2 cách xử lý authentication & authorization trong microservices.
1 là xử lý tập trung: có thể để ở API Gateway hoặc có 1 microservices thực hiện việc authentication/authorization, các service khác sẽ gọi đến service đó để kiểm tra quyền.
2 là authentication/authorization trên mỗi microservices. Khi đó sẽ viết nó thành 1 thư viện dùng chung giữa các microservices. Việc update thư viện này cũng ko thường xuyên nên không gặp phải vấn đề.

Và bên anh đang áp dụng cách thứ 2, nó tránh việc phải gọi đến service xác thực quá nhiều. Em có thể tìm hiểu chi tiết hơn về giải pháp trong slide anh có share ở mấy comment khác đó

Cảm ơn anh Minh Khôi đã rất nhiệt tình giải đáp cho các các bạn fan của Topdev những thắc mắc liên quan đến Microservices.

Chúc các bạn dev nhiều thuận lợi trong công việc và cuộc sống.