How does one scale dedicated EC2 instances on AWS? - java

I'm creating on online real-time multiplayer mobile game using Kryonet (a Java TCP/UDP networking library) that I'm planning to host on AWS.
The architecture is as follows: clients connect to a central login/account server that allows them to login and view their stats etc. This bit is easy, as it'll basically just be a REST API, and can be scaled in a pretty standard way (like you would any webapp).
However, the more interesting bit is when players actually play a match. For this, I plan to have a separate pool of "match" servers (EC2s). The login/account server will pair two players, then send the client the address of a particular match server. The players will then join that match server, which will host their match (perhaps lasting 5-10 minutes). The match server needs to be sticky as it will be running a real-time instance of the game, and will be sending/receiving UDP packets in real time. Each match server will probably be able to host a few hundred matches.
My question is about how I should go about scaling these match servers. I suppose I will have them auto-register with the central server at start-up, and send some type of keep alive. I could build this all myself; however, I'm wondering if AWS has tools/services that can do this all for me.

Okay, I've done a little more reading of the AWS documentation. It seems that I can probably achieve this as follows:
Each time two players are paired up, they are added to a queue. They are taken off the queue when a spot is free on one of the match-playing servers. When the size of this queue exceeds some threshold, then the number of EC2s is scaled. This can be done with basically all in AWS config: http://docs.aws.amazon.com/autoscaling/latest/userguide/as-using-sqs-queue.html
The tricky bit is then scaling down instances. Unlike a normal REST API, you can't just turn a server off. The server needs to finish all its current games. It seems that AWS has this covered too with lifecycle hooks.

Related

How to notify client-side of an Instant-Message (IM) app of updates?

I've been through different questions about this topic, however, none of them have cleared my doubts on the best approach notifying the client side of a server-client IM app.
The Problem:
The whole problem is how to notify the client application of updates. I've alread seen the following approaches:
Clients keeps checking for updates: From time to time, client app performs a check in the server to see if there are updates for that specific user;
Problem: it is not performatic at all. Suppose you have one million users and each one of them checks for new updates every second. Serve would have to deal with one million requests per second. Wont work.
Client app opens a socket: The client app opens a socket and sends its address to the server. Server, by its turn, persists this information and connects to the socket whenever it needs to notify the client of some update.
Problem: Often the client will be connected to a NAT, so, the IP it has access to is in a non-visible range. In order to send messages to this client, a port forwarding in the NAT would have to be configured, which can't be done.
Despite of the technology, I think this approach will always be used, however, I have no idea how the problem described above can be solved.
Google Cloud Message (GCM): use the GCM service to notify the client of any update. Problem: It does't seems right to use a third server to handle the IM and it raises concerns about the scalability of the system. When the number of messages and users increases exponentially, it seems that the service will go down. Despite that, it seems that passing the information for two servers before delivering to the targets just adds bottlenecks in the process.
A combination of 2 and 3: uses GCM to reach the client when the last persist addres is no longer available.
Problem: same as described in 2
XMPP: I've seen many answers indicating the use of XMPP for IM applications, however, XMPP is a protocol - as per what I've foun in the web. I don't see how it can solve the problem described in 2 for instance.
Given the options above, can someone indicate me what line should I try to go for? Which one of these approaches has the best chances of success?
Thank y'all in advanced.
Use Google Cloud Messaging. Opposing to what you stated this service is built to scale to billions of users it will generally not introduce performance bottlenecks.
What you basically want to do is to use the messaging service to wake up devices. If you insist you can then still use your client server approach and thus your own protocol to have the client lookup new messages from the backend.

Networking with a remote java program

