Chia sẻ về Testing với hệ thống Microservices – Phần 1

Năm mới chúc mọi người có thật nhiều sức khỏe, an khang thịnh vượng, và sự nghiệp ngày càng thăng tiến


Đôi dòng tản mạn trước khi bắt đầu chuỗi bài viết, năm 2021 thì mình cũng không có nhiều bài viết lắm do 1 phần mình vừa mới thay đổi chỗ làm, và công việc cũng hơi nhiều. Bên cạnh đó thì cũng mong muốn trải nghiệm nhiều hơn về testing để có thể chia sẻ thêm cho các bạn những kinh nghiệm thực tế nhưng mà mình trải qua. Còn nói đơn giản hơn thì năm ngoái mình hơi lười 🤣 chủ yếu mình chỉ toàn post bài trên fanpage Facebook để chia sẻ vài mẹo nhỏ khi thực hiện testing. Hy vọng năm nay mình sẽ bớt lười lại và có nhiều bài viết hơn ở blog này 😮‍💨 Ví dụ như chuỗi bài viết sắp tới đây về Microservices là những kinh nghiệm và thực tế mình đã trải qua trong 1 năm vừa rồi, mình thấy có những cái hay ho có thể chia sẻ để mọi người cùng có thêm những thông tin thú vị 😄 ,vì là những kinh nghiệm do mình trải qua nên có những thứ nó sẽ được nhìn nhận ở khía cạnh từ quan điểm của mình, nên có thể các bạn có cách nhìn nào hay hơn có thể comment chia sẻ nhé 😉

Microservices là gì?

Trước khi bắt đầu chuỗi series bài viết này thì mình cũng muốn chia sẻ qua 1 tí về Microservices là gì và nó khác gì so với những kiến trúc xây dựng ứng dụng trước đây?

Đầu tiên thì phải nói tới thời xa xưa, thời mình còn là con nòng nọc, lúc các chú các bác bắt đầu có Internet, và phát triển những phần mềm ứng dụng cho người dùng. Khi đó thì việc xây dựng ứng dụng nó rất là đơn giản, nó như kiểu mình xậy dựng cái nhà cấp 4, đổ nền, dựng tường, lợp mái nhà, và thế là có cái nhà. Tương tự với nền tảng ứng dụng thì chúng ta có việc xây dựng persistent layer (lớp lưu trữ dữ liệu), business logic layer (lớp chứa các yêu cầu và cách mà ứng dựng hoạt động), và cuối cùng là presentation layer (nơi hiển thị thông tin cho người dùng), ví dụ như bạn có nhu cầu xây dựng 1 ứng dụng cho phép hiển thị hình ảnh trai xinh gái đẹp, khi đó đầu tiên bạn cần persistent layer để chứa hình ảnh trai xinh gái đẹp, bạn cần có business logic để cho phép thêm, xóa hoặc chỉnh sửa hình ảnh, cũng như hiển thị hình ảnh, bạn cần presentation layer để hiên thị hình ảnh đó cho user xem trên bất kỳ nền tảng nào chẳng hạn. Với việc xây dựng ứng dụng theo cách trên thì ta gọi nó là Monolithic Architecture.

Let’s do some magic
Monolithic Architecture

Rồi thì con người cũng phải phát triển và tiến bộ hơn 🤔 từ xe bò ta lên xe ngựa, từ xe ngựa ta lên xe động cơ đốt trong và dần dần thì ta có chiếc xe hơi xịn xò như ngày hôm nay. Tương tự cho ngành công nghệ phần mềm, điều đó cũng xảy ra, từ 1 ứng dựng đơn giản chỉ click, click rồi hiển thị thông tin, ta có thêm nhiều yêu cầu hơn, ta có thêm nhiều tính năng hơn cho ứng dụng đó. Và dần dần từ Monolithic Architecture ta có Service-oriented Architecture và cuối cùng là Microservices Architecture.

