Unix socket, “ma tốc độ” thường bị lãng quên

Nếu bạn có từng để ý rằng, webserver kết nối tới PHP-FPM ở cổng 9000, PHP kết nối với MySQL ở cổng 3306, hay kết nối với Redis ở cổng 6379, Memcache ở cổng 11211. Tuy nhiên, còn một cách kết nối khác ít được biết đến đem lại khả năng tăng tốc hơn 50% so với TCP/IP, đó là sử dụng Unix socket.

Nếu bạn đang sử dụng VPSSIM hoặc HocVPS hoặc CentOS, hãy đọc qua bài này để biết Unix socket là gì và chuyển sang Phần hai: Hướng dẫn cài đặt trên VPSSIM / HocVPS để dễ thực hiện theo nhé.

Unix socket là gì?

Unix socket là một điểm giao tiếp để trao đổi dữ liệu giữa các ứng dụng trên cùng một máy tính. Khác với giao thức TCP/IP thực hiện ở giao thức mạng, Unix socket thực hiện ở nhân hệ điều hành, nhờ vậy có thể tránh được cách bước như kiểm tra hoặc routing, đem lại tốc độ kết nối nhanh hơn và nhẹ hơn so với TCP/IP.

Ưu điểm của Unix socket

Thật là đơn giản để chứng minh bằng các bài benchmark để dụ dỗ các bạn chuyển sang sử dụng Unix socket:

Unix socket giúp tốc độ truy cập MySQL tăng 30-50% hay giảm latency từ 60ms xuống còn 5ms, còn nữa PostgreSQL tăng hơn 30%Redis tăng 50%,… so với TCP/IP.

Những con số đó có làm các bạn trầm trồ chưa? Và cũng thật là thiếu sót nếu chỉ đưa ra lời khen, mà bỏ qua đi một số nhược điểm của Unix socket.

Nhược điểm của Unix socket

Nhược điểm cố hữu và không thể khắc phục của Unix socket là hai ứng dụng chỉ có thể kết nối với nhau trên cùng một máy chủ. Không thể kết nối hai ứng dụng bằng kết nối Unix socket nếu chúng ta có dự định scale ứng dụng ở nhiều máy chủ khác nhau, kể cả private network.

Thêm nữa, Unix socket thực chất là một “tập tin” trên máy chủ, nên đôi khi chúng ta sẽ gặp vấn đề về phân quyền. Tuy nhiên, mình rất ít khi gặp vấn đề này và có vẻ nó cũng an toàn hơn khi lỡ public các cổng của ứng dụng ra ngoài internet 😉

Nếu các bạn không scale, không phân chia ứng dụng web ra làm nhiều phần, database và webserver riêng thì không có gì phải đắn đo. Chuyển sang socket là điều nên làm.

Bài viết này sẽ hướng dẫn các bạn cấu hình các loại phần mềm sau:

Cách sử dụng Unix socket

Trong một buổi sáng thứ Bảy đẹp trời hôm nay, mình tiến hành nâng cấp các ứng dụng trên máy chủ và cũng cố gắng chuyển sang Unix socket tất cả có thể. Và bạn đoán xem, chỉ tốn khoảng 15p để Tuấn chuyển PHP, MySQL, WordPress,… sang Unix socket. Đó là vì các ứng dụng đa số đã hỗ trợ rồi, bạn chỉ việc thay đổi cấu hình từ TCP/IP sang Unix socket thôi.

Có downtime! Những thay đổi này sẽ khiến website bạn down trong khoảng 30s – 1 phút. Vì vậy, nếu website quan trọng, hãy đọc hết bài viết thật kĩ rồi mới tiến hành thay đổi.

Nên thực hiện theo thứ tự này để đảm bảo downtime ít nhất có thể bạn nhé.

MySQL

Thông thường MySQL đã chạy sẵn ở TCP và Unix socket rồi nên chúng ta không cần cấu hình hay khởi động lại gì cả. Tuy nhiên, để chắc chắn, hãy chạy lệnh sau để kiểm tra xem MySQL có đang LISTEN bằng Unix socket hay chưa:

netstat -ln | grep "unix.*mysql"

Nếu trả về kết quả như hình trên thì quá đơn giản, hãy thay đổi source code của website để kết nối bằng Unix socket thay vì TCP.

Với WordPress, hãy mở tập tin wp-config.php và thay đổi dòng:

define('DB_HOST', 'localhost');

thành đường dẫn socket của MySQL vừa tìm được ở trên:

define('DB_HOST', 'localhost:/var/run/mysqld/mysqld.sock');

