Đây có phải là kiến ​​trúc phù hợp cho trò chơi di động MMORPG của chúng tôi không?


14

Những ngày này, tôi đang cố gắng thiết kế kiến ​​trúc của một game di động MMORPG mới cho công ty của tôi. Trò chơi này tương tự như Mafia Wars, iMobsters hoặc RISK. Ý tưởng cơ bản là chuẩn bị một đội quân để chiến đấu với đối thủ của bạn (người dùng trực tuyến).

Mặc dù trước đây tôi đã làm việc trên nhiều ứng dụng di động nhưng đây là điều mới mẻ đối với tôi. Sau rất nhiều cuộc đấu tranh, tôi đã tìm ra một kiến ​​trúc được minh họa với sự trợ giúp của sơ đồ dòng cấp cao:

Sơ đồ dòng cao cấp

Chúng tôi đã quyết định đi với mô hình máy khách-máy chủ. Sẽ có một cơ sở dữ liệu tập trung trên máy chủ. Mỗi khách hàng sẽ có cơ sở dữ liệu cục bộ riêng sẽ đồng bộ với máy chủ. Cơ sở dữ liệu này hoạt động như một bộ đệm để lưu trữ những thứ không thay đổi thường xuyên, ví dụ như bản đồ, sản phẩm, hàng tồn kho, v.v.

Với mô hình này, tôi không biết làm thế nào để giải quyết các vấn đề sau:

  • Điều gì sẽ là cách tốt nhất để đồng bộ hóa cơ sở dữ liệu máy chủ và máy khách?
  • Một sự kiện có nên được lưu vào DB cục bộ trước khi cập nhật nó lên máy chủ không? Điều gì xảy ra nếu ứng dụng chấm dứt vì một số lý do trước khi lưu các thay đổi vào DB tập trung?
  • Các yêu cầu HTTP đơn giản sẽ phục vụ mục đích đồng bộ hóa?
  • Làm thế nào để biết người dùng nào đang đăng nhập? (Một cách có thể là để khách hàng tiếp tục gửi yêu cầu đến máy chủ sau mỗi x phút để thông báo rằng nó đang hoạt động. Nếu không, hãy xem xét một khách hàng không hoạt động).
  • Là xác nhận phía khách hàng là đủ? Nếu không, làm thế nào để hoàn nguyên một hành động nếu máy chủ không xác thực một cái gì đó?

Tôi không chắc đây có phải là một giải pháp hiệu quả hay không và nó sẽ mở rộng như thế nào. Tôi thực sự đánh giá cao nếu những người đã làm việc trên các ứng dụng như vậy có thể chia sẻ kinh nghiệm của họ, điều này có thể giúp tôi tìm ra thứ gì đó tốt hơn. Cảm ơn trước.

Thông tin bổ sung:

Phía máy khách được triển khai trong công cụ trò chơi C ++ có tên là marmalade. Đây là một công cụ trò chơi đa nền tảng, có nghĩa là bạn có thể chạy ứng dụng của mình trên tất cả các hệ điều hành di động lớn. Chúng tôi chắc chắn có thể đạt được luồng và cũng được minh họa trong sơ đồ dòng của tôi. Tôi đang dự định sử dụng MySQL cho máy chủ và SQLite cho máy khách.

Đây không phải là một trò chơi theo lượt nên không có nhiều tương tác với người chơi khác. Máy chủ sẽ cung cấp danh sách người chơi trực tuyến và bạn có thể chiến đấu với họ bằng cách nhấp vào nút chiến đấu và sau khi một số hình ảnh động, kết quả sẽ được công bố.