Trở lại ví dụ ban đầu ở trên ứng dụng hiển thị trai xinh gái đẹp, ban đầu mình chỉ có nhu cầu hiển thị hình ảnh trai xinh gái đẹp nên ứng dụng khá đơn giản. Sau 1 thời giản ứng dụng được đưa vào hoạt động thì lại có nhu cầu mở rộng thêm như cho phép hẹn hò, cho phép đặt chỗ khách sạn hay mua vé xem phim cũng như quẹt trái quẹt phải, mua gói premium chẳng hạn, rồi bùm chúng ta có ứng dụng Tinder 😛 Khi đó thì việc tiếp tục duy trì với Monolithic Architecture hoàn toàn khả thi, chỉ là nếu tiếp tục có thêm nhiều tính năng hơn nữa thì khi đó ứng dụng sẽ trở nên khá lớn, dẫn tới việc khó bảo trì hay mở rộng thêm tính năng, ngoài ra thì khi cần thay thế hoặc nâng cấp bất cứ thứ gì nhỏ nhất bên trong ứng dụng đều tiềm ẩn những rủi ro liên quan tới mức độ phụ thuộc và độ tương thích với toàn thể ứng dụng, ví dụ như nâng cấp phiên bản thư viện nào đó trong business logic layer. Từ những vấn đề nêu trên thì dần dần phát triển ra SOA và Microservices Architecture, 2 kiến trúc trên ra đời để giải quyết những vấn khó khăn gặp phải Monolithic Architecture khi ứng dụng càng ngày càng phát triển và mở rộng hơn. Vậy SOA và Microservices Architecture khác gì so với Monolithic Architecture 🥺

Cả Service-oriented Architecture và Microservices Architecture, thì ta đều có bước chuyển đổi dần trong việc chia tách những tính năng của ứng dụng thành những module nhỏ hơn. Lúc này ứng dụng sẽ được chia nhỏ ra thành những services và mỗi services chỉ phục vụ 1 business logic cụ thể, như ví dụ ở trên lúc này khi mình muốn thêm tính năng đặt phòng khách sạn hay vé xem phim thì mình sẽ có riêng 1 service cho phần này, khi đó nếu mình có thay đổi hay làm gì đó thì những tính năng trước như thêm xóa sửa hình hoặc mua gói premeium sẽ không bị ảnh hưởng gì cả.

Vậy lợi ích của 2 kiến trúc này so với Monolithic là gì? Rõ ràng khi bạn chia tách những tính năng ra thành những module/service riêng biệt thì việc phát triển hay mở rộng ứng dụng sẽ trở nên dễ dàng hơn. Bên cạnh đó việc thay thế module/service cũng sẽ không quá phực tạp, ví dụ như mình có module/service đặt vé xem phim với CGV, giờ đùng 1 phát CGV ko muốn hợp tác nữa thì việc mình thay thế đặt vé xem phim với Lotte cũng được thực hiện 1 cách dễ dàng và không ảnh hưởng nhiều tới các services khác. Ngoài ra còn vài lợi ích khác so với Monolithic như việc mở rộng ứng dụng sẽ đơn giản hơn do lúc này mình có thể mở rộng ở mức module/service, ví dụ sau 1 năm users của ứng dụng mình tăng lên từ 100 người lên 1tr người và phần lớn toàn vô để đặt khách sạn hoặc vé xem phim, khi đó việc mở rộng module/service liên quan tính năng trên cũng sẽ dễ dàng hơn so với Monolithic, do với kiến trúc Monolithic thì khi mở rộng lên thì mình cần triển khai toàn bộ ứng dụng, dẫn tới có những phần không cần thiết phải mở rộng lên nhưng vấn được “khuyến mãi” kèm theo, và kéo theo cost sẽ không được tối ưu. Bên cạnh đó nó còn có những ưu điểm khác nữa, mọi người có thể coi thêm ở Microservices Architecture.

