2009-12-17 19 views
40

Tôi sẽ trải qua một chút suy nghĩ lại về các trò chơi nhiều người chơi ở quy mô lớn trong thời đại các ứng dụng Facebook và điện toán đám mây.Độ trễ thấp, tin nhắn có quy mô lớn xếp hàng

Giả sử tôi đã xây dựng thứ gì đó trên các giao thức mở hiện có và tôi muốn phân phối 1.000.000 người chơi đồng thời, chỉ để giải quyết vấn đề.

Giả sử mỗi người chơi có hàng đợi tin nhắn đến (để trò chuyện và không có điều gì) và trung bình một hàng đợi tin nhắn gửi đến khác (guild, khu, trường hợp, đấu giá, ...) để chúng tôi có 2.000.000 hàng đợi. Một người chơi sẽ nghe 1-10 hàng đợi tại một thời điểm. Mỗi hàng đợi sẽ có trung bình có thể 1 tin nhắn mỗi giây, nhưng hàng đợi nhất định sẽ có tỷ lệ cao hơn nhiều và số lượng người nghe cao hơn (ví dụ: hàng đợi "vị trí thực thể" cho một phiên bản cấp). Giả sử không quá 100 mili giây độ trễ xếp hàng của hệ thống, điều này là phù hợp với các trò chơi hành động nhẹ nhàng (nhưng không phải là các trò chơi như Quake hoặc Unreal Tournament). Từ các hệ thống khác, tôi biết rằng việc phục vụ 10.000 người dùng trên một hộp 1U hoặc hộp lưỡi dao là một kỳ vọng hợp lý (giả sử không có gì khác đắt tiền hơn, như mô phỏng vật lý hoặc không biết gì). Vì vậy, với hệ thống thanh ngang, nơi khách hàng kết nối với cổng kết nối, kết nối với máy chủ xếp hàng thông điệp, chúng tôi sẽ nhận được 10.000 người dùng trên mỗi cổng với 100 cổng máy chủ và 20.000 hàng đợi tin nhắn trên mỗi máy chủ xếp hàng với 100. máy xếp hàng. Một lần nữa, chỉ cho phạm vi chung. Số lượng kết nối trên mỗi máy MQ sẽ nhỏ: khoảng 100, để nói chuyện với mỗi cổng. Số lượng kết nối trên cổng sẽ cao hơn rất nhiều: 10,100 cho khách hàng + kết nối tới tất cả các máy chủ xếp hàng. (Trên đầu trang này, thêm một số kết nối cho các máy chủ mô phỏng trò chơi thế giới hoặc whatnot, nhưng tôi đang cố gắng giữ riêng biệt bây giờ)

Nếu tôi không muốn xây dựng từ đầu, tôi phải sử dụng một số thông điệp và/hoặc cơ sở hạ tầng xếp hàng tồn tại. Hai giao thức mở tôi có thể tìm thấy là AMQP và XMPP. Mục đích sử dụng XMPP giống một chút so với hệ thống trò chơi này, nhưng chi phí khá đáng chú ý (XML, cộng với dữ liệu hiện diện dài dòng, cộng với các kênh khác phải được xây dựng trên đầu). Mô hình dữ liệu thực tế của AMQP gần với những gì tôi mô tả ở trên, nhưng tất cả người dùng dường như là các tập đoàn lớn, doanh nghiệp và khối lượng công việc dường như có liên quan đến công việc chứ không phải liên quan đến cập nhật trò chơi trong thời gian thực.

Có ai có kinh nghiệm ban ngày với các công nghệ này hoặc triển khai công nghệ của chúng, mà bạn có thể chia sẻ không?

+14

