2014-11-14 19 views
7

Tôi đang phát triển máy chủ web hiệu suất cao cần xử lý các kết nối đồng thời ~ 2k và 40k QPS, đạt được thời gian resp < 7ms.
Ổ cắm Unix chậm hơn tcp khi được kết nối với redis

Những gì nó đang truy vấn Redis server (chạy trên cùng một máy chủ) và trả về phản hồi cho máy khách. Trong quá trình thử nghiệm, tôi quan sát thấy việc triển khai bằng cách sử dụng TCP STREAM_SOCKET hoạt động tốt hơn so với kết nối với các khe cắm unix. Với ~ 1500 kết nối TCP giữ khoảng 8ms trong khi khe cắm unix đến ~ 50.

Máy chủ được viết bằng C, dựa trên hồ bơi chủ đề Posix liên tục, tôi sử dụng kết nối chặn với Redis. Hệ điều hành của tôi là CentOS 6, kiểm tra được thực hiện bằng cách sử dụng Jmeter, wrk và ab. Để kết nối với redis tôi sử dụng hiredis lib cung cấp hai cách kết nối này với Redis.
Theo như tôi biết unix socket nên ít nhất là nhanh như TCP.

Có ai có ý tưởng gì có thể gây ra hành vi như vậy không? . Tôi bị kẹt. Cảm ơn.

+1

Bạn có thể sao chép tốc độ chậm này bên ngoài của ứng dụng của bạn sử dụng 'redis-benchmark'? –

+1