Vậy SOA hay Microservices Architecture nó quá hoàn hảo và không có nhược điểm gì cả? 😩 Rất tiếc là ông trời không cho cái gì hoàn hảo cả, với những ưu điểm như mình có nói sơ qua ở trên thì nhược điểm của 2 kiến trúc trên cũng có khá nhiều, ví dụ như mức độ phức tạp khi phát triển cũng như testing. Tính thống nhất giữa các services khi thực hiện communicate với nhau (data, integration, etc.) và nếu phát triển 1 hệ thống theo hướng SOA hay Microservice mà không có tính thống nhất cao (contract giữa các service, bounded context rõ ràng) thì chúc mừng team các bạn, các bạn đã quay trúng ô “1 mớ rác hỗn độn” hay còn gọi là microservice chaos, lúc này nó còn tệ hơn Monolithic Architecture 🥲

Nhìn chung 2 architectures này không quá khác biệt về mặt phylosophy, và ở mức độ bài viết của lần này thì mình cũng sẽ không đề cập quá chi tiết về sự khác biệt của 2 kiểu kiến trúc này. Nhìn chung cả 2 kiến trúc trên đều hỗ trợ nhà phát triển trong việc phát triển 1 ứng dụng khi nó bắt đầu trở nên lớn hơn, có nhiều tính năng hơn, cũng như phức tạp hơn.

Theo quan điểm của mình thì việc vận dụng hoặc lựa chọn 1 trong 3 kiến trúc này sẽ phụ thuộc khá nhiều vào nhu cầu của ứng dụng cũng như mô hình kinh doanh, không có cái nào vượt trội hơn hẳn cả, mọi cái đều có ưu điểm và nhược điểm của mình. Riêng về SOA và Microservices Architecture bạn nào quan tâm thì có thể đọc thêm bài này để rõ hơn về sự khác nhau giữa 2 kiến trúc này cũng như những ưu điểm và nhược điểm của nó SOA vs Microservices Architecture, vì nhìn qua thì 2 kiến trúc này khá tương đồng nhau 🤣

Những khó khăn trong việc testing với Microservices Architecture

Giờ thì chuẩn bị vô phần chính của chuỗi series blogs này của mình 🤠 Như mình đã giới thiệu ở trên, từ mô hình Monolithic chuyển sang SOA hay Microservices hay thì nó có những sự khác biệt cơ bản, và dẫn tới khi thực hiện testing cũng có những vấn đề cần giải quyết xung quanh đó, dưới đây là những vấn đề mà trong cả năm qua mình đã trải nghiệm cũng như giải quyết nó, và ngoài ra cũng có những vấn đề mình chưa giải quyết xong dự định năm nay sẽ ráng “xúc” nó luôn 🙄

  • Làm sao để nhận diện sự ảnh hưởng hoặc mức độ phụ thuộc lẫn nhau giữa các services khi document không đầy đủ hoặc bị outdated
  • Làm sao để có thể tìm hiểu về cả hệ thống từ view end-user đi xuống tới mức services, mình hay gọi cách này là top down approach
  • Làm sao để thực hiện việc testing hiệu quả khi có hơn gần 60+ services trong cả hệ thống, giải quyết bài toán mỗi lần service deploy new version và thực hiện regression testing thế nào
  • Làm sao để thực hiện việc automation checking cho hệ thống microservices, bao gồm cả việc rút gọn thời gian run automation cho toàn bộ test suites chỉ dưới 10-30 phút cũng như chiến lược cho việc thực hiện automation checking
  • Làm sao để thực hiện performance testing cho service khi nó có quá nhiều dependency services
  • Làm sao để thực hiện việc shift-right testing đối với 1 hệ thống lớn khi có new release quan trọng lên production
  • Làm sao để thực hiện việc testing distributed transaction trong hệ thống này