Tôi muốn tóm tắt những gì chúng tôi đã làm. Thỏ, Qpid, ZeroMQ và những người khác đều có nhiều lựa chọn thiết kế mắt kinh doanh hơn và độ trễ thấp hơn, và giảm nhu cầu tin tưởng khách hàng, hoặc không hỗ trợ tỷ lệ tham gia/tạo/xếp hàng cao tạo/xóa hoặc giống. XMPP không liên kết tốt trên hộp vật lý đầu tiên. JMS thậm chí còn tệ hơn cả Thỏ và bạn bè. Redis Pub/Sub là thú vị, nhưng một lần nữa không liên kết/cluster. Chúng tôi đã kết thúc bằng văn bản của riêng mình trên đầu trang của Erlang/OTP (cùng một ngôn ngữ được sử dụng cho Thỏ và ejabberd), sử dụng bộ đệm giao thức của Google là IDL cấp thấp. –

+0

cảm ơn bạn đã chia sẻ, ý của bạn là gì bởi "XMPP không liên kết tốt trên hộp vật lý đầu tiên"? – alex

+3

Tôi có nghĩa là "không liên kết tốt/quá khứ/hộp vật lý đầu tiên." Thêm phần cứng không làm được gì nhiều cho việc mở rộng quy mô, bởi vì XMPP là sự lựa chọn sai của giao thức ở đó. –

Trả lời

10

@MSalters

'hàng đợi thông điệp' Re: hoạt động mặc định

RabbitMQ là chính xác những gì bạn mô tả: pubsub thoáng qua. Nhưng với TCP thay vì UDP.

Nếu bạn muốn đảm bảo phân phối cuối cùng và các tính năng lưu giữ và phục hồi khác, thì bạn cũng có thể có - đó là một tùy chọn. Đó là toàn bộ quan điểm của RabbitMQ và AMQP - bạn có thể có rất nhiều hành vi chỉ với một hệ thống gửi tin nhắn.

Mô hình bạn mô tả là hành vi DEFAULT, tạm thời, "tắt lửa và quên" và định tuyến thư đến bất kỳ nơi nào người nhận. Mọi người sử dụng RabbitMQ để phát hiện multicast trên EC2 chỉ vì lý do đó. Bạn có thể nhận được các hành vi kiểu UDP trên unicast TCP pubsub. Neat, huh?

Re UDP:

Tôi không chắc liệu UDP có hữu ích ở đây hay không. Nếu bạn tắt Nagling thì RabbitMQ thời gian chờ tin nhắn đơn chiều (client-broker-client) đã được đo tại 250-300 micro giây. Xem ở đây để so sánh với độ trễ của Windows (cao hơn một chút) http://old.nabble.com/High%28er%29-latency-with-1.5.1--p21663105.html

Tôi không thể nghĩ nhiều trò chơi nhiều người cần độ trễ hai lần nhỏ hơn 300 micro giây. Bạn có thể nhận được dưới 300us với TCP. Cửa sổ TCP đắt hơn UDP thô, nhưng nếu bạn sử dụng UDP để đi nhanh hơn và thêm trình phục hồi tùy chỉnh hoặc trình quản lý seqno/ack/resend thì có thể làm chậm lại bạn. Tất cả phụ thuộc vào trường hợp sử dụng của bạn. Nếu bạn thực sự thực sự thực sự cần phải sử dụng UDP và acks lười biếng và như vậy, sau đó bạn có thể loại bỏ TCP của RabbitMQ và có thể kéo nó đi.

Tôi hy vọng điều này sẽ giúp làm rõ lý do tại sao tôi đề xuất RabbitMQ cho trường hợp sử dụng của Jon.

+0

Cảm ơn lời đề nghị. Một thay thế cho Rabbit là Qpid, trong đó yêu cầu 6 M thông điệp mỗi giây trên một hộp máy chủ 8 lõi đơn (!) Khi chạy trên hạt nhân có độ trễ thấp Red Hat. Tuy nhiên, tôi nghi ngờ rằng hộp cũng có 10.000 người dùng kết nối cùng một lúc. Nếu bạn có một liên kết tốt để so sánh Thỏ vs Qpid, tôi rất muốn nhìn thấy nó! –

+0

