Unicorn vs. Puma vs Passenger 5: App Server nào phù hợp với bạn?

 Dec-28-2020 04:45 PM
#news
Có khoảng 3 hệ thống các app server của Ruby nổi bật nhất đó là: UnicornPuma và Passenger 5. App server nào để giải quyết những vấn đề cụ thể cho Ruby? Làm thể nào để chọn đúng app server cho ứng dụng của bạn? Trong bài viết này, chúng ta sẽ cùng lướt qua những sự khác biệt của 3 app server này và bạn sẽ có câu trả lời riêng cho mỗi hệ thống của mình.

Tốc độ thực tế của app server quan trọng như thế nào?

Trước hết, chúng ta cần biết, tốc độ thực tế của app server quan trọng như thế nào? Tốc độ thực tế của app server là yếu tố chúng ta hầu như không quan tâm lắm khi xây dựng một hệ thống. Thời gian thực hiện code, truy vấn cơ sở dữ liệu và các request HTTP có khả năng làm giảm sự chênh lệnh về thời gian respone giữa các app server có thể tính đến micro giây hoặc mili giây. Chúng ta sẽ không cần quan tâm quá nhiều tới các số liệu về hiệu suất được công bố chuẩn, đặc biệt là các yếu tố dẫn đến crash server do hàng trăm request đồng thời do sự tấn công từ hacker vì nó là yêu cầu cần thiết đối vợi mọi ứng dụng web. Nếu xét trong hệ quy chiếu này, Unicorn, Puma và Passage đều rất nhanh cho hầu hết các ứng dụng Ruby.

Điều cần quan tâm tiếp theo là gì?

Một ứng dụng web được chạy dựa trên các thành phần: phần mềm, phần cứng và mạng. Cho dù những ứng dụng production có băng thông cao đi chăng nữa thì chúng vẫn có lỗi xảy ra hằng ngày như truy vấn vào cơ sở dữ liệu mất 30s hay một request API HTTP mất đến hơn 60s. Điều quan trọng là phải phát hiện và cô lập các lỗi này càng sớm càng tốt. Hệ thống các app server của Ruby đã phát triển giúp giảm thiểu sự tác động của những sự cố thường xuyên xảy đến cho một ứng dụng web của bạn. Hãy cùng xem các vấn đề thường xuyên gặp phải và cách các app server giúp chúng ta ngăn chặn các sự cố đó.

1. Slow clients

Chúng ta muốn tải ảnh ASAP lên ứng dụng web của mình với một hastag nào đó. Không may, đường truyền mạng không ổn định và khiến tốc độ upload bị giảm đáng kể. Làm sao để app server của bạn xử lý được việc mạng của client chậm? Việc xử lý một request của máy khách chậm có làm ảnh hưởng tới việc app server tiến hành các công việc khác hay không?

Trong hệ thống các app server, cả Puma và Passenger đều có thể xử lý được việc client có tốc độ chậm. Trong khi Unicorn thì không thể handle được việc này mà phari thực hiện thông qua các worker. Tài liệu Unicorn nói rõ: "Bạn không nên cho phép unicorn chịu trách nhiệm cho client ở bên ngoài mạng local của mình" Tuy nhiên, bạn có thể khắc phục bằng cách sử dụng Ngĩn làm proxy nguợc và để nó ghi đệm lại yêu cầu của client.

2. Slow apps

Đặt trường hợp, chương trình của bạn đang xử lý một logic khá phức tạp. Điều gì sẽ xảy ra với các request đang cố gắng truy cập vào ứng dụng của bạn trong khi server đang xử lý đoạn code này?

Nếu ứng dụng của bạn chạy Ruby MRI, và ứng dụng này phải tuân theo các chuẩn của toàn cầu về việc lock request, thì chỉ có một thread duy nhất trong việc xử lý của Ruby có thể thực thi đoạn code của bạn bất cứ lúc nào. Để thực hiện nhiều request hơn, app server của bạn cần hỗ trợ Clustering: sinh ra nhiều tiến trình để thực hiện code trên cùng một máy chủ để thực hiện các request.

Puma, Passenger và Unicorn đề hỗ trợ clustering.

3.Slow I/O

Trong trường hợp bạn có quá nhiều bản ghi trong cơ sở dữ liêu (khoảng 10k bản ghi) mà bạn lại quên giới hạn số lượng bản ghi trả về trong 1 lần request, các request khác cần truy cập vào để truy vấn cơ sở dữ liệu có bị chặn không, kể cả trong trường hợp server không thực hiện bất cứ công việc nào?

Mặc dùng clustering cũng có support việc truy suất chậm, nhưng nó cũng không quá hiệu quả vì:

  • Một tiến trình đơn của Rails sử dụng 1 lượng bộ nhớ đáng kể (khoảng 100MB) nhưng mỗi thread bổ sung bên trong tiến trình đó chỉ chiếm 1 phầm nhỏ (chưa tới 1MB)
  • Phần lớn các app server bị hạn chế về bộ nhớ và thêm nhiều tiến trình chỉ đẩy bạn đến gần hơn với giới hạn đó mà thôi.

