AppWarpS2 game room resources management for mongo service

+1 vote
Hi I have AppWarpS2 game server solution and Mongo db service that we are currently developing and testing right now.

My question is around room management in regard to mongo client db connection with the java driver.

Server holds static client to our monngodb service:

   public class ClientSingleton
{
    // Client instance singleton as volatile (modified by different threads &
    // not cached locally: all reads and writes go straight to "main memory")
    private volatile static ClientSingleton uniqueInstance;
    // The MongoClient class is designed to be thread safe and shared among threads.
    // We create only 1 instance for our given database cluster and use it across
    // our application.
    private MongoClient mongoClient;
    private MongoClientOptions options;
    private MongoCredential credential;
    
    private final String password = "xxxxxxxxxxxxxxxxxxxxxxxx";
    private final String host = "xx.xx.xx.xx";
    private final int port = 38180;

    /**
     *
     */
    private ClientSingleton()
    {
        // Setup client credentials for DB connection (user, db name & password)
        credential =  MongoCredential.createCredential("xxxxxxxxxxx", "OurDB", password.toCharArray());
        
        // Setup client options
        // Don't to leave socketTimeout and connectTimeout at defaults (eg infinite) if connection hangs
        // for some reason will get stuck forever!
        // Set number of milliseconds the driver will wait before a connection attempt is aborted, for connections
        // made through a Platform-as-a-Serivce (PaaS) it is advised to have a higher timeout (e.g. 25 seconds)
        // Set number of milliseconds the driver will wait for a response from the server for all types of
        // requests (queries, writes, commands, authentication, etc.).
        // ConnectionsPerHost
        // ThreadsAllowedToBlockForConnectionMultiplier maximum number of threads that may be waiting
        // for a connection to become available from the pool.
        options = MongoClientOptions.builder()
                .connectTimeout(25000)
                .socketTimeout(60000)
                .connectionsPerHost(100)
                .threadsAllowedToBlockForConnectionMultiplier(5)
                .build();
        try
        {
            // Create client (server address(host,port), credential, options)
            mongoClient = new MongoClient(new ServerAddress(host, port),
                    Collections.singletonList(credential),
                    options);
        }
        catch (UnknownHostException e)
        {
            e.printStackTrace();
        }
    }
    
    /**
     * Double checked dispatch method to initialise our client singleton class
     *
     */
    public static ClientSingleton getInstance()
    {
        if(uniqueInstance == null)
        {
            synchronized (ClientSingleton.class)
            {

                if(uniqueInstance == null)
                    uniqueInstance = new ClientSingleton();
            }
        }
        return uniqueInstance;
    }
    
    /**
     * @return our mongo client
     */
    public MongoClient getClient() {
        return mongoClient;
    }

}

I understand failure to properly utilise connection pooling is one major “gotcha” that greatly impact Mongo db performance. Also creating new connections to the db is expensive and I should try and re-use existing connections. I've not left socket timeout and connect timeout at defaults (eg infinite) if connection hangs for some reason I think it will get stuck forever! I set number of milliseconds the driver will wait before a connection attempt is aborted, for connections made through a Platform-as-a-Serivce it is advised to have a higher timeout (e.g. 25 seconds). I also set number of milliseconds the driver will wait for a response from the server for all types of requests (queries, writes, commands, authentication, etc.).

The mongodb holds question data for quiz game. Server creates room for quiz game from game table properties (based on your trivia quiz example) and moves players to room which calls mongo singleton and gets reference to client and db.

Following a game or I should say after an room idle time the room get destroyed - this idle time is currently set to 60 mins. I believe that if connections per host is set to 100 then while this room is idle then it would be using valuable connection resources as room holds client connection to db. If I have several hundred concurrently connected games and each accessing the db to pull the questions then maybe following that request free up the client connection for other rooms to use? How should this be done? I'm concerned about possible bottle necks here!

How could I clean up connections to db here as I understand that static rooms created in dashboard cannot get deleted? If server creates room that was created in dashboard can the server delete this room? If so how would I delete this room (what is the API) for this. If not then I think I should clean up the resource to client db connection following a successful retrieval of questions from db? Can this be done?
asked Aug 6, 2015 in AppWarpS2 by wiredvoltage (84 points)
edited Aug 6, 2015 by wiredvoltage

2 Answers

+1 vote
 
Best answer

Hi,

You can delete Dynamic Rooms using deleteRoom APIStatic rooms cannot be deleted using above API. Static rooms will only be deleted from Dashboard.Although you don’t have to worry about clean up the connections yourself.

MongoDB connection pooling is smart enough to deal with all your concern. Even though you have set connection limit to 100, it will not create it while initialization, it will just start with minimal connections (say 1 or 5) Also, it is always a good practice to keep this number on lower level (I think 10-10 is optimal number if your mongo operations can be completed in few milliseconds). When your room logic calls any operation on MongoDB, it internally takes connection from pool and return it once operation is done. It does not hold it for rest of the time. When you delete the room, you actually don’t need to do the clean up because your client is actually not holding any connection (It only holds it for the time being while operation is getting processed, for example while you fetch the questions from db). When the system will be shutdown gracefully, connection pool will terminate all the connections from server.

Let me know if you have further queries.

Thanks.

answered Aug 8, 2015 by rajeev.etc (1,660 points)
selected Aug 8, 2015 by wiredvoltage
Hi rajeev fantastic that completly makes sense to me now. Thanks for clearing that up. During testing I found that client requests to the mongodb and back again averaged a time of 0.100 sec so maybe I'll try and lower the connection numbers in production model and carry out some tests.
0 votes

Hi,

We have one query i.e. when you are fetching questins from your server

  • onRoomCreation or
  • on TimerTic

Also, are you fetching one question at a time if so, then I would like to suggest that you should fetch sets of questions on RoomCreation.

So that Whenever a user make a request for next or previous question you can return the same from existing sets of questions based on index and previous/next parameters.

If you can share the control flow of the app (from user's perspective and server side) then it will be really helpful for us to support you in a better way.

Thanks & Regards

Vishnu Garg

AppWarp Support Team

answered Aug 6, 2015 by Vishnu Garg (674 points)
@Vishnu Thanks for you reply - our room collects a set of questions from the db upon room creation.

More info regarding project here on Code Review which may help!?

http://codereview.stackexchange.com/questions/99139/multi-player-game-server-accessing-and-querying-mongodb

Look forward for your reply on how best to manage game room resources...
Download Widgets
Welcome to ShepHertz Product line forum, where you can ask questions and receive answers from the community. You can also reach out to us on support@shephertz.com
...