Jon, bạn có thể chỉ cho tôi tại tham chiếu 6M không? Tôi có cảm giác rằng nó đề cập đến một trường hợp mà RabbitMQ và Qpid đều được thử nghiệm với nguồn cấp dữ liệu OPRA (dữ liệu thị trường tài chính) một số thời gian trước đây. Đây là một trường hợp tốt, nhưng như tôi nhớ lại chúng tôi cả hai sử dụng batching và nén để có được một tỷ lệ cao hơn. Lưu ý rằng trong trường hợp của OPRA, việc sử dụng cả hai đợt và nén là thực hành tiêu chuẩn. Re so sánh hai nhà môi giới trong các trường hợp tương tự như gần đây, không có gì immmediately lò xo để tâm trí, nhưng Googling có thể tiết lộ nhiều hơn nữa. Chúc mừng alexis – alexis

+0

Vâng, đó có thể là trường hợp kiểm tra. Con số 6 triệu là trên trang web Red Hat cho việc triển khai Qpid dựa trên Linux "độ trễ thấp" của họ. Và trường hợp thử nghiệm đó hầu như không liên quan gì đến trường hợp tôi quan tâm, có vấn đề là có 1.000.000 người dùng được kết nối, mỗi người chỉ nhận được một vài tin nhắn ... –

4

Jon, âm thanh này giống như trường hợp sử dụng lý tưởng cho AMQP và RabbitMQ.

Tôi không chắc chắn lý do tại sao bạn nói rằng người dùng AMQP là tất cả các tập đoàn doanh nghiệp lớn. Hơn một nửa số khách hàng của chúng tôi đang ở trong không gian 'web' từ các công ty lớn đến nhỏ. Rất nhiều trò chơi, hệ thống cá cược, hệ thống trò chuyện, hệ thống kiểu twittery và thông tin điện toán đám mây đã được xây dựng từ RabbitMQ. Thậm chí còn có các ứng dụng điện thoại di động. Quy trình làm việc chỉ là một trong nhiều trường hợp sử dụng.

Chúng tôi cố gắng theo dõi những gì đang xảy ra ở đây: (! Chắc chắn rằng bạn click thông qua danh sách các trường hợp sử dụng trên del.icio.us quá)

http://www.rabbitmq.com/how.html

Xin đừng mất một nhìn. chúng tôi ở đây để giúp đỡ. Hãy gửi email cho chúng tôi tại [email protected] hoặc nhấn tôi trên twitter (@monadic).

2

Trải nghiệm của tôi là với một giải pháp thay thế không mở, BizTalk. Bài học đau đớn nhất mà chúng tôi học được là những hệ thống phức tạp này KHÔNG nhanh. Và như bạn đã tìm ra từ các yêu cầu phần cứng, điều đó chuyển trực tiếp thành các chi phí đáng kể.

Vì lý do đó, thậm chí không đi gần XML cho các giao diện cốt lõi. Cụm máy chủ của bạn sẽ phân tích 2 triệu thư mỗi giây. Điều đó có thể dễ dàng là 2-20 GB/giây của XML! Tuy nhiên, hầu hết các tin nhắn sẽ được cho một vài hàng đợi, trong khi hầu hết các hàng đợi trong thực tế lưu lượng truy cập thấp.

Vì vậy, hãy thiết kế kiến ​​trúc của bạn để dễ dàng bắt đầu với máy chủ xếp hàng COTS và sau đó di chuyển từng hàng đợi (loại) đến máy chủ xếp hàng tùy chỉnh khi xác định nút cổ chai.

Ngoài ra, vì lý do tương tự, đừng cho rằng kiến ​​trúc xếp hàng đợi là tốt nhất cho mọi ứng dụng mà ứng dụng của bạn có. Lấy ví dụ "vị trí thực thể trong ví dụ" của bạn. Đây là trường hợp cổ điển khi bạn không muốn gửi thư được đảm bảo. Lý do bạn cần chia sẻ thông tin này là vì nó thay đổi mọi lúc. Vì vậy, nếu một tin nhắn bị mất, bạn không muốn dành nhiều thời gian để phục hồi nó. Bạn sẽ chỉ gửi locatiom cũ của thực thể bị ảnh hưởng. Thay vào đó, bạn muốn gửi vị trí hiện tại của pháp nhân đó. Công nghệ-khôn ngoan này có nghĩa là bạn muốn UDP, không TCP và một cơ chế phục hồi mất mát tùy chỉnh.