Như cái danh sách ở trên thì đó là 1 trong những vấn đề chính mà mình đã gặp phải trong cả năm vừa qua, có những cái mình đã xử xong, và cũng có những cái gọi là technical debt hy vọng năm nay xử tiếp 🤐 Trong chuỗi bài viết này thì các phần kế tiếp mình sẽ chia sẻ kinh nghiệm, trải nghiệm cũng như cách mình đã sử dụng để giải quyết dần những vấn đề trên. Đầu năm chắc mở hàng tới đây thôi, để dành cho phần tiếp theo thôi 👻

Hướng dẫn sử dụng plugin InfluxDB và LOKI với jmeter

JMeter Real-Time Monitoring, Integration With Grafana+InfluxDB 2.0 (Flux) -  DZone Integration

Bạn nào từng làm performance test (hay còn gọi là load test, mặc dù mình ko thích cách gọi này lắm do load test chỉ là 1 phần của performance test =]]) thì thường sẽ gặp phải những vấn đề như: làm sao để có thể theo dõi kết quả chạy load test 1 cách trực tiếp? Làm sao để lưu trữ dữ liệu load test và so sánh nó với những thông số khác theo trục thời gian (HTML report thì bạn rất khó để xác định được chính xác mốc thời gian với điểm nghi ngờ bị performance và đi kiểm tra với các thông số của hệ thống). Hay thậm chí là so sánh kết quả thực hiện load test hiện tại với các mốc thời điểm 1-2-3-4-…. tháng trước? Hay thậm chí là cách nào đó để lưu trữ những dữ liệu của response data khi thực hiện load test 1 cách hiệu quả?

Từ những điều khó khăn trên mà mình gặp phải dẫn tới việc nhóm mình trong lúc rảnh rỗi đã viết 1 plugin trên JMeter để giải quyết vấn đề trên.

yay yay yay

Hướng dẫn cài đặt

Việc đầu tiên là các bạn cần vô link này nhấn like và follow (mình đùa thôi nhưng nhớ làm cũng được :D). Các bạn vô link này download plugin về (cái file để download như hình dưới đây)

Plugin download

Sau khi download xong file đó thì các bạn giải nén nó ra và copy file “jmeter-backend-listener-plugin.jar”

vô thư mục lib/ext (thư mục này nằm trong folder các bạn đã cài đặt JMeter)

Như vậy thì việc cài đặt plugin đã hoàn toàn xong =)) nói chung nó dễ đến mức không còn có thể dễ hơn được nữa

Hướng dẫn cấu hình plugins với JMeter

Sau khi đã cài đặt plugin xong thì đến bước cấu hình để sử dụng plugin, việc cấu hình plugin cũng rất là đơn giản như những bước dưới đây

Đầu tiên là các bạn cần phải mở JMeter lên rồi, =)) không mở lên thì lấy cái gì mà cấu hình hay sử dụng đúng ko nào =)). Sau đó các bạn tạo 1 thread-group bất kỳ. Sau 2 bước trên các bạn sẽ có 1 structure của JMeter như hình sau

Kế tiếp các bạn tạo tiếp 1 “backend listener” element trong JMeter theo như hình sau

add-listener-to-testplan

Sau khi add xong thì các bạn sẽ có structure của JMeter test plan như hình sau

Giờ thì đến bước cấu hình cho listener plugin, để cấu hình cho plugin thì bạn click vô “Backend listener” element và chọn 1 trong 2 options sau (mỗi option tương ứng cho việc bạn sẽ send JMeter metrics hoặc JMeter response data vô InfluxDB hoặc Loki)

select-listener

Sau khi chọn xong loại backend listener thì các bạn cấu hình thông số cho nó

config-influxdb-listener
InfluxDB Backend Listener Configuration
config-loki-listener
Loki Backend Listener Configuration

Để hiểu rõ từng options trong configuration thì các bạn có thể coi thông tin chi tiết ở link sau

Lưu ý: Nếu bạn muốn dùng cả InfluxDB và Loki thì bạn chỉ cần add 2 “backend listener” vô JMeter test plan, nhưng lưu ý là nhớ đổi tên cả 2 element, do cơ chế của JMeter là sẽ broad cast cái sampler result vô từng listener theo element name của chính nó, nên khi bạn add 2 element thì nó sẽ bị trùng tên (default name của backend listener)

