Hari-hari ini saya mencoba merancang arsitektur game mobile MMORPG baru untuk perusahaan saya. Game ini mirip dengan Mafia Wars, iMobsters, atau RISIKO. Ide dasarnya adalah menyiapkan pasukan untuk melawan lawan Anda (pengguna online).
Meskipun saya sebelumnya telah bekerja pada beberapa aplikasi seluler tetapi ini adalah sesuatu yang baru bagi saya. Setelah banyak perjuangan, saya datang dengan arsitektur yang diilustrasikan dengan bantuan diagram alir tingkat tinggi:
Kami telah memutuskan untuk menggunakan model client-server. Akan ada database terpusat di server. Setiap klien akan memiliki database lokal sendiri yang akan tetap sinkron dengan server. Basis data ini bertindak sebagai cache untuk menyimpan hal-hal yang tidak sering berubah misalnya peta, produk, inventaris dll.
Dengan model ini, saya tidak yakin bagaimana mengatasi masalah berikut:
- Apa cara terbaik untuk menyinkronkan server dan basis data klien?
- Haruskah suatu peristiwa disimpan ke DB lokal sebelum memperbaruinya ke server? Bagaimana jika aplikasi berhenti karena suatu alasan sebelum menyimpan perubahan ke DB yang terpusat?
- Apakah permintaan HTTP sederhana dapat digunakan untuk tujuan sinkronisasi?
- Bagaimana cara mengetahui pengguna mana yang saat ini masuk? (Salah satu cara bisa membuat klien terus mengirim permintaan ke server setelah setiap x menit untuk memberitahukan bahwa itu aktif. Jika tidak, anggap klien tidak aktif).
- Apakah validasi sisi klien sudah cukup? Jika tidak, bagaimana cara mengembalikan suatu tindakan jika server tidak memvalidasi sesuatu?
Saya tidak yakin apakah ini solusi yang efisien dan bagaimana skalanya. Saya akan sangat menghargai jika orang-orang yang sudah mengerjakan aplikasi semacam itu dapat berbagi pengalaman mereka yang mungkin membantu saya untuk menghasilkan sesuatu yang lebih baik. Terima kasih sebelumnya.
Informasi tambahan:
Sisi klien diimplementasikan dalam engine game C ++ yang disebut marmalade. Ini adalah mesin permainan lintas platform yang artinya Anda dapat menjalankan aplikasi di semua OS seluler utama. Kita tentu bisa mencapai threading dan yang juga diilustrasikan dalam diagram alir saya. Saya berencana menggunakan MySQL untuk server dan SQLite untuk klien.
Ini bukan permainan berbasis giliran sehingga tidak ada banyak interaksi dengan pemain lain. Server akan memberikan daftar pemain online dan Anda dapat melawan mereka dengan mengklik tombol pertempuran dan setelah beberapa animasi, hasilnya akan diumumkan.
Untuk sinkronisasi database saya memiliki dua solusi dalam pikiran:
- Simpan stempel waktu untuk setiap catatan. Catat juga kapan DB lokal terakhir diperbarui. Saat menyinkronkan, hanya pilih baris yang memiliki stempel waktu lebih besar dan kirim ke DB lokal. Simpan bendera isDeleted untuk baris yang dihapus sehingga setiap penghapusan hanya berperilaku sebagai pembaruan. Tetapi saya memiliki keraguan serius tentang kinerja karena untuk setiap permintaan sinkronisasi kami harus memindai DB lengkap dan mencari baris yang diperbarui.
- Teknik lain mungkin untuk menyimpan log dari setiap penyisipan atau pembaruan yang terjadi terhadap pengguna. Saat aplikasi klien meminta sinkronisasi, buka tabel ini dan cari tahu baris mana dari tabel yang telah diperbarui atau dimasukkan. Setelah baris-baris ini berhasil ditransfer ke klien, hapus log ini. Tapi kemudian saya memikirkan apa yang terjadi jika pengguna menggunakan perangkat lain. Menurut tabel log semua pembaruan telah ditransfer untuk pengguna itu tetapi sebenarnya itu dilakukan pada perangkat lain. Jadi kita mungkin harus melacak perangkat juga. Menerapkan teknik ini lebih memakan waktu tetapi tidak yakin apakah itu melakukan yang pertama.
sumber
Jawaban:
Jika ini bukan permainan "waktu nyata" dalam arti bahwa para pemain tidak perlu melihat hasil langsung dari tindakan pemain lain di kancah permainan, maka Anda harus menyetujui permintaan HTTP. Tapi Perlu diingat overhead HTTP.
Yang mengatakan menggunakan HTTP tidak akan menyelamatkan Anda dari merancang protokol komunikasi Anda dengan hati-hati. Tetapi jika Anda bertanggung jawab atas server dan sisi klien Anda beruntung karena Anda dapat menyesuaikan protokol saat Anda membutuhkannya.
Untuk menyinkronkan antara Master DB dan DB Klien Anda dapat menggunakan protokol transport apa pun yang Anda miliki aksesnya, HTTP atau lainnya. Bagian yang penting adalah logika di balik sinkronisasi. Untuk pendekatan langsung, cukup menyatukan dari server semua perubahan terbaru yang diperlukan oleh klien sejak timestamp terakhir dalam DB klien. Terapkan ke DB klien dan ikuti itu. Jika Anda memiliki lebih banyak perubahan pada sisi klien, unggahlah jika masih relevan, jika tidak, buang.
Beberapa game bahkan tidak menggunakan DB lokal, mereka hanya melacak status dengan mengumpulkan info yang relevan dari server saat dibutuhkan.
Jika kehilangan acara lokal tidak dapat diterima maka ya, Anda harus memiliki penyimpanan lokal dan menyimpan ke penyimpanan itu sesering mungkin. Anda dapat mencoba melakukan itu sebelum setiap jaringan mengirim.
Untuk memeriksa pengguna aktif, kami biasa melakukan ping dengan HTTP setiap 20 detik pada game yang sukses ... Nilai ini langsung naik karena server telah kelebihan beban :( Tim server tidak memikirkan kesuksesan. Jadi saya akan meminta Anda untuk menambahkan pesan atau semacam header khusus dalam protokol komunikasi Anda yang akan memungkinkan Anda mengkonfigurasi ulang klien Anda (untuk penyetelan beban frekuensi ping dan nilai-nilai terkait komunikasi lainnya).
Validasi sisi klien sudah cukup jika Anda tidak keberatan curang, peretas, dan skrip otomatis lainnya yang menyerang permainan Anda. Server hanya dapat menolak tindakan Anda dan mengirim pesan kesalahan dengan beberapa detail. Anda menangani pesan kesalahan dengan memutar kembali perubahan lokal atau dengan tidak menerapkannya ke penyimpanan lokal Anda jika Anda bisa menunggu sampai server merespons untuk benar-benar menyimpan perubahan.
Kami menggunakan pola perintah di game kami untuk memungkinkan rollback sederhana dan efisien dari tindakan pengguna yang gagal atau tidak valid. Perintah dimainkan secara lokal dikirim ke rekan-rekan atau diterjemahkan ke pesan server dan kemudian diterapkan pada rekan-rekan atau diperiksa di server, jika ada masalah perintah tidak dimainkan dan adegan permainan kembali ke keadaan awal dengan pemberitahuan.
Menggunakan HTTP bukanlah ide yang buruk karena, nanti, ini akan memungkinkan Anda untuk berintegrasi dengan sangat mudah dengan klien Flash atau HTML5, fleksibel, Anda dapat menggunakan semua jenis bahasa scripting server dan dengan teknik penyeimbangan beban dasar tambahkan lebih banyak server nanti tanpa banyak usaha untuk skala backend Anda.
Anda memiliki banyak hal yang harus dilakukan tetapi ini adalah pekerjaan yang menyenangkan ... Jadi nikmatilah!
sumber
Cara termudah adalah dengan mengimplementasikan database sebagai satu file yang dapat Anda transfer. Jika Anda mencoba untuk membandingkan perbedaan antara database maka itu adalah dunia yang menyakitkan, dan saya berbicara dari pengalaman.
Perhatikan bahwa server Anda tidak boleh mempercayai keputusan yang dibuat klien berdasarkan database lokal itu, karena klien dapat mengubahnya. Itu harus ada murni untuk detail presentasi.
Tidak. Bagaimana jika server memutuskan acara tidak pernah terjadi? Klien tidak seharusnya membuat keputusan tentang peristiwa, karena klien tidak dapat dipercaya.
Saya perhatikan Anda juga berbicara tentang DB lokal dalam dua cara: satu, untuk "hal-hal yang tidak sering berubah" dan dua, untuk acara. Ini tidak boleh benar-benar berada di database yang sama, karena alasan di atas - Anda tidak ingin mulai mencoba untuk menggabungkan atau mengubah baris data individual dalam database. Misalnya, integritas referensial menjadi masalah ketika klien memiliki referensi ke item yang Anda putuskan untuk hapus dari server. Atau jika klien mengubah satu baris dan server mengubah satu baris, perubahan mana yang diutamakan, dan mengapa?
Ya, asalkan mereka cukup jarang atau kecil. HTTP tidak efisien bandwidth jadi ingatlah itu.
Jika Anda menggunakan protokol sementara seperti HTTP, maka itu ide yang masuk akal. Ketika server menerima pesan dari klien, Anda dapat memperbarui waktu 'terakhir terlihat' untuk klien itu.
Tidak, tidak sama sekali. Klien ada di tangan musuh. Cara mengembalikan suatu tindakan sepenuhnya tergantung pada apa yang Anda anggap sebagai tindakan dan apa efeknya. Rute termudah adalah tidak mengimplementasikan tindakan sama sekali sampai server merespons untuk mengizinkannya. Rute yang sedikit rumit adalah untuk memastikan setiap tindakan memiliki kemampuan rollback untuk membatalkan tindakan, dan menyimpan semua tindakan yang tidak diakui pada klien. Ketika server mengakui mereka, hapus mereka dari cache. Jika suatu tindakan ditolak, kembalikan setiap tindakan dalam urutan terbalik hingga dan termasuk yang ditolak.
sumber