I'm looking to have a network of bukkit servers that all operate under a single game mod that allows for inter-server communication. The conventional way to do this is to utilize a MySQL database and have all the servers pull from the database periodically (5 seconds or so) to keep all the servers up to date. I'm wondering if there is a better way to accomplish this.
I have an idea, but I don't know enough about networking to know if it is feasible. I'm considering having the game mod run under it's own java server (here-on referred to as the mod server and not related to bukkit). The mod server will have all the data associated with the mod and it will be responsible for executing all the computation regarding the mod (handling money transactions, adding and removing claimed land, and dealing with the tax cycle). All the bukkit servers interface with the mod server whenever it needs to determine if, for instance, a player can break a block, or hurt another player. All changes to the data of the mod is done on the mod server. The bukkit servers are essentially just portals to interact with the mod server. As long as the mod server is single threaded, then there shouldn't be any concurrency issues, race conditions, or conflicts.
I've been reading into Remote Method Invocation and I was thinking that maybe it was the avenue to accomplish this. The mod server would be considered the RMI server, and the clients would be the Bukkit servers. I read through the documentation for the Java Sockets, but I'm not sure that it's what I'm looking for. I'm having a difficult time googling it because it's only a concept for which I don't know all the technical terms. Any ideas or suggestions? Thanks.
Each bukkit server should be in charge of managing the players on it and only those on it. Thus you don't need this mod server to handle SQL when you can simply load player data when a player joins that specific server. Any updates to the player can be done on the local data and then committed to the database when the player leaves or when it happens. As an example, or server uses zPermissions for cross server permissions. It updates on change and players who change to another server have all their permissions from the original. The only problem here is when the group permissions change which simply needs a permissions reload to update, but those will not change often once your server gets organized.
Are you using BungeeCord? If you are, you can create your own plugin channel.
You can send and recieve data from every subserver (bukkit server) to the master server (bungeecord proxy) via your own channel. Here is an explanation:
http://www.spigotmc.org/wiki/bukkit-bungee-plugin-messaging-channel/#the-bungeecord-plugin-channel

Realtime data transport architecture

I have a concept of a game system that includes (preferably) Java server and multi-platform clients (Web, Android, iOS).
This is a 1vs1 player-vs-player realtime game. Servers performs a matchup of 2 players. So basically server needs to handle many matches containing 2 players. Both players alter same data, and each player should be updated in realtime with actions of other player.
Can you suggest me:
1) Server-side framework/library that would ease the implementation, as I would rather not start learning node.js from the scratch. :) Vert.x comes to mind.
2) Should clients hold the replica of the data, and alter it locally (meaning only data that is transfered are only commands, here I see JMS as good solution), or should only server alter the data and then send the complete data set every time change occurs?
3) How should the data be transfered? Considering the multi-platform requirement only thing I see viable are WebSockets.
4) An example/tutorial of server handling pairing of WebSocket connections? All I ever found are 1-to-1 connections.
5) Considering scalability, can you explain how could all this work in a distributed environment?
1) I don't think node.js is such big deal to learn. I would personally prefer a well known - broadly used framework.
2) If you are considering mobile, probably the first option seems more sound. You should consider send/push deltas during the game, and still provide functionality to retrieve the full state of the game in case the client disconnect and connect with same ID.
3) WebSocket would be the best option. Push approach, TLS option and well supported. Another option is the WebRTC data connection, that is peer-2-peer most of the times. I say most of the times because if one of the users is behind a dynamic NAT router or restrictive firewall, it won't be possible, and you will need a TURN (relay) server. Anyway, it is less supported than WS.
4) You should not "pair websockets". The WS connections just input commands to your logic, and your logic broadcast events to whoever it wants. Despite of being a 1vs1 game, probably you want to inspect the flow of events for further debugging or analysis. So consider WS as a transport, not as an entity.
5) Very, very, very broad question. But assuming that you are going to use WS, and that your application will be so successful that you will need multiple servers... assume that it is impossible to predict that two users will connect to the same server, so you should consider a message bus that allow to play users from one server with the users in other server. An EDA (Event Driven Architecture) would make sense.

Using multiple servers in Java

