I am developing a multiplayer online game. I have the following issue:
When the user breaks his/her connection with the server, he needs to reconnect. At the first connection, during registration, the registration module produces a special ResponseDispatcher which holds the reference to the connection Channel. But if the user logs out, this Channel becomes invalid. Even though I can detect the problem and clean up resources, I have to store the reference to the registration module and Connection module to the game module, in order to renew the Channel when the user authorises and reconnects again. This creates a lot of interdependencies among modules and it gets really hard to maintain.
What I need is something like an HttpSession in Servlet Container, so that I can get the references to my channel and session resources from all modules of my server.
How is HttpSession implemented in Servlet? Is it a global hashmap storing all JSESSIONID, from which the container determines which attribute map to return? If it is a global sysmbol table, will it hit the performance (even though the time is O(1) for hashMap, there might be session modifications so it probably has to be synchronized)?
PS. Maybe some recommendations of design patterns for this case would also do.
I would recommend trying Shiro
Shiro can handle Session Management outside of a servlet container.
You may want to back Shiro with EhCache to provide proper caching and, if required, session persistence (and load balancing, etc...)
Have a look at the Facade Pattern
I'm not exactly sure what the question is. Why do you "have to store the reference to the registration module and connection module"?
Anyway there are two immediately sensible solutions to your problem.
1) Make the Registration module and Connection module Singletons. Whether this is useful depends entirely on what functionality these modules provide.
2) Make the Registration module and Connection module Persistent Entities, save them to a DataStore, complete with necessary references, and retrieve and rebuild them on reconnect.
I'm not quite sure why rolling your own session implementation would be something you want to do, what happens when the session times out?
Your design seems somewhat flawed. The player should not "still be online" if his connection goes down (this is a contradiction in terms, you cannot by definition be online if you are not connected to a network), regardless of whether this was intentional or not (you cannot know whether it is intentional or not), you have no idea whether the player is able to reconnect within a timely fashion or not, so you should assume the worst. More importantly, from a purely design aspect, getting killed by the game, because your internet connection is rubbish, is probably not something you want to deal with. If persisting data is such a costly affair you should reexamine your datastore options. Also, what happens in the scenario where the server crashes while he's offline?
Related
I heard a web application should be as stateless as possible. But it seems to me very hard to realize this often. For instance, what if I:
Process a request
Redirect the user to the start page
Want to display the result of the request?
If the result is a little bit more complex, then just a string which could be passed as a parameter (or I don't want to include that information via URL), then I cannot combine 2. and 3.
The only solution I can think of here is keeping the information as states in the Java program.
But that would break with the rule of a stateles web application, wouldn't it?
I heard a web application should be as stateless as possible
What? There is state everywhere in a web app, both in the client and on the server. Frameworks like Sproutcore/Ember even have components called State Managers to manage, um, the state.
The server maintains some state in a user's session (typically).
Did you hear that HTTP is stateless? That's another story, and completely true. Also, it can be a good idea to write server side components that don't share state, due to threading concerns. But neither of those points should be taken to imply that your application doesn't have state.
I recently watched several Google I/O videos where Google developers present GWT with respect to performance and security. In that video the speaker makes mention of several GWT-isms:
Client-side request "batching"
"Disposability"
The pursuit of GWT app "statelessness"
With respect to "batching" it seems like GWT can be configured to queue-up server-side RPC calls and send them all at once (instead of many tiny, performance-hindering calls). Unfortunately, I'm just not seeing the forest through the trees here: doe GWT handle batching for you, or do you have to write the logic that performs this bundling/batching? If you have to do it, what kinds of calls can/should be bundled? How do you know when its time to fire the batch off?
In GWT lingo, what does it mean when someone says:
"Clients and servers are disposable"; but
"Views" are not disposable
How does this concept of "batching" and "disposability" relate to GWT app "statelessness". By that, the speaker defined statelessness as:
Browser embodies the session (?!?!)
Server is stateless - except for caching (?!?!)
Client never notices a restart (?!?!)
If someone could help give me concrete understanding of these 3 items and how they relate to each other I think I'll start to "get gwt". Thanks in advance!
doe GWT handle batching for you, or do you have to write the logic that performs this bundling/batching? If you have to do it, what kinds of calls can/should be bundled? How do you know when its time to fire the batch off?
GWT-RPC has no batching mechanism. You can (relatively) easily add some by queueing "commands" in a list and then sending the list as a single GWT-RPC call. Some projects should do that for you with minimal effort (GWT-Platform for example).
RequestFactory on the other hand has batching built-in: you create a RequestContext instance and batch calls to it until you fire() it.
"Clients and servers are disposable"; but "Views" are not disposable
The first is related to statelessness (and, for example, with AppEngine, you don't control when a new server instance is created, shutdown or restarted: the server can disappear at any time, so don't keep state in memory).
The second is about performance: everything related to the DOM in the browser is slow, so constructing a new view (widgets stacked together) is heavy-weight (less so with Cell widgets though). As a result, you don't want to make them disposable, i.e. throw them away every now and then. You'll rather want to keep one view instance around that you reuse for the lifetime of the app.
Not exactly the same notion of "disposability".
Browser embodies the session (?!?!)
GWT is built of single-page apps. You can store state on the client simply in variables in your app; you don't need cookies or whatever to have the state shared between pages.
Server is stateless - except for caching (?!?!)
Storing session state on the server has a cost (state must be persisted –particularly if the server is disposable–, shared between servers –when you have a cluster / run in the cloud–, etc. you'll spend as many resources keeping existence of your session state as doing actual business logic).
Client never notices a restart (?!?!)
HTTP is a a disconnected protocol. If the server is restarted, the client won't know about it, and it shouldn't have to know about it.
If someone could help give me concrete understanding of these 3 items and how they relate to each other I think I'll start to "get gwt".
It's not about getting GWT, it's about getting the Web and getting single-page webapps, and how to scale them.
Whether they're made with GWT or jQuery on the client-side, and Java or Python or .NET on the server-side doesn't matter.
Read about REST, it sums it all.
I need to check if existing web application is ready the be deployed in a clustered environment.
Cluster:
Several Linux boxes. The flow is controlled by a load balancer that is using simple round robin algorithm with sticky session.
Application
Stateless (hopefully) java web application that retrieves content from back office and format it appropriately.
I have access to the source code. What should I check in the code to be sure that it will run in the cluster?
Check that something is not cached in a memory or file system that stores state of the application.
...Something else?
If you're using EJBs (which is recommended if you access a DB), then here is a list of restrictions:
http://java.sun.com/blueprints/qanda/ejb_tier/restrictions.html
I guess similar restrictions apply to the web application.
The easiest way to check the application is to start by having it running on 2 servers with the same data so at startup both are in the same state. Let's assume for a user to complete an operation, the browser will make 2 consecutive HTTP requests to your web app -- what you need to do is hit webserver 1 with first call and web server 2 with second call; then try the other way around, then with both requests going to the same webserver -- and if you get the same result each time you're very likely you have ready-to-cluster application. (It doesn't mean the app IS ready to cluster as there might be object states etc it stores in memory which are not easy to spot from the front-end, but it gives you a higher probability that IT MIGHT BE ok to run in a cluster.)
If its truly "stateless", there would be no problem, you could make any request of any server at any time and everything would just work. Most things aren't quite that easy so any sort of state would either have to be streamed to and from the page as it moves from client to server, or be stored on the back end, and have some sort of token passed back and forth in order to retrieve it from whatever shared data store you're using for that. If they are using the HttpSession, then anything that is retrieved from the session, if modified, needs to be set back into the session with session.setAttribute(key,value). This setting the attribute acts as a signal that whatever is being stored in the session needs to be replicated to the redundant servers. Make sure anything stored in the session implements, and actually is, Serializable. Some servers will allow you to store objects, (I'm looking at you weblogic), but will then throw an exception when it tries to replicate the object. I've had many a coworker complain that having to set stuff back to the session should be redundant, and perhaps it should, but this is just the way things work.
Having state is not a big problem if done properly. Anyway, all applications have state. Even if serving somewhat static file, the file content associated with an URL is indeed part of the state.
The problem is how this state is propagated and shared.
state inside user session is a no brainer. Use a session replication mechanism (slower but no session loss on node crash) or session sticky load balancer and your problem is solved.
All other shared state is indeed a problem. In particular even cache state must be shared and perfectly coherent otherwise a refresh on the same page could generate different result on random depending on witch web server, and thus the cache you hit.
You can still cache data using a shared cached (like ehcache), or failing back to session sticky.
I guess it is pretty difficult to be sure that the application will indeed work in a clusterised environement because a singleton in some obscure service, a static member somewhere, anything can potentially produce strange results. You can validate the general architecture for sure, but you'll need to do in reality and perform some validation test before going into production.
I am maintaining a map of sessionid(s) and HttpSession Objects in my web app. I use an HttpSessionListener to populate or remove a session from the map. When my web server crashes and goes down and comes back up, i need a way to check if the sessionid being submitted is valid or not. Obviously, when the app comes back online, the Map is empty, therefore all session id's are invalid, but I just want some way to check the incoming sessionid, if possible, at all..
thanks
You can keep those in DB in some table. This way it will not suffer by the crash. And by the way, servers serializes the session to the disk, if you want them too.
One suggestion is to serialize your Map to disk and reload when the Web server starts up. The strategy to backup your Map to disk depends on your requirement, you could write to disk each time you add/update the map or in regular intervals. It is fairly easy to write your session data to disk, this is something that is often done for achieving redundancy and load balancing scenarios.
Why on earth are you maintaining the sessions yourself? The servlet container is supposed to do that for you. I haven't seen your code, maybe you have a good reason for doing what you're doing, but I get the feeling that you just don't understand the servlet API, and are trying to re-implement it yourself.
Also, you might be interested in this: Tomcat has a feature where it persists the sessions, which means that the session state survives a server restart. (Turn this off when updating the application, since there might be mismatches between different versions of classes.)
I have a JSF web client and a Java client that both use the same stateless EJB layer for their application logic. I'm unsure of how to balance the need for performance (limiting the amount of data that is transported between the presentation and application layers) with security (in the sense of ensuring all decisions are made based on up to date data).
I understand that this is a subjective topic, so perhaps I can make it more objective with concrete examples:
Do I only send the username to the EJBs, and then load the User entity on each and every EJB call, or do I send the User entity from the presentation layers?
If I need more information than just the User entity (let's say I need to load an additional entity on each EJB call), do I send the username and the other entity's key and load both the entities in the application layer, or do I send both entites from the presentation layers?
What about if I need even more information for certain EJB calls (>= 3 entities)?
When does it make sense to send the actual entity instead of just its key, or is the answer never, always reload on the application layer side? Should I be worried about performance? I've heard that Hibernate (which I'm using) employs intelligent caching meaning the User entity probably won't be reloaded from the DB every time? What if my EJB methods have a very small granularity and frontend actions might sometimes cause 3 or more EJB methods to be called, with each needing to load the User entity?
A final related question: I intend on using the JAAS principal to store the username which is loaded by the EJBs. What if my Remote facade EJBs call a bunch of Local stateless EJBs that also require the user information, do I still use the JAAS principal and load the User entity in each of them as well or is there a better way?
You should consider stateful EJBs, since it sounds like the clients need non-trivial state to answer a series of requests concerning the same state from one user. That said, stateful EJBs are kind of a bear to write and configure properly.
As a matter of design, I would not have the clients send user information to the business logic layer. One, it just punts the problem over to the client, no? to load, store and send this info? also it makes me nervous from a security perspective, to let a presumably less-secure client tier feed sensitive user data to a more-secure backend-tier which then trusts and uses that info.
But, really, I think you mentioned the best approach already: Hibernate's lazy loading. You just interact with the object and let it load data on demand. To work well with Hibernate in this regard, the User object should be small, so that loading it is fairly quick, and push all the big, heavy info into child objects or other entities. Then it doesn't matter if you have to load User a lot; it's just a bit of a 'pointer' to other info.
I don't think it changes things if you use JAAS, no. Although I might say, for what I imagine your purposes are, JAAS may or may not be worthwhile. In the time it takes you to integrate, write permissions, use those permissions, deal with consequences of the SecurityManager, etc. you probably could have just written a simple permissions framework for yourself anyhow.
if you make just one EJB, make stateless session. personally i found it humbug empty interfaces