Theo [liên kết này] (http://redis.io/topics/benchmarks) Lợi ích hiệu suất của ổ cắm miền unix so với vòng lặp TCP/IP có xu hướng giảm khi pipelining được sử dụng nhiều (tức là đường ống dài). – helloV

+0

bạn có đặt SO_NODELAY không? Tôi đã thấy điều này giúp rất nhiều trong các tình huống nhất định. – geert3

Trả lời

15

Ổ cắm miền Unix thường nhanh hơn cổng TCP trên giao diện loopback. Nói chung, các ổ cắm miền Unix có độ trễ trung bình là 2 micro giây trong khi các socket TCP 6 micro giây.

Nếu tôi chạy điểm chuẩn với giá trị mặc định (không có đường dẫn), tôi thấy 160k yêu cầu mỗi giây, về cơ bản vì máy chủ redis đơn luồng bị giới hạn bởi ổ cắm TCP, yêu cầu 160k chạy ở thời gian phản hồi trung bình là 6 micro giây.

Làm lại đạt được 320 nghìn yêu cầu SET/GET mỗi giây khi sử dụng Ổ cắm miền Unix.

Nhưng có giới hạn, thực tế là ở Torusware đã đạt được sản phẩm Speedus, hiệu suất TCP socket hiệu suất cao với độ trễ trung bình 200 nano giây (ping chúng tôi tại [email protected] để yêu cầu phiên bản Hiệu suất cực đoan). Với độ trễ gần như bằng không, chúng tôi thấy điểm chuẩn redis đạt được khoảng 500 nghìn yêu cầu mỗi giây. Vì vậy, chúng ta có thể nói rằng độ trễ của máy chủ redis là khoảng 2 micro giây cho mỗi yêu cầu trung bình.

Nếu bạn muốn trả lời càng sớm càng tốt và tải của bạn thấp hơn hiệu suất máy chủ redis-peak thì tránh pipelining có lẽ là lựa chọn tốt nhất. Tuy nhiên, nếu bạn muốn có thể xử lý thông lượng cao hơn, thì bạn có thể xử lý các đường ống yêu cầu. Phản hồi có thể mất nhiều thời gian hơn nhưng bạn sẽ có thể xử lý nhiều yêu cầu hơn trên một số phần cứng. Như vậy, trên kịch bản trước đó, với một đường ống gồm 32 yêu cầu (đệm 32 yêu cầu trước khi gửi yêu cầu thực tế thông qua socket), bạn có thể xử lý lên đến 1 triệu yêu cầu mỗi giây trên giao diện loopback. Và trong kịch bản này là nơi mà lợi ích của UDS không cao, đặc biệt bởi vì việc xử lý đường ống như vậy là nút cổ chai hiệu suất. Trong thực tế, yêu cầu 1M với một đường ống 32 là khoảng 31k "thực tế" yêu cầu mỗi giây, và chúng tôi đã thấy rằng redis-server có thể xử lý 160k yêu cầu mỗi giây.

Ổ cắm miền Unix xử lý khoảng 1.1M và 1.7M yêu cầu SET/GET mỗi giây, tương ứng. TCP loopback xử lý yêu cầu 1M và 1.5 SET/GET mỗi giây.

Với pipelining nút cổ chai chuyển từ giao thức truyền tải sang xử lý đường ống.

Điều này phù hợp với thông tin được đề cập trong trang web redis-benchmark.

Tuy nhiên, pipelining tăng đáng kể thời gian phản hồi.Do đó, không có pipelining 100% hoạt động thường chạy trong vòng chưa đến 1 mili giây. Khi pipelining 32 yêu cầu thời gian đáp ứng tối đa là 4 mili giây trong một máy chủ hiệu năng cao và hàng chục mili giây nếu máy chủ redis chạy trong một máy khác hoặc trong một máy ảo.

Vì vậy, bạn phải cân bằng thời gian phản hồi và thông lượng tối đa.

+3

Thật kỳ lạ khi không ai nhận xét về câu trả lời dài và đẹp này. Cảm ơn vì đã chia sẽ kinh nghiệm của bạn! – scaryguy

1

Mặc dù đây là câu hỏi cũ, tôi muốn bổ sung. Các câu trả lời khác nói về 500k hoặc thậm chí là 1,7 triệu phản hồi/giây. Điều này có thể đạt được với Redis, nhưng câu hỏi là:

Khách hàng - # Mạng # -> Webserver - # Something # -> Redis

Các chức năng máy chủ web trong loại một proxy HTML để Redis tôi giả sử.

Điều này có nghĩa là số lượng yêu cầu của bạn cũng bị giới hạn đối với số lượng yêu cầu mà máy chủ web có thể đạt được. Có một giới hạn thường bị lãng quên: nếu bạn có kết nối 100Mbit, bạn có 100.000.000 bit một giây theo ý của bạn, nhưng mặc định trong các gói 1518 bit (bao gồm cả không gian cần thiết sau gói). Điều này có nghĩa là: 65k gói mạng. Giả sử tất cả các câu trả lời của bạn nhỏ hơn là phần dữ liệu của gói đó và không phải gửi lại do lỗi CRC hoặc các gói bị mất.

Ngoài ra, nếu kết nối liên tục không được sử dụng, bạn cần thực hiện bắt tay TCP/IP cho mỗi kết nối Điều này bổ sung 3 gói cho mỗi yêu cầu (2 nhận, một lần gửi). Vì vậy, trong tình huống không được tối ưu hóa đó, bạn vẫn còn 21k yêu cầu có thể đạt được đối với máy chủ web của bạn. (hoặc 210k cho kết nối gigabit 'hoàn hảo') - nếu phản hồi của bạn phù hợp với một gói 175 byte.

Vì vậy:

  • kết nối liên tục chỉ cần một chút bộ nhớ, do đó kích hoạt nó. Nó có thể tăng gấp bốn lần hiệu suất của bạn. (trường hợp tốt nhất)
  • Giảm kích thước phản hồi của bạn bằng cách sử dụng gzip/deflate nếu cần để chúng phù hợp với ít gói nhất có thể. (Mỗi gói bị mất là một phản ứng có thể bị mất)
  • Giảm kích thước phản hồi của bạn bằng cách loại bỏ 'rác' không cần thiết như dữ liệu gỡ lỗi hoặc thẻ xml dài.
  • kết nối HTTPS sẽ thêm một khổng lồ (trong comparisation đây) hất
  • Thêm card mạng và thân cây họ
  • nếu phản ứng luôn nhỏ hơn sau đó 175 byte, sử dụng một card mạng dedicted cho dịch vụ này và giảm kích thước khung hình mạng để tăng các gói gửi mỗi giây.
  • đừng để máy chủ làm những thứ khác (như phục vụ các trang web bình thường)
  • ...
Các vấn đề liên quan