For a college assignment I'm building a networked Java application using sockets*. My architecture must be scalable so I would like to have multiple servers available for my clients to communicate with.
My question is, how can a client know about all available servers? My first thought is for the clients to keep a (hardcoded) list of server IP addresses and select from the list. What is best practice in this case?
*We cannot use RMI.
Let's imagine your network provider's costs got too high, and you decided to switch. Boom go your IP addresses. I would suggest the judicious use of DNS, especially round-robin DNS.
Using a central tracker could seem like a good idea, but it itself must be scalable, akin to Google App Engine, or it will become a chokepoint.
Simply create multiple A-records for a given name, and your clients will randomly select one when resolving.
If you are unable to use DNS an IP list may be beneficial--with one change. All of the servers circulate updated copies of the list and if a server cannot be reached, another is tried until a connection is made(and the list likewise updated). When the list is found to differ from the existing one the client's list is updated.
You can use RMI stuffs, making primary and secondary servers.
Secondary server may be continuously polling primary, when primary goes down, secondary can register on naming services to take on. When primary comes back, it will register back making secondary go down... like that.
Regarding client to know server, client can ask servers using RMI for identity.

Running java server application 24/7 and secrets behind all those famous online live apps

I'm currently building an application that is about VOIP / random chatting, which is similar to skype or chatroullet. My question is extension to this
https://stackoverflow.com/questions/11384155/running-java-server-application-24-7-not-on-local-machine
I've been experimenting and playing around with TCP / UDP sockets and now I have ability to build VOIP / instant chatting applications. But as you might already know, in order for data transmission between client to client or client to server, the server application has to be powered on (in other word, be online) and be accessible by client applications. The problem is that, I'm not living by my self but with my family, which I can't simply use one of my computer to run my server application for 24/7 mainly due to the electricity bills and my lack of knowledge about the networking concerns me about the security, because I had to go through some configuration / port forwarding on my current router in order to make the protocol accessible by other users outside of my local network. So my biggest question is that, how do people or developers normally have been dealing with this kind of situations? Have they been simply using their own computer to run the server application? or have they purchased an external machine to run the server application
===========================================
Additional question:
Is TCP / UDP socket the only way of making applications such as MMO, VOIP and instant chatting programs?
i see that your topic was closed in the previous thread. I think such questions are unrelated to stackoverflow.
However, i would like to give you a glimpse of what is happening to most of us who own / make Java Web Applications. I used to work in a datacenter for a year and a half. Java applications are a little harder to put online as they require resources that not many data centres are willing to invest time and support in. Other than that, they are pretty much as straightforward as normal PHP applications.
You will need the standard options like Colocation, Dedicated Server, VPS, Cloud Virtual Machine, or a shared tomcat / application server hosting.
Colocation is where you put your own purchased and configured server with the data center, you have complete ownership of the server, nobody can touch it unless permitted by yourself. You pay to put your server into the data center, and are in charged of anything that happens within the server, including OS patch.
Usually servers in data centers (due to size constraint) come in rack units. 1U refers to 1 rack space, usually this is equivalent to one PC, although a server is much more powerful. In Singapore, the charges per U is SG$200.
Dedicated server is where you lease a server from the data center. The server is managed by the data center and can be as powerful as you want it to be. OS updates, installations, service guarantees are provided by the data center.
VPS is having a fraction of a server resource, but many challenge that you do not have the "root" access to the server in most cases.
Cloud is the virtualization of the entire operating system. If this was Linux, you would have the root access to it. Many of us now are going for this option because of its scalability. Some data centers may use popular virtualization hypervisors like VMware ESXi, Microsoft Hyper V.
The list above is represented from the most expensive to the least. Of course, that is depending on your location and service provider.
Hardly anybody i know tries to put a running server at home, it is a fire hazard itself, you will not know when your electricity will be cut off, standard dedicated bandwidth would as expensive.
Hosting with a data center would be much cost efficient and safer in my opinion.
EDIT:
Is TCP / UDP socket the only way of making applications such as MMO, VOIP and instant chatting programs?
Have you looked at HTML 5 Web Sockets, or any AJAX based framework for this?
Try searching the web for cloud hosting. For example, Heroku, AWS and many others provide a hosted service. That is what people use to host their service and it is more cost effective than trying to maintain something yourself.
Are you writing an Android application for it as well? Just as an aside you might want to make use of this ARO tool to ensure you are using the network efficiently. http://developer.att.com/developer/legalAgreementPage.jsp?passedItemId=9700312

Categories