Để đồng bộ hóa cơ sở dữ liệu, tôi có hai giải pháp:

  1. Lưu dấu thời gian cho mỗi bản ghi. Cũng theo dõi khi DB cục bộ được cập nhật lần cuối. Khi đồng bộ hóa, chỉ chọn những hàng có dấu thời gian lớn hơn và gửi đến DB cục bộ. Giữ một cờ isDelatted cho các hàng đã xóa để mọi thao tác xóa chỉ đơn giản là hoạt động như một bản cập nhật. Nhưng tôi có nghi ngờ nghiêm trọng về hiệu suất vì đối với mọi yêu cầu đồng bộ hóa, chúng tôi sẽ phải quét DB hoàn chỉnh và tìm kiếm các hàng được cập nhật.
  2. Một kỹ thuật khác có thể là giữ một bản ghi của mỗi lần chèn hoặc cập nhật diễn ra đối với người dùng. Khi ứng dụng khách yêu cầu đồng bộ hóa, hãy chuyển đến bảng này và tìm hiểu các hàng của bảng nào đã được cập nhật hoặc chèn. Khi các hàng này được chuyển thành công đến máy khách, hãy xóa nhật ký này. Nhưng sau đó tôi nghĩ về những gì sẽ xảy ra nếu người dùng sử dụng thiết bị khác. Theo bảng nhật ký, tất cả các bản cập nhật đã được chuyển cho người dùng đó nhưng thực tế điều đó đã được thực hiện trên một thiết bị khác. Vì vậy, chúng tôi có thể phải theo dõi thiết bị cũng. Việc thực hiện kỹ thuật này tốn nhiều thời gian hơn nhưng không chắc nó có thực hiện được việc đầu tiên không.

2
Tôi sẽ lấy một đánh giá về MsQuery và fiddle với nó - Tôi không chắc MySQL cung cấp những gì về mặt sao chép nhưng MsQuery 2008 R2 cung cấp cho bạn một kỹ thuật LOAD sao chép (5-6) để lựa chọn. Chỉ là một suy nghĩ, không ghét MySQL hay bất cứ điều gì, nhưng Microsoft thực sự giỏi trong việc phân cụm.
Jonathan Dickinson

1
@Jonathan Dickinson: Có cụm MySQL: P
Coyote

1
Cũng nhìn vào PostgreSQL - phiên bản 9 có công nghệ sao chép, PostgreSQL có danh tiếng lâu đời tuyệt vời để xử lý các tải nặng thực sự tốt, nhiều nhà phát triển dường như là các hạt tối ưu hóa, và tốt nhất là nó là nguồn mở và hoàn toàn miễn phí cho mọi mục đích sử dụng (bao gồm cả thương mại).
Randolf Richardson

điều này là chúng ta không thể sử dụng cùng một cơ sở dữ liệu ở phía máy khách và máy chủ. Tôi nghĩ rằng DB phù hợp nhất cho máy khách sẽ là SQLite để nó không tiêu tốn nhiều tài nguyên vì ứng dụng sẽ chạy trên thiết bị di động. Mặc dù người làm việc trên phần máy chủ chỉ biết MySQL nên đó là lý do tại sao chúng tôi đã chọn nó. Ngoài ra tôi đã nghe nói rằng hầu hết các trò chơi MMO sử dụng cơ sở dữ liệu MySQL.
umair

1
@umair: Phía máy khách có thể là SQLite (ví dụ trên iPhone đã có sẵn). Nhưng bạn có thể chọn chỉ lưu trữ dữ liệu có liên quan mà bạn cần trong một tệp (Dù sao SQLite cũng vậy) và không bận tâm với DB phía máy khách ở tất cả các loại như bạn sẽ làm với ứng dụng Javascript.
Coyote

Câu trả lời:


15

Nếu đó không phải là một trò chơi "thời gian thực" theo nghĩa người chơi không cần phải thấy kết quả ngay lập tức của các hành động của người chơi khác trên một cảnh trò chơi thì bạn sẽ ổn với các yêu cầu HTTP. Nhưng hãy nhớ rằng chi phí hoạt động của HTTP.

Điều đó nói rằng việc sử dụng HTTP sẽ không giúp bạn tiết kiệm thiết kế giao thức liên lạc của mình một cách cẩn thận. Nhưng nếu bạn phụ trách cả máy chủ và phía máy khách, bạn thật may mắn vì bạn có thể điều chỉnh giao thức khi bạn cần.

Để đồng bộ hóa giữa DB chủ và DB khách, bạn có thể sử dụng bất kỳ giao thức truyền tải nào bạn có quyền truy cập, HTTP hoặc các giao thức khác. Phần quan trọng là logic đằng sau sự đồng bộ. Đối với cách tiếp cận đơn giản, chỉ cần gộp từ máy chủ tất cả các thay đổi mới nhất mà máy khách cần kể từ dấu thời gian cuối cùng trong DB máy khách. Áp dụng nó cho DB khách hàng và đi với điều đó. Nếu bạn có nhiều thay đổi hơn về phía khách hàng, hãy tải lên nếu nó vẫn còn liên quan, nếu không thì loại bỏ.

