Herkese Merhabalar,
En kısa ve en öz soru : Hearthstone, CS:GO vb. gibi turn-based ve sunucuya 2-16 kişinin bağlanabildiği, bağlanırken en iyi sunucuyu seçip, birini araması, yüzlerce sunucuda game-server kurulu, load balance sistemi ile çalışan, tek veritabanı ile kontrol edilen bir sistem nasıl yapılır ?
Kısa ve öz soru : C# kullanarak(Kesinlikle ve kesinlikle C# olacak, web server kullanmayacağım.), birden çok sunucu ile her sunucuda "master-game-server" olmak üzere ve bu server'da aralarında "realm" paylaşarak her realm maksimum 2 kişi kaldıracak, MongoDB gibi bir NoSQL server ile veriler paylaşacak, saniyede 10k anlık tcp paketi kaldıracak bir sunucu sistemi yapmak istiyorum ve yolun ortalarında gibiyim, sona ulaşamıyorum. Bilgi yetersizliği, optimizasyon, tek veritabanı sunucusu çökerse çok kötü sorunlar olabilir, aynı anda aynı işi yapan 5 veritabanı sunucusu olabilir vs.
(Örnek: Hearthstone server - 2 kişilik, session aktarımı, turn-based vs.)
1) Böyle bir sistem nasıl yapılır ?
2) Böyle sistemi kolay yoldan sağlayan AWS var sanırım, SUPERCELL sunucuları bunu kullanıyor. Yada bu forumda sağlayan varmı kolay yoldan ?
(Not: Çok fazla teknik bilgim yok, biraz daha türkçeleştirerek anlatırsanız çok memnun olurum. Sorun yazılımsal mı, donanımsal mı en ufak bir fikrim yok. Hearthstone C# ile yazıldığından kaynak kodlarını okuyabiliyorum. Oyun içi haberleşme "google protocol buffers" ile async socket ile bağlantı sağlıyor. Bunu yapmak çok zor değil fakat hangi sunucuya bağlandığı vs. detaylı bilgileri anlayamıyorum. Birçok SSL gibi şifrelemeler kullanılmış. Çok komplex bir sistem yazılmış.)
Derin Mevzu :
Böyle bir konu'm vardı bununla alakalı :
https://www.r10.net/dedicated-server-...-database.html
Bunun devamı olarak buraya tekrar konu açmayı tercih ettim. Siz üstad'lara birkaç soru sormak istiyorum;
Öncelikle ben C# ile TCP (veri kaybı, sırasız gitme vb. olmaması için) tabanlı Asynchronous kullanarak bir server-client yazdım. Mobil-PC arası gayet iyi bir şekilde çalışıyor.
Veritabanı ise tek sunucu olup MongoDB düşünüyorum.
Amacım "Scalability" kullanarak "Horizontal scaling" modunda çalıştırmak istemem.
(Konu karışmaması için soruları anlattığımın altına soracağım, biraz ıvır-zıvır anlatayım önce.)
Soru 1 :
Şimdi, örnek olarak benim 11 adet sunucum olsun. Her 2'si farklı şirket, farklı ülke, farklı alt yapı. 1'i ise DB server.
2 Server - A Ülkesi - AANET
2 Server - B Ülksei - BBNET
2 Server - T Ülkesi - TTNET (Allah Korusun)
...
1 Server - D Ülkesi - DB Server
Tek veritabanı sunucusu sorun çıkarabilir, kapanırsa oyun sunucuları iletişim kuramaz, bilgiler RAM'de durur, bir süre sonra hata verip çökebilir. Bu çok riskli birşey. Büyük şirketler bu sorunu nasıl çözüyor ?
Soru 2 :
Eğer ben game-server için güncelleme yapmak istesem, bütün sunuculara tek-tek girip hepsini ayrı ayrı mı güncelleyeceğim ? Bu çok mantıksız. Adamın 100 sunucusu varsa ? 100 adet ayar.ini dosyası demek. Hepsini tek tek değiştirmek çok uzun sürer, aynı anda olmaz.
Soru 3 :
Client bağlandığı zaman rastgele bir server seçecek. Bu client tarafına yazdığım IP adresleri yardımı ile olacak. Peki oldu ya, şanstır, eşit şekilde paylaşılmadı, %90 A sunucusuna bağlandı. Bu büyük bir sorun demek. Bu sorunu çözmek için sunucular arası bağlantı gerekir. 100 Sunucu olsa, her sunucuya 99 adet diğer sunucuları tutan bir liste yapmak gerek ki, sunucu dolduğuna yakın, kullanıcının "session" dediğimiz durumu diğer sunucuya göndersin. Bu sorun nasıl çözülecek ?
Soru 4 :
Load balancing ve cluster arasında fark tam olarak nedir ?
Soru 5 :
SUPERCELL firması, AWS kullanıyor. Load-Balancing olaylarını otomatik yapıyor sanırım. Fakat sadece bunu biliyorum, arkada derin bir ayar var. Böyle bir sistem yapan kaynak vs. varmı ?
Soru 6 :
Can alıcı nokta, matchmaking sistemi. Evet. A kişisi odayı A sunucusunda kurdu , 30 sn'dir bağlanan birisi yok, biri(leri)ni bekliyor. Peki client B sunucusunda, teknik olarak A kişisinin kurduğuna bağlanması için bulunduğu server'dan A sunucusuna taşınması gerekir ki bu boşuna makineye bağlanma demek. Zaten kesinlikle ve kesinlikle oyuncular karşılıklı oynayabilmesi için aynı sunucuda olması gerekli. Örneğin CS'go da oyuna bağlanırken sol tarafta, kaç server olduğu (gerçek sunucu değil, 16 kişilik oyun sunucusu), kaç oyuncu olduğu vs. herşeyi topluyor, biliyor. Matchmaking sistemini nasıl tasarlayacağım ? Her sunucuda boş bir list oluşturup mu bakacağım ? Bu yapılır fakat tek sunucu üzerinden olur. Onlarca sunucu ile nasıl yapacağım ?
Soru 7 :
Bunları yapanlar biliyorum ki büyük firmalar, büyük üstadlar. Fakat hizmeti sağlayan, kullandıkları servis vb. aynı şirketin ve bizde kullanabiliriz diye düşünüyorum, ya da bu hizmeti yapacak firmalar varmı ?
------------------------------------------
=================================
vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
Dediğimi çok anlatamadım ve uzun oldu biliyorum, cevaplamaya çalışırsanız çok mutlu olurum. İnternette kaynak çok sınırlı ve istediğim gibi bulamadım da diyebilirim. Tekrardan teşekkür ediyorum, iyi forumlar !
^^^^^^^^^^^^^^^^^^^^^^^^^^^
=================================
------------------------------------------
C# - Cluster - Load Balancing - Parallel Server Tasarımı
6
●1.167
- 05-03-2016, 21:59:10Hepsini okuyamadım post'un gerçekten uzun olmuş
Şu keywordlere bakabilirsin.
IIS + Application Request Routing (Clustered ortam için)
HAProxy + Nginx (IIS'in önüne static caching ve High Availability için)
Redis (.NET için Sessionları burada tutabilirsin ki Scale edilebilir sistem için bir session server önemli) - 06-03-2016, 10:47:21daha afyonum patlamamışken böyle bir konu ile karşılaşınca afalladım. sanırım daha önceki konuda da yazmıştım birşeyler. burdaki sorularına basit, anlaşılabilir şekilde cevap vermeye çalışayım. bilinenlerin aksinde yabancı terim kullanmadan, biraz da sana araştıracak noktalar bırakarak;
1. tek veritabanının problem yaşatacağını söylemişsin ki, kesinlikle doğru. bunun için uygulaman gereken yöntem : replication
2. konu dışında bir açıklama yapayım. aynı anda birden fazla client'a bir iş yaptırmak istiyorsan, en kolay yöntemin adı : servis (service) . "oyun sunucularının client olduğu ve ayar değişikliklerini sorgulayıp alabilecekleri (get)" ya da "değişiklik yapıldığı zaman bu değişiklikleri tüm ya da belli oyun sunucularına gönderecek (push)" bir servise ihtiyacın var. en senkronize yöntem push'tur. (bu kelimenin okunuşu abes oldu, esnerken yazdım) şayet konu sadece ayar dosyaları ise, oyun olarak bakmaman daha mantıklı. ufak bir dosya senkronizasyonu da bu durumu çözebilir.
3. 6. cevaba bakabilirsin
4. çok çok basit olarak cluster yapısındaki servisler, birbirleri ile bağlantılıdır. load balancing'de ise bağımsızdır. senin yapın için kullanacağın load-balancing.
5. bilmiyorum.
6. senin sistemin için kullanabileceğin iki yöntem olduğunu düşünüyorum. öncelikle;
- 3. soruna "Client bağlandığı zaman rastgele bir server seçecek." şeklinde başlamışsın. Rastgele seçim durumunda senin düşündüğün problem ortaya çıkabilir. "sıralı" olarak atayabilirsin. kaba anlatımla bir sunucu dolmadan diğerine göndermez.
- diğer bir yöntem ise, havuz yöntemidir. oyun isteklerini havuza atarsın, başlayabilir oyuncu sayısı havuzda biriktiğinde, o oyuncuları oyuna alırsın. genelde bu yapının kullanıldığını düşünüyorum.
en basit en anlaşılabilir şekilde cevaplamaya çalıştım. - 06-03-2016, 11:26:16c1982 adlı üyeden alıntı: mesajı görüntüle
Redis'i neredeyse herkes den duyuyorum fakat ne olduğunu araştırmama rağmen hâlâ anlamış değilim. Bir nevi SQL Server gibi sanki.
foo adlı üyeden alıntı: mesajı görüntüle
Şimdi "replication" yöntemi sanırım db sunucularının aralarında senkronize olarak aynı bilgileri aynı işleri yapması. Bu cepte.
"push" yöntemini de araştırdım, diğer konuda da geçmişti. Sanırım bunu kullanacağım.
Herşey tamam, ama asıl sorun olan can alıcı şey, load-balancing nasıl yapılacak ? Windows server kullanacağımdan bir port'a 15K kişi bağlanınca artık port hatası veriyor. Bu da bir sunucuya 15k kişi bağlanabilir demek. 10M kişi için 1k sunucu demek. Ki olmaz da tanesi 50TL olsa 50k TL aylık ? o.O
Bu kadar gider yapmayıp, bu kadar kişiyi kaldıran sunucuları görüyoruz. Mesela agar,io server C++ ile yazılmış. Fakat yapımcısı bu konu hakkında pek detay vermiyor. Bunu örnek verme sebebim, tam istediğim çalışma prensibi olması.
Daha basit olmak gerekirse, C# ile Windows sunucu, MongoDB kullanarak, 5 adet sunucu ile en fazla kaç kişi kaldırabilir, nasıl yapılır ? - 06-03-2016, 12:00:12kahve ve sigara sonrası biraz ayıldım. kaba olmasın ama çok yanlış düşünüyorsun. senin düşündüğün yapıda, "load-balancer" oyun sunucuların ile oyuncular arasında aktif olarak duruyor. oyun sunucuları ile oyuncular arasında trafik load-balancer üzerinden geçerse senin dediğin gibi olur. benim dediğim sistemde adına load-balancer demeyelim, "yönlendirici" diyelim kafan karışmasın.
şöyle olsa nasıl olur : yönlendiricinin amacı, oyuncuyu doğru sunucuya yönlendirmek olsun. oyuncu, yönlendiriciye bağlanır, yönlendirici isteği alır, database'e yazar, varsa diğer kontrollerini yapar, skor tutar vs, sonra oyuncuya hangi sunucu boşsa ona bağlanacağını döndürür ve bağlantıyı kapatır. oyuncu gelen cevaba göre, o oyun sunucusuna bağlanır. aynı anda her sunucuda 10K oyuncu varsa, 100 oyun sunucusu ama önde 1M oyuncuyu bu 100 sunucuya yönlendirecek 1 veya 2 yönlendirici. - 06-03-2016, 22:25:53foo adlı üyeden alıntı: mesajı görüntüle
Dediğiniz kafama yattı. Fakat 1 Yönlendirici olursa gene sıkıntı olur. Bu da "replication" yöntemi olarak bahsettiğiniz mevzudan yapılabilir. Peki, bunları yaptım diyelimü herşey güzel fakat büyük bir sorun var. O da port limiti. Şimdi 1 harita maksimum 4 kişilik olsun. Bunun adına da "realm" diyelim. Her sunucu da 3.750 farklı duello demek eğer her sunucu 15K ile sınırlandırırsak. Benim sorunum ise 15K dan daha fazla kişi nasıl alabilirim.
https://blog.whatsapp.com/196/1-million-is-so-2011
Böyle birşey de istemiyorum fakat her sunucuya 50K kişi katılsa fena olmaz hani. Windows-C# ile bu bir sorun gibi. - 07-03-2016, 11:40:22yönlendirici sayısını istediğin kadar arttırabilirsin. yönlendiricilere eşit olmasa da yine de dağıtım istersen dns load balancing yapabilirsin.
port konusuna gelince;
şayet senin yönlendiricin ya da sunucuların "client" olarak davranıyor ise yani başka bir servise tcp/udp gibi bir protokol ile bağlantı yapıyorsa, bu limitin söz konusu olur. server - client yapısı gereğidir. genellikle web sunucusunu düşünebilirsin bu durumda. sunucu 80 portunu dinler. client sıralı bir port üzerinden, sunucunun 80 portuna bağlanır. Aynı client üzerinden aynı anda açık 100K bağlantı olduğunu düşündüğünde, client üzerinde aktif 100K port olması lazım, ama sunucu sadece 80 portunu dinliyor halen.
yukarda belirttiğim yönlendirici yapısını kullanırsan, yönlendirici, arkadaki oyun sunucularına aktif bağlantı yapıp, oyuncuya iletmeyeceği için sadece oyunculara cevap verecek tek bir port dinleyecek. burada dikkat etmen gereken nokta; yönlendirici örneğin remote bir sql ya da nosql sunucusuna client olabilir. o zaman bu limit karşına çıkacaktır. ama oyuncu tarafından gelen istek cevaplanıp kapatılacağı için anlık 60K veritabanı bağlantısı çok yüksek bir değer
verdiğin linkteki değerin abartılacak bir durumu yok. her tcp bağlantısı kernel seviyesinde bir miktar ram kullanır. sunucunuzdaki ram miktarına göre arttırabilirsiniz. tabi socket bağlantıyı alıp kullanan servisin de ne kadar ram kullandığına göre belirlersin. güncel bir sunucu üzerinde 1 milyon kolay bir rakam. tabi ordaki sunucunun freebsd olduğuna da dikkat edin, freebsd zevklidir.