Hi. What features of BlazeDS are you using? The messaging service requires sessions to work properly. If your request goes to another server instance, that instance won't know about your subscription state.
I guess if you were just making RemoteObject calls the session wouldn't matter as much but as you found out it looks like we do require sessions currently (although not cookies).
Can you tell me some more about your setup? Your clients are just browsers? Are you using a load balancer or something to route requests to different servers? And that load balancer or whatever is stateless and not using sticky sessions to pin a client to a particular server?
If you feel there is a valid use case for being able to disable session detection you can add an enhancement request in our bug database:
Thanks for the response.<br /><br />> What features of BlazeDS are you using? <br /><br />We use two AMF channels. One for normal remoting type operations and the other to receive messages from a JMS queue.<br /><br />-------------<br /><service id="remoting-service" class="flex.messaging.services.RemotingService"><br /> <adapters><br /> <adapter-definition id="java-object" class="flex.messaging.services.remoting.adapters.JavaAdapter" default="true" /><br /> </adapters><br /><channels><br /> <channel ref="nrt-amf" /><br /> </channels><br />-------------<br /><br /> <service id="message-service" class="flex.messaging.services.MessageService"><br /><br /> <adapters><br /> <adapter-definition id="jms" class="flex.messaging.services.messaging.adapters.JMSAdapter" /><br /> </adapters><br /><channels><br /> <channel ref="nrt-amf-polling" /><br /> </channels><br />-------------<br /><channel-definition id="nrt-amf" class="mx.messaging.channels.AMFChannel"><br /> <endpoint url="http://somwhere:80/messagebroker/nrtamf" class="flex.messaging.endpoints.AMFEndpoint" /><br /> <properties><br /><br /> <serialization><br /> <legacy-collection>true</legacy-collection><br /> </serialization><br /><polling-enabled>false</polling-enabled><br /><br />-------------<br /><channel-definition id="nrt-amf-polling" class="mx.messaging.channels.AMFChannel"><br /> <endpoint url="http://somewhere:80/messagebroker/nrtamfpolling" class="flex.messaging.endpoints.AMFEndpoint" /><br /> <properties><br /> <br /> <serialization><br /> <legacy-collection>true</legacy-collection><br /> </serialization> <polling-enabled >true</polling-enabled><br /><wait-interval-millis>60000</wait-interval-millis><br /><max-waiting-poll-requests>2550</max-waiting-poll-requests><br /><polling-interval-millis>0</polling-interval-millis><br />-------------<br /><br />> Your clients are just browsers? <br /><br />Yes.<br /><br />> Are you using a load balancer or something to route requests to different servers?<br /><br />Yes. At the moment, it uses a least connection algorithm to balance requests across systems. No session / transport layer work is being done there. No pinning or sticky sessions.<br /><br />I have a feeling that since our JMS connection uses long polling, and each reconnect may get a different server, there is some wasted session/connection overhead with our current setup. We are seeing memory problems (likely http://www.adobeforums.com/webx/.59b5bc91 or some other inefficency)<br /><br />- Can you explain a little how sessions are used (in the case of JMS)<br /><br />- Do you have a preferred setup/config in this case? I noticed that there is a blaze clustering option (would that do session replication?) If sessions are required, we'd like to ensure session efficiency and provide state failover as well.
>>Can you explain a little how sessions are used (in the case of JMS)
Messaging works pretty much the same whether you are using JMS or not. A client subscribes to one or more messaging destinations on the server. There is a message queue on the server that contains all of the undelivered messages for the client. When a new message is sent to a destination and the client is subscribed to the destination, the message gets added to it's message queue. The way that messages get delivered to the client depends on the channel/endpoint that is being used. In the case of long polling, the client makes an initial poll request to the server. If there are no undelivered messages for the client, the request gets parked on the server until new messages come in.
The session is used to associate the client with the information we have about the client on the server. . . what destinations the client is subscribed to, the queue of messages to be delivered to the client over a given endpoint, etc.
I'm not sure exactly what will happen if you use a load balancer that doesn't do session pinning but things definitely will not work properly.
In the best case scenario with long polling, poll requests to a server where the client didn't have any subscriptions would just be ignored. This wouldn't be great because with your least balanced algorithm, you wouldn't be sure when the poll request would get to the right machine and the load balancer would be slowing things down at that point when you want it to speeding things up. A worse scenario would be that I think you could potentially get subscribed to the same destination on multiple servers. If that happened, the client would have a message queue on each server. The client could get duplicate messages or the queues could just hang around with the client never retrieving the messages.
Something like that could cause your memory problems. Most memory problems like this we have seen, have been due to message queues building up faster than the messages can be delivered. The message queue will usually not go away until the HTTP Sesssion times out, so a shorter HTTP Session timeout or sending messages less frequently can help with this.
>>Do you have a preferred setup/config in this case?
I think the preferred setup would be to use a load balancer that does session pinning. The clustering in BlazeDS is mostly for scalability. If two servers are clustered, a message sent to one server in the cluster will get delivered to another server in the cluster if a client is connected to the other server and should get the message (ie. if the client is subscribed to the same destination the message was sent to). You really don't need this behavior with JMS because two clients subscribed to the same JMS destination on different servers will both get a sent message through the JMS system. There is no need to send messages between BlazeDS server instances.
The clustering in BlazeDS also does some failover but this is pretty basic. If one server goes down, the client will failover to another server in the cluster but the other server won't know anything about the client's subscriptions. The client will setup these subscriptions again on it's own (ie. resubscribe to the destination(s) on the new server) but this will also happen if you are using a load balancer.
We don't do state failover currently. We don't keep things like the queue of undelivered messages in the session so you really won't get any benefit from replicating sessions.
Hope that helps.
That helps a lot. You helped us get on the right path.
One last item...for clients using MessageService/JMSAdapter/long poll channel, I would imagine the FlexSession would establish a connection to the topic, and with pinning, the client would reuse that connection to get any topic messages that are available.
If I understand the mechanics correctly, this the general flow:
1) client connects to the FlexSession via httpsession
2) clients waits for wait-interval-millis (long poll)
3) reconnects to the same FlexSession at polling-interval-millis frequency
If the polling-interval-millis was set to, lets say, 30 seconds and in those 30 seconds (while the client is not conncted) 100 JMS messages came into the topic. Will the client receive the 100 messages when it re-connects back with the FlexSession? Or does the client have to be waiting in long poll to get the messages?
We are using the flex.messaging.services.RemotingService to call into Java objects. We specifically do not want to have this session as we wish to load balance with no session affinity in the cluster processing these requests. This worked fine with the 3.0 series BlazeDS but is rather less happy in the 3.2 release. Is there a way to turn off this session stuff and use the flex.messaging.services.RemotingService? -- presently it appears our options are:
- Configure off the session stuff
- not sure how
- Compile a custom version that doesn't do this
- Not too enthused about this
- Roll back to the 3.0 version
- Probably the leading option presently
- Would much prefer to remain on 3.2 though
Like the original poster, we encounter this error when our load balancer is set to have no session affinity:
[FaultEvent fault=[RPC Fault faultString="Detected duplicate HTTP-based FlexSessions, generally due to the remote host disabling session cookies. Session cookies must be enabled to manage the client connection correctly." faultCode="Server.Processing.DuplicateSessionDetected" faultDetail="null"] messageId="6ADC180B-250D-06E8-967A-F7581523B439" type="fault" bubbles=false cancelable=true eventPhase=2]
Thanks, Rod S.
- Configure off the session stuff
Hi. The RemotingService uses the BlazeDS messaging system which requires session affinity. All the services (RemotingService, MessageService, etc.) communicate with the server over a channel. The channel needs to be able to talk back to the same server for things like Pub/Sub messaging to work. I see the point that session affinity shouldn't be required for remoting requests that are stateless, but in BlazeDS a number of services can share the same underlying channel so not requiring session affinity could break other services.
This issue has come up before. I even found some blog postings that documented workarounds, though they do require customizing/modifying BlazeDS.
I thought there would be a bug for this logged already but I couldn't fine one in the bug system. Feel free to log a bug if you feel it is important to have this.
I can think of a number of ways this could be resolved. One would be to have a stateless channel that didn't require session affinity. Another would be to have a mode in which the remoting calls bypassed the BlazeDS messaging system, similar to the way in which web service and http service requests can get made directly to a target server and not go through the BlazeDS proxy.
Currently you can call a RemoteObject in ActionScript using NetConnection. These messages are processed on the server by the flex.messaging.endpoints.amf.LegacyFilter class. Using NetConnection instead of the mx.rpc.remoting.RemoteObject class on the client might allow you to bypass the session detection on the server.
Hope that helps.
Thanks, that does help.
I have filed this as http://bugs.adobe.com/jira/browse/BLZ-443 as I think this is a valid and useful configuration. I put it in as a Feature Request as the current behavior sounds by design so I'm not sure "bug" would be an accurate representation. In the short-term we will likely have to revert to 3.0. Longer term I suppose either the feature will be provided or we'll have to build our own customized version.
In terms of rolling our own solution, we currently use the AMFChannel. I would be interested in your thoughts on how much work adding either the stateless channel or a property to one of the existing objects to make it operate this way might be and any tips on where to look, likely problems we'd have, etc?
Just noticing I never answered these questions of Alan's.
>>If the polling-interval-millis was set to, lets say, 30 seconds and in those 30 seconds (while the client is not conncted) 100 JMS messages came into
>>Will the client receive the 100 messages when it re-connects back with the FlexSession?
Yes, the client will receive the 100 messages that were sent/pushed to the server while the client was in between poll requests.
>> Or does the client have to be waiting in long poll to get the messages?
No. There is a message queue on the server that is associated with the client. As long as the client is actively subscribed to the destination, it doesn't have to be physically connected to the server to get new messages. The messages will stay in the queue until the client polls the server again.
Thanks for filing the feature request. Yes, I agree that it should be considered an enhancement and not a bug.
As far as rolling your own solution goes, I think the simplest thing to do would probably be to do what Martin talks about on his blog, which is to disable the duplicate session detection. This code as he points out is in the flex.messaging.endpoints.BaseHTTPEndpoint class in the setupFlexClient() method.
If you are also doing messaging with your BlazeDS application, I would create a new endpoint, basically a copy of AMFEndpoint that used your new version of BaseHTTPEndpoint.java and just use that endpoint for remoting, not for messaging.
The duplicate session detection code adds a layer of security in the case of messaging. It would prevent someone who guessed your client's subscriber id from polling the server for messages intended for you from another session. This shouldn't matter in the remoting case because there wouldn't be any state associated with the client outside the session.
Just to be sure I understand the ramifications of this solution, we'd
presumably end up with an empty (other than any default stuff) session for
every user on every node they'd sent a request to? That is, if my user
generated 5 requests and the load balancer sends them to 5 nodes, each node
is going to setup a session? Presumably this is rather inexpensive for empty
sessions of course.
Thanks, Rod S.
Yeah. That's right. You'd get a new session for every request which obviously isn't ideal but the amount of stuff being stored in the session or associated with the session should be relatively small. In addition to the J2EE session, I think a new flex.messaging.FlexSession and flex.messaging.client.FlexClient will get created.
Also, make sure you set the scope on the destination to "request" so that the remote object class that is instantiated doesn't get held onto by the session. You should also be able to set the session timeout on the server to something pretty short as the session isn't really being used.