Một số trò chơi thậm chí không sử dụng DB cục bộ, họ chỉ cần theo dõi trạng thái bằng cách gộp thông tin liên quan từ máy chủ khi cần.

Nếu mất các sự kiện cục bộ không được chấp nhận thì có, bạn nên có bộ nhớ cục bộ và lưu vào bộ lưu trữ đó càng thường xuyên càng tốt. Bạn có thể thử làm điều đó trước khi mỗi mạng gửi.

Để kiểm tra người dùng hoạt động, chúng tôi đã sử dụng ping với HTTP cứ sau 20 giây trên một trò chơi thành công ... Giá trị này tăng ngay lập tức vì các máy chủ đã bị quá tải :( Nhóm máy chủ không nghĩ về thành công. Vì vậy, tôi sẽ nói với bạn để thêm một thông điệp hoặc một loại tiêu đề đặc biệt nào đó trong giao thức liên lạc của bạn sẽ cho phép bạn cấu hình lại các máy khách của mình (để cân bằng tải tần số ping và các giá trị liên quan đến giao tiếp khác).

Xác nhận phía khách hàng là đủ nếu bạn không bận tâm đến những kẻ gian lận, tin tặc và các kịch bản tự động khác tấn công trò chơi của bạn. Máy chủ có thể chỉ cần từ chối hành động của bạn và gửi thông báo lỗi với một số chi tiết. Bạn xử lý thông báo lỗi đó bằng cách khôi phục các thay đổi cục bộ hoặc không áp dụng chúng cho bộ nhớ cục bộ của bạn nếu bạn có thể đợi cho đến khi máy chủ phản hồi để thực sự lưu các thay đổi.

Chúng tôi đã sử dụng mẫu lệnh trong trò chơi của mình để cho phép khôi phục đơn giản và hiệu quả các hành động của người dùng không thành công hoặc không hợp lệ. Các lệnh được phát cục bộ gửi đến các đồng nghiệp hoặc dịch sang tin nhắn máy chủ và sau đó được áp dụng trên các đồng nghiệp hoặc kiểm tra trên máy chủ, trong trường hợp có vấn đề, các lệnh không được phát và cảnh trò chơi trở lại trạng thái ban đầu với thông báo.

Sử dụng HTTP không phải là ý tưởng tồi vì sau này, nó sẽ cho phép bạn tích hợp rất dễ dàng với các máy khách Flash hoặc HTML5, nó linh hoạt, bạn có thể sử dụng bất kỳ loại ngôn ngữ kịch bản máy chủ nào và với các kỹ thuật cân bằng tải cơ bản thêm nhiều máy chủ sau mà không cần nhiều nỗ lực để mở rộng quy mô phụ trợ của bạn.

Bạn có rất nhiều việc phải làm nhưng đó là một công việc thú vị ... Vì vậy, hãy tận hưởng!


3
+1 cho 'HTML có thể là đủ tốt' bởi vì nó có thể là :).
Jonathan Dickinson

1
@Coyote: cảm ơn vì đã dành thời gian và cung cấp câu trả lời chi tiết như vậy. Thực sự thích ý tưởng HTTP của bạn để cung cấp hỗ trợ cho các khách hàng khác.
umair

1
Có thể lực lượng sẽ ở bên bạn :)
Coyote

5

Điều gì sẽ là cách tốt nhất để đồng bộ hóa cơ sở dữ liệu máy chủ và máy khách?

Cách dễ nhất là triển khai cơ sở dữ liệu dưới dạng một tệp bạn có thể chuyển. Nếu bạn cố gắng so sánh sự khác biệt giữa các cơ sở dữ liệu thì đó là một thế giới đau khổ và tôi nói từ kinh nghiệm.

Lưu ý rằng máy chủ của bạn không được tin tưởng các quyết định mà khách hàng đưa ra dựa trên cơ sở dữ liệu cục bộ đó, vì khách hàng có thể thay đổi nó. Nó phải tồn tại hoàn toàn cho chi tiết trình bày.

Một sự kiện có nên được lưu vào DB cục bộ trước khi cập nhật nó lên máy chủ không?

Không. Nếu máy chủ quyết định sự kiện không bao giờ xảy ra thì sao? Dù sao thì khách hàng cũng không nên đưa ra quyết định về các sự kiện, vì khách hàng không thể tin tưởng được.