Done !!!!!!!!!

Kế tiếp thì các bạn sẽ cần làm thêm 1 bước là import dashboard Grafana mà bọn mình đã xây dựng sẵn cho plugin của bọn mình. Các bạn download template ở link sau. Kế tiếp là import nó vô Grafana (bạn nào chưa biết cách import Grafana dashboard thì Google dùm mình nha =)) mình assume là ở đây mọi người đều có mạng internet và có thể truy cập được Google để tìm kiếm thông tin). Bên cạnh đó các bạn cũng cần phải cài đặt InfluxDB, LokiGrafana (các bạn có thể coi cách cài đặt những cái đó ở link mình đính kém theo cái tên của nó)

Sau khi xong hết những cái đó thì chạy thử JMeter test và tận hưởng thành quả hoy

i1
i3
l4
l3

Những câu hỏi thường gặp khi sử dụng plugin

1. Sử dụng plugin này có làm ảnh hưởng tới kết quả performance test không?

Trả lời: Plugin sẽ không ảnh hưởng tới kết quả performance test

=> Giải thích: Cơ chế của backend listener của JMeter là khi JMeter thực hiện 1 request lên SUT/AUT (system under test/application under test) thì kết quả của JMeter request đó sẽ được truyền vô plugin listener ở 1 thread riêng. Hiểu nôm na thì JMeter sẽ có 2 thread riêng khi bạn sử dụng plugin này, 1 thread sẽ chỉ chuyên làm nhiệm vụ thực hiện việc gởi những request lên hệ thống bạn test, và 1 thread làm nhiệm vụ gởi kết quả lên InfluxDB hay Loki. Với cơ chế này thì nếu bạn đang thực hiện performance test mà InfluxDB hay Loki có bị chết thì việc thực hiện load test vẫn sẽ tiếp tục diễn ra chứ không bị gián đoạn, ngoài ra nếu việc send dữ liệu lên hệ thống collect metrics bị chậm thì cũng sẽ ko ảnh hưởng tới kết quả performance test.

2. Sử dụng plugin rồi nhưng có tính trạng bị treo máy Master khi run performance test ở chế độ distributed?

Trả lời: Plugin không có lỗi, lỗi là do cơ chế nhận sampler result ở JMeter khi run ở mode distributed =))

=> Giải thích: khi các bạn run performance test với JMeter ở chế độ “Distributed” (hay còn gọi là kiểu master và slave, việt hóa là ông chủ và những nô lệ =]]). Thì cơ chế của JMeter máy master sẽ làm nhiệm vụ truyền lệnh run cũng như send *.jmx file (hay còn gọi kịch bản test) xuống những máy slave. Việc thực hiện gởi những request lên hệ thống test sẽ do những máy slave làm, sau đó thì kết quả sẽ được gởi về lại máy master. Và thường vấn đề gây treo máy nó nằm ở đây. Do khi thực hiện cơ chế này nhiều bạn mắc 1 sai lầm là physical machine (hiểu nôm na là máy dùng để chạy JMeter) đang run Master cũng là máy sẽ run Slave, khi đó physical machine đó sẽ bị quá tải ở cả Memory/CPU/Network và dẫn tới treo máy. Để hạn chế tình trạng trên thì tốt nhất mỗi máy master và slave các bạn nên run nó trên những physical machine riêng biệt. Ngoài ra thì bạn có thể vô file jmeter.properties (nằm trong folder bin) để cấu hình cơ chế mà những máy slave sẽ send kết quả về cho master như hình dưới đây:

3. Sử dụng plugin nhưng khi thực hiện query hoặc load kết quả lên Granafa rất chậm?

Trả lời: Cuộc sống thì cái này nằm ngoài phạm vi của plugin rồi