+2

Có: Sự cố với TCP xuất hiện khi bạn thả một gói. Gian hàng trước khi phục hồi có thể có ý nghĩa - và với TCP, hạt nhân sẽ giữ lại thông tin * mới hơn * chỉ vì thông tin * cũ hơn chưa đến. Để chơi game (chẳng hạn như cập nhật vị trí), điều đó là không mong muốn. Lưu ý rằng thông điệp xếp hàng khách hàng là tất cả người dùng được phân phối trên toàn thế giới - chúng không nằm trong cụm chính nó, do đó các vấn đề về mạng là một thực tế của cuộc sống. (Trong thực tế, ngay cả trong phòng máy chủ được kết nối tốt, bạn sẽ thấy một số lượng mất gói tin, dường như không có vấn đề lớn như thế nào thiết bị chuyển mạch và bộ đệm của bạn) –

3

FWIW, trong trường hợp kết quả trung gian không quan trọng (như thông tin định vị) Qpid có "hàng đợi giá trị cuối cùng" có thể chỉ phân phối giá trị gần đây nhất cho người đăng ký.

+0

Thật tuyệt khi biết! Tôi đã thực sự đã kiểm tra và xây dựng Qpid và hiện đang dùng thử. Những gì tôi không đặc biệt thích là cấu hình mặc định được giới hạn ở 300 kết nối. Nó sẽ làm 20.000 kết nối mỗi hộp? –

+0

Tôi trả lời sâu hơn trong danh sách [email protected], nhưng để đóng khoảng cách ở đây, có, làm 20.000 kết nối mỗi hộp sẽ không có vấn đề, giả sử bạn đã có đủ mã lực phần cứng. –

10

Hiện tại tôi đang xây dựng một hệ thống như vậy.

Tôi đã thực hiện một số lượng hợp lý đánh giá một số MQ, bao gồm RabbitMQ, Qpid và ZeroMQ. Độ trễ và thông lượng của bất kỳ trong số đó là quá đủ cho loại ứng dụng này.Tuy nhiên, điều không tốt là thời gian tạo hàng đợi ở giữa nửa triệu hàng đợi trở lên. Qpid đặc biệt giảm nghiêm trọng sau hàng nghìn hàng đợi. Để phá vỡ vấn đề đó, bạn thường sẽ phải tạo ra các cơ chế định tuyến của riêng bạn (số lượng nhỏ hơn tổng số hàng đợi và người tiêu dùng trên các hàng đợi đó đang nhận được các thông điệp mà họ không quan tâm).

Hệ thống hiện tại của tôi có thể sẽ sử dụng ZeroMQ, nhưng theo cách khá hạn chế, bên trong cụm. Các kết nối từ máy khách được xử lý với một sim tùy chỉnh. daemon mà tôi xây dựng bằng cách sử dụng libev và hoàn toàn đơn luồng (và đang hiển thị tỷ lệ rất tốt - nó sẽ có thể xử lý 50.000 kết nối trên một hộp mà không có bất kỳ vấn đề nào - tỷ lệ đánh dấu của chúng tôi là khá thấp, và có không vật lý).

XML (và do đó XMPP) là rất không phù hợp với điều này, vì bạn sẽ chốt CPU xử lý XML lâu trước khi bạn trở thành ràng buộc trên I/O, mà không phải là những gì bạn muốn. Hiện tại, chúng tôi đang sử dụng Bộ đệm giao thức của Google và những bộ đệm này dường như rất phù hợp với nhu cầu cụ thể của chúng tôi. Chúng tôi cũng đang sử dụng TCP cho các kết nối máy khách. Tôi đã có kinh nghiệm sử dụng cả UDP và TCP cho điều này trong quá khứ, và như được chỉ ra bởi những người khác, UDP không có một số lợi thế, nhưng nó hơi khó khăn hơn để làm việc với.

Hy vọng rằng khi chúng tôi gần hơn một chút để khởi chạy, tôi sẽ có thể chia sẻ thêm chi tiết.