Tôi nhận thấy bạn cũng đang nói về DB cục bộ theo hai cách: một, cho "những thứ không thay đổi thường xuyên" và hai, cho các sự kiện. Chúng không thực sự nằm trong cùng một cơ sở dữ liệu, vì những lý do trên - bạn không muốn bắt đầu cố gắng hợp nhất hoặc tìm các hàng dữ liệu riêng lẻ trong cơ sở dữ liệu. Ví dụ, tính toàn vẹn tham chiếu trở thành vấn đề khi máy khách có tham chiếu đến một mục mà bạn quyết định xóa khỏi máy chủ. Hoặc nếu máy khách thay đổi một hàng và máy chủ thay đổi một hàng, thay đổi đó được ưu tiên, và tại sao?

Các yêu cầu HTTP đơn giản sẽ phục vụ mục đích đồng bộ hóa?

Có, cung cấp chúng khá ít hoặc ít. HTTP không hiệu quả về băng thông, vì vậy hãy nhớ điều đó.

Làm thế nào để biết người dùng nào đang đăng nhập? (Một cách có thể là để khách hàng tiếp tục gửi yêu cầu đến máy chủ sau mỗi x phút để thông báo rằng nó đang hoạt động. Nếu không, hãy xem xét một khách hàng không hoạt động).

Nếu bạn sử dụng một giao thức nhất thời như HTTP, thì đó là một ý tưởng hợp lý. Khi máy chủ nhận được tin nhắn từ khách hàng, bạn có thể cập nhật thời gian 'nhìn thấy lần cuối' cho khách hàng đó.

Là xác nhận phía khách hàng là đủ? Nếu không, làm thế nào để hoàn nguyên một hành động nếu máy chủ không xác thực một cái gì đó?

Không hoàn toàn không. Thân chủ nằm trong tay kẻ thù. Làm thế nào để hoàn nguyên một hành động phụ thuộc hoàn toàn vào những gì bạn coi là một hành động và tác động của nó. Cách dễ nhất là không thực hiện hành động nào cho đến khi máy chủ phản hồi để cho phép. Một lộ trình phức tạp hơn một chút là đảm bảo mọi hành động đều có khả năng khôi phục để hoàn tác hành động và lưu trữ tất cả các hành động chưa được xử lý trên máy khách. Khi máy chủ thừa nhận chúng, hãy xóa chúng khỏi bộ đệm. Nếu một hành động bị từ chối, hãy khôi phục lại từng hành động theo thứ tự ngược lại và bao gồm cả hành động bị từ chối.


1
Bạn đóng đinh nó. Bạn đã đúng khi đồng bộ hóa DB +1 Máy khách không bao giờ nên tự thay đổi DB ... Chỉ cần gọi các chức năng chạy trên máy chủ và cập nhật DB bằng cách sử dụng logic của trò chơi, sau đó truy xuất kết quả.
Coyote

@Kylotan: cảm ơn vì đã chỉ ra các dòng chảy trong mô hình của tôi
umair

@Kylotan: "Cách dễ nhất là triển khai cơ sở dữ liệu dưới dạng một tệp bạn có thể chuyển. Nếu bạn cố gắng so sánh sự khác biệt giữa các cơ sở dữ liệu thì đó là một thế giới đau khổ và tôi nói từ kinh nghiệm." điều này có nghĩa là tất cả dữ liệu được tải xuống mỗi khi ứng dụng được khởi chạy. Có những thứ sẽ không thay đổi rất thường xuyên và vì vậy có thể không chấp nhận tải xuống mỗi lần. Điều này cũng sẽ tăng thời gian ra mắt của ứng dụng đáng kể. Có suy nghĩ gì không?
umair

Nếu dữ liệu nhỏ, thì vấn đề sẽ biến mất. Tôi sẽ ngạc nhiên nếu cơ sở dữ liệu tập trung dữ liệu tĩnh của bạn rất lớn. Nhưng dù sao đi nữa, nếu bạn chia dữ liệu tĩnh thành các phần nhỏ hơn, thì bạn chỉ cần gửi những dữ liệu đã thay đổi kể từ lần trước. Chắc chắn, bạn - có thể thực hiện việc này trên cơ sở mỗi hàng, nếu bạn sẵn sàng giữ thời gian sửa đổi ở mỗi hàng. Nói chung, tôi thích có dữ liệu tĩnh bên ngoài DB quan hệ, để cho phép tôi ghi đè lên nó một cách dễ dàng.
Kylotan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.