=> Giải thích: Do cơ chế lưu trữ của InfluxDB như cơ chế chia table/shard (nó tương tự cơ chế index ở bên mấy database dạng SQL) sẽ dẫn đến việc khi bạn load dữ liệu lên Grafana nó sẽ mất thời gian để query những thông số theo nhu cầu, ngoài ra thì việc sử dụng regex nhiều quá cũng ảnh hưởng tới thời gian Grafana lấy được dữ liệu từ InfluxDB

Mobile app performance Testing with Apptim

Recently I’ve found a tool called APPTIM. This tool is a nice addition to your performance testing on mobile devices providing a bunch of useful features to help visual performance metrics as well as collecting related logs.

This blog is a quick starter guide to help you jump in this tool. I won’t talk about fancy things regards to how important of performance testing, why performance testing is needed etc

To get started and record the session, refer to this guide

The performance bottlenecks

Upon a session is ended, you are presented into a summary screen to have a quick brief about how the application performed on the specific device. Noticable summary information are:

  • % CPU Usage
  • Avg Memory Usage
  • % Memory Usage
  • Power Usage
  • Downloaded Data
  • Errors/Exceptions if any

Visualize performance metrics

Performance testing artifacts always end with of visualized metrics. APPTIM support many common metrics which is parsed from based on dumpsys command. APPTIM actually aggregates ALL the data and round up into a friendly visualization.

  • CPU
  • Threads:
  • Memory:
  • Database:

Besides database visualize metric, APPTIM also list out the transaction performed internally in the database’s application. It also points out the WORST transaction (most spent time in ms) to perform

  • Power Usage:

All above metrics are parsed from dumpsys output command, which is nice because you will envision yourself into friendly metrics rather than a bunch of raw numbers

Logs

As said from the beginning, all logs including crash, power usage, memory dump, network…. (well so many) are also collected and presented in the local report. Those are all raw logs and bestow for you to dig in more information if you need to debug performance bottlenecks if you can’t seem to figure out from the metrics

—————————————————————————————————————————————————————–

Above are common features for a performance testing tool to record metrics and logs related. BUT APPTIM does more than that:

  • Provide activities and layout correctness (Android only): How activities and layouts are used in term of performance determinations. They help mainly developers to determine whether the application need to be adjusted to improve performance as activities and layout is important factors
  • Integrate with Jira: You can gather a piece of information from the session and send them directly to JIRA.
  • Support exploratory testing: The pros of APPTIM is logs , metrics and misc information collection. That’s why APPTIM supports the ability to take note during the session so that if any bugs found you will have all the needed pieces.
  • Support BOT testing: I think it’s coming soon.
  • Collaboration: The generated report is also pushed to your workspace. Workspace in APPTIM is your own private page which you can take part in to view the all of previously reports, not just a current one. With paid subscription, collaboration happens by inviting more of your colleagues to

Automation Testing
So does APPTIM support using it for automation testing? So far as I’ve tried, the supports of automation testing tied to local devices and AWS farm.

  • Local devices & emulators: Once your session is started, you just need to execute your tests. APPTIM collect performance information, so the automation session works along with this nicely. At the end of automation session, APPTIM also ends it session and performance testing will be collected
  • AWS farm devices: Blazemeter conducts an article regards to using APPTIM directly in their Taurus scripts, you can refer here

I will contact more with APPTIM regards to their automation support and APPTIM native scripts and write another article later about this

Summary:

Pros:

  • A all-in-one performance collection
  • Required dependencies are installed automatically
  • Support collaborations through public APPTIM cloud
  • Compare two sessions (paid)
  • Support JIRA integration
  • Provide useful correctness regards to activities and layouts on Android
  • All performance, logs, device and extensive information are delivered to you
  • Support automation testing

Cons:

  • Automation testing support still limited
  • The workflow to really start the session is cumbersome a bit

So far I’m liking this tool. It’s a nice addition to help you to start performance testing locally on the devices.