Cách hiệu quả nhất để giải quyết việc truy suất chậm đó là multithreading (đa luồng). Một tiến trình của worker sinh ra một thread worker bên trong nó. Mỗi request đưuọc xử lý bởi một trong các thread đó, nên khi có 1 thread tạm dừng để truy suất (VD truy cập cơ sở dữ liệu) thì một thread khác sẽ bắt đầu công việc của nó. Việc luân phiên này giúp chúng ta tận dụng tối đa giới hạn của RAM và giữ cho CPU hoạt động hết công suất.

Puma là lựa chọn open source duy nhất cho phép xử lý đa luồng. Passenger bản Enterprise cũng hỗ trợ cung cấp multithread. Unicorn thì lại không hỗ trợ đa luồng.

Multiple Process và Multithread giúp loại bỏ các vấn đề về hiệu suất code và truy suất.

Tóm lại, một host độc lập phục vụ cho ứng dụng code Ruby cần 2 diều để cung cấp cho người dùng trải nhiệm tốt nhất:

  • Multiple process: host của bạn có thể chạy code Ruby trên nhiều request đồng thời
  • Multithread: host của bạn có thể sử dụng bộ nhớ hiệu quả hơn khi chờ I/O

Nếu không có Multiple process, ứng dụng của bạn sẽ bị tắc nghẽn khi thực thi code Ruby vì một luồng chỉ xử lý một đoạn code trong 1 thời điểm. Nếu không có đa luồng, ứng dụng của bạn có thể bị chậm do phải chờ I/O.

Puma và Passenger bản Enterprise có thể cung cấp multiple processes (clustering) và thự hiện đa luồng. Unocorn và Passenger chỉ hỗ trợ clustering mà thôi.

Điều gì xảy ra nếu ứng dụng của bạn không an toàn?

Có thể bạn chưa biết nhưng bạn không thể sử dụng đa luồng nếu ứng dụng của bạn không an toàn. Trong trường hợp này, Puma, Unicorn, and Passenger đều có thể hoạt động được. Với Puma, bạn có thể sẽ chỉ cần limit số lượng tiến trình woker trong 1 thread. Sau đó thì nó hoạt đồng như Unicorn hoặc Passenger phiên bản miễn phí.

App server nào chúng ta nên sử dụng?

Sau rất nhiều phân tích, tổng kết lại thì chúng ta nên sử dụng app server nào?

Unicorn

Dù không có multithread và phải phụ thuộc vào Nginx cung cấp bộ nhớ đệm cho các request, nhưng Unicorn vẫn được sử dụng khá phổ biến. Nó phù hợp nhất với các ứng dùng không an toàn và chỉ phải xử lý các vấn đề liên quan tới việc xử lý chứ không liên quan tới tốc độ của client. Tuy nhiên thì thực ra cũng k có sự khác biệt lắm giữa Passenger và Puma trong trường hợp này. vậy tại sao lại sinh ra các app server khác?

Passenger

Passenger được tạo ra theo sát với Ruby từ năm 2008. Ngoài Ruby ra thì nó cũng chạy cho các ứng dụng Python, Node.js và Meteor. Passenger là lựa chọn phù hợp khi:

  • Ứng dụng của bạn phát triển bằng nhiều ngôn ngữ mà Passenger hỗ trợ và bạn muốn hợp nhất các stack trong server.
  • Bạn sẵn sàng chịu rủi ro cho ứng dụng. Passenger bản Enterprise hỗ trợ nhiều lựa chọn hơn trong TH có rủi ro bằng: tài liệu, cấu hình hay các công cụ gỡ lỗi hoặc hỗ trọ đặc biệt

Passenger ít phù hợp khi:

  • Bạn chỉ có duy nhất code Ruby
  • Bạn không muốn mất tiền để trả cho server
  • Ứng dụng của bạn hoạt động trong môi trường bị giới hạn về bộ nhớ (như Heroku) và không thể đồng thời thêm I/O qua các luồng

Puma

Lý do khiến Puma trở thành app server được sử dụng rộng rãi nhất (đặc biệt là ămcj định cho Rails và Heroku) là: dễ cấu hình và có thể hoạt động một cách linh hoạt.

So sánh tính năng của Unicorn, Passenger 5, and Puma

  UNICORN PUMA PASSENGER 5
Clustering yes yes yes
Multithreaded no yes Enterprise Only
Slow client buffering no yes yes
ActionCable yes yes yes
Support Open Source Open Source Open Source/Paid
Installation Gem Gem Binary or Gem
Zero-Downtime Deploys yes yes Enterprise

Nguyễn Thùy Dương

Hỗ trợ trực tuyến
Online Offline
Hỗ trợ trực tuyến