Vậy là xong. Bạn thử truy cập vào website WordPress của bạn xem có hoạt động không nhé. Để chắc chắn WordPress đang kết nối MySQL bằng socket, hãy cài plugin Server Info và xem ở Settings > Server Info.

Redis

Nếu bạn không sử dụng Redis có thể bỏ qua phần này.

Đối với Redis thì chúng ta có thể chạy song song TCP và socket nên bạn cũng không phải lo lắng rằng sẽ bị ảnh hưởng đến website. Hãy mở tập tin /etc/redis/redis.conf và tìm, chỉnh sửa hai dòng bên dưới nhé.

unixsocket /var/run/redis/redis.sock
unixsocketperm 777

Sau đó khởi động lại bằng lệnh service redis-server restart và tiếp tục một số chỉnh sửa để WordPress và Nginx có thể kết nối tới. Nếu đang sử dụng plugin Redis Object Cache để kết nối WordPress tới Redis, hãy chèn 2 dòng bên dưới vào tập tin wp-config.php:

define('WP_REDIS_SCHEME', 'unix');
define('WP_REDIS_PATH', '/var/run/redis/redis.sock');

Nếu đang sử dụng Nginx kết nối tới Redis, hãy tiếp tục thực hiện những bước khác và thay đổi đường dẫn socket của Redis ở phần cấu hình Nginx. Khi đã hiện dòng chữ Status Connected với Path là đường dẫn của tập tin socket có nghĩa là chúng ta để kết nối thành công.

Trang quản lý của plugin Redis Object Cache.

Tiếp tục kiểm tra một lần nữa, hãy chắc chắn rằng WordPress đang đọc và ghi tới Redis bởi socket bằng câu lệnh:

redis-cli monitor

Chúng ta sẽ thấy đường dẫn tới tập tin socket thay vì 127.0.0.1:6379 như trước.

PHP-FPM

Việc chuyển từ TCP qua Unix socket với PHP-FPM là rất dễ. Bạn chỉ cần truy cập vào đường dẫn /etc/php/7.2/fpm/pool.d/ và chỉnh sửa tập tin www.conf.

Chỉnh sửa dòng bên dưới (cổng 9000 có thể khác nhau tùy phiên bản PHP của bạn hoặc ngẫu hứng):

listen = 127.0.0.1:9000

thành một đường dẫn, ví dụ:

listen = /var/run/php72-fpm.sock

Nếu khởi động lại ngay bây giờ, website của bạn sẽ gặp lỗi 502 Bad Gateway, chuyện này là bình thường thôi. Lí do là webserver như Nginx và Apache không thể kết nối tới PHP-FPM ở cổng 9000 nữa vì chúng ta mới thay đổi mà, nào chuyển sang bước tiếp theo thôi.

Nginx

Đối với Nginx, sẽ không có sự thay đổi từ TCP sang Unix socket vì Nginx đóng vai trò như webserver, phải luôn LISTEN ở một cổng nào đó và public ra bên ngoài để người dùng có thể truy cập.

Mục đích khi chỉnh sửa Nginx là giúp webserver này có thể kết nối tới các upstream, ví dụ như PHP-FPM, Redis (sau khi các upstream này chuyển sang Unix socket) để sử dụng mà thôi.

Hãy mở tập tin chứa các cấu hình upstream của bạn. Mình dùng EasyEngine thì nằm ở tập tin /etc/nginx/conf/upstream.conf.

Tại đây chúng ta sẽ thấy các upstream php, php7 (nếu có), redis (nếu có), memcache (nếu có) đều đang kết nối qua TCP. Hãy thay đổi lại thành đường dẫn mà bạn đã cấu hình ở phía trên cho PHP-FPM và Redis như sau:

upstream php {
server unix:/run/php5-fpm.sock;
# server 127.0.0.1:9000;
}

upstream php7 {
# server 127.0.0.1:9070;
# server unix:/var/run/php/php71-fpm.sock; # php7.1
server unix:/var/run/php/php72-fpm.sock; # php7.2
# server unix:/run/php/php73-fpm.sock; # php7.3
}

upstream redis {
server unix:/var/run/redis/redis.sock;
keepalive 10;
}

Chắc chắn chúng ta cấu hình Nginx đúng bằng lệnh nginx -t, sau đó restart lại Nginx (service nginx restart) là được.

Ngay sau đó khởi động lại PHP-FPM bằng lệnh service php7.2-fpm restart. Bạn sẽ thấy một tập tin có tên /var/run/php72-fpm.sock, vậy là thành công rồi.

Bạn hãy truy cập website xem có bị 502 Bad Gateway nữa không nhé.

Apache

Tương tự Nginx, Apache bắt buộc phải chạy ở mode TCP, chúng ta chỉ việc thay đổi cấu hình của Apache để nó có thể kết nối các ứng dụng ở socket thay vì TCP. Trang document của phần mềm có hướng dẫn khá chi tiết về cách sử dụng:

<FilesMatch "\.php$">
SetHandler "proxy:unix:/var/run/php72-fpm.sock"
</FilesMatch>

Restart Apache và tận hưởng thành quả thôi. Lưu ý: Apache chỉ hỗ trợ unix socket ở phiên bản 2.4.7 trở lên.

Kết bài

Mong rằng các bước cấu hình của bạn đều thành công và quan trọng hơn hết là tốc độ xử lý nhanh hơn so với trước kia. Nếu có vấn đề với việc cấu hình các ứng dụng hay muốn hướng dẫn các ứng dụng mới, đừng ngần ngại để lại comment để mình biết và hỗ trợ bạn nhé.

17 bình luận
  1. bàn ăn badova nói

    chào bạn. mình đang có site bàn ăn badova cần tối ưu bạn có dịch vụ này không

    1. atuan nói

      Hiện tại thời gian tối ưu kĩ càng 1 trang thì thường dài từ 3 tuần đến 1 tháng nên mình không nhận nữa. Khi nào mình có thời gian sẽ trực tiếp mail cho bạn.

      Cảm ơn bạn nhé.

  2. sơn nói

    /var/run/php72-fpm.sock cái đường dẫn này tự mình tạo ra vậy hay lấy ở đâu vậy bác.

    1. atuan nói

      Tự tạo ra bạn nha. Thật ra bạn ghi đường dẫn đó, khi restart các service nó sẽ tạo tự động đó 😀

      1. sơn nói

        Không biết site của bác chạy trên OS và script nào ạ? Mình xin phép lấy một số nội dung của bác để viết bài hướng dẫn cho Centos 7 và VPSSIM được không ạ?

        1. atuan nói

          Feel free to contribute bạn nha. Nhớ ghi nguồn tham khảo từ trang mình là được rồi 😀

        2. atuan nói

          Mình viết bài này dựa vào EasyEngine, trên Ubuntu với các stack mình có liệt kê ở trên á

  3. Thành nói

    Mình thấy trang so sánh này có bảo đến nhược điểm của unix so với TCP là khả năng chịu tải
    https://community.centminmod.com/threads/php-7-x-benchmarks-centmin-mod-vs-easyengine-vs-webinoly-vs-vestacp-vs-oneinstack.14988/

    1. atuan nói

      Hi bạn,

      Cảm ơn bạn đã đóng góp. Mình đã biết vấn đề này rồi và sẽ sắp xếp để viết phần 3.

      1. Thành nói

        Mong bác tìm ra được giải pháp giải quyết vấn đề này 😀

  4. Trần Hiệp nói

    Phần upstream php mình tìm ở VPSSIM nhưng không biết chỗ nào, không biết Tuấn có thể hướng dẫn giúp mình được không?

    1. Anh Tuấn nói

      Để tối về mình cài đặt lại xem sao. Khi có update mình sẽ thông báo bạn.

    2. Anh Tuấn nói

      Hmmm, không biết bạn có xem bài hướng dẫn này chưa, vì mình nghĩ cách này vẫn thực hiện được mà: https://datuan.dev/2019/03/unix-socket-tren-hocvps-vpssim-script/

      1. Trần Hiệp nói

        Mình xem cả 2 bài của bạn rồi, mình đã kích hoạt cả Redis cũng như các tính năng khác. Nhưng vào filezilla kiểm tra ở sv thấy file sock 0kb thì như thế vẫn hoạt động tốt chứ bạn!

      2. Trần Hiệp nói

        Mà mình cảm giác sau khi chuyển từ memcached chạy TCP/IP sang Redis chạy unix sock ko biết có làm đúng không. Mà thấy chậm hơn thì phải

  5. Mai Nam nói

    Này là hình như easyengine 3 , nếu EE 4 thì chỉnh như thế nào ban nhỉ ?

    1. Anh Tuấn nói

      Đúng rồi bạn, bài viết này chỉ dành cho EasyEngine v3 và WordOps thôi. EEv4 mình không còn sử dụng nữa nên không hỗ trượ được. Về ý tưởng thì bạn có thể map socket của MySQL server ra con host và cho các container khác kết nối vào, nhưng đối với EEv4 tự động thì mình nghĩ việc đó không dễ đâu.

Để lại một trả lời

Địa chỉ email của bạn sẽ không được công bố.