when building a server, one sometimes performs asynchronous tasks from client to server (which responds to client in asynchronous time),
or the server needs to send the client a message
now if the client is listening at all times (meaning polling) it takes a lot of resources which is problematic
here is where I assume the operating system steps in and assumes the role of polling for the appropriate port, and letting the application know using the appropriate event (the application subscribes using the OS API)
am I right in my assumptions?
how do I subscribe to a port using the OS's API? (lets say android for the sake of argument)
how is a message from server to client work exactly?
and how does the server know the client's IP at all times?
I have seen many questions in the subject, but wasn't able to figure out the big picture
Edit:
I am using GCM in android, but have seen other apps that does not use it and still manage to do it right, also it's a more general question as to what is the right approach in java VS. any operating system it uses (ubnutu, windows, android, etc.)
Totally right - polling is typically a waste of resources. Until recently, many apps would either keep a socket open and poll every few minutes to keep it alive, or make periodic HTTP calls to a server.
Nowadays, Google Cloud Messaging is used by most apps to push data instead of constantly polling. As you correctly guessed, this is implemented by maintaining a persistent connection with Google's servers. The advantage of this is that it's very efficient for battery life, and that all apps can use this one resource to send push notifications, instead of each app having to poll a different server or create its own persistent connection.
The idea is that you send requests to GCM from your server (this can be in response to user activity, etc), which sends it to all of the client's devices. You can either send a message with a small payload (up to 4kb) or a "send-to-sync" message, which tells an app to contact the server (e.g. to sync new data from the server after user changes).
here is where I assume the operating system steps in and assumes the role of polling for the appropriate port, and letting the application know using the appropriate event (the application subscribes using the OS API)
GCM pushes messages to clients, so there isn't active waiting like you'd see in a simple polling system.
how is a message from server to client work exactly? and how does the server know the client's IP at all times?
There's no need for servers to know the client IP, as any online android device will typically maintain a connection with GCM. Targeting specific users is done via User Notifications.
(Oh, and I realize that your question is more general than just Android, which I have more experience in, but iOS has a similar system in place. Some developers I've met like to use Parse for managing push notifications).
Related
I want to monitor firebase client connections from my java server.
I have found a lot of examples on how to use onDisconnect from the client side (iOS), and it works great.
But is it possible to monitor client connections from a java server using the java server sdk? I simply want my server to know about user disconnects, but without the client having to 'tell' the firebase database that it has connected/disconnected.
The reason for this is mostly security, and a wish to trust the client as little as possible to do important tasks. Ideally most of my data should be 'read only' from the client, except for some 'write only' request queues consumed by the java server.
From the firebase java server documentation: https://firebase.google.com/docs/reference/serverreference/com/google/firebase/database/OnDisconnect
The OnDisconnect class is used to manage operations that will be run
on the server when this client disconnects. It can be used to add or
remove data based on a client's connection status. It is very useful
in applications looking for 'presence' functionality.
It seems like what I want to do is possible and supported, but I'm having a hard time figuring out how to make my server monitor 100-1000 connections realtime.
Lets say I'm monitoring a database reference that I know clients are monitoring. In that case none of the options to 'remove on disconnect' or to 'set on disconnect' are useful.
Thanks a lot for reading this, I'm REALLY loving firebase right now, just a few more issues to figure out :-) Also sorry for my english, I'm not a native speaker.
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.
I have deployed a Java web application in Heroku.
Now, I want to change the back-end so that it can notify connected users regarding specific events. I thought I could use server-sent events to do that and the way I thought it would work is the following:
When user opens up the front-end, it would establish a connection for the server-sent events.
When the back-end receives such a request, it would create such a connection (basically an EventOutput) and store it somewhere along with the user's ID (let's say in a Map in memory).
When a new event comes along, the back-end will find the user that needs to be notified, retrieve his connection according to his ID and send him the notification.
This works just fine when you have only one machine handling the requests.
My problem starts when I want to scale up my app and introduce more machines. Then, I cannot really store these connections in memory in one machine anymore, I need to use some centralized location. But the centralized location will need to serialize/deserialize the connection, which means that it's not the same connection anymore!
How do you usually do something like that?
One solution is to use session affinity (a.k.a. sticky sessions), which will ensure that a single session's requests are "always" routed to the same process (I say "always" because there are some caveats). You can turn this feature on by running this command:
$ heroku labs:enable http-session-affinity
In this way, you can keep things in memory and will not have to serialize the session.
Here is an article describing this feature in more detail: https://blog.heroku.com/archives/2015/4/28/introducing_session_affinity
You could use a pub-sub solution (ex: Redis pub-sub) that is accessible to each of your dynos.
On starting, your app subscribes to the appropriate channels. When an event happens, it is published to a channel. This means all instances of your app (spread across multiple dynos) receive that event, and any of them that have SSE connections open can respond to the event.
I'm developing an Android app that requires 2 (or more) devices to communicate with each other.
I tried using Google Cloud Messaging but I was disappointed to find out that the GCM max capacity is 100 messages, so it is broken and does not fit my requirements.
I was thinking about java sockets. Every device will open a new socket (or keep its socket open) and communicate with a group of sockets (devices).
In order to communicate this way I need a server-side app that can send messages to the client (android device). So I figured out that HTTP or web-service won't help me. Am I right?
What is the best way for me to implement such a server-side app?
You can refer to this question I previously asked and implemented. It was for implementing my own Notification mechanism but it equally (or even more) applies to chatting applications since message queues perfectly fit that usecase.
Building an Android notification server
I ended up not doing it and using GCM at the end but I did have a fully working solution using ActiveMQ and Paho. You can research them both and understand their inner workings. It's easy in principle and definitely possible but the problem is, you may not be able to do this for iOS or WP as it requires running a service in the background (in case your app is not open and you want to make sure the messages are at least sent in a notification).
The possible solution to that problem would be to use both the notification service (GCM or equivalent) for background notifications and then using your MQ for actual communication but I decided that was too much for my project.
If you look at Paho, it will have a fully working MQTT solution that will work even if the phone is not "online" (sleeping or otherwise) and there are plenty of samples for ActiveMQ and drivers for multiple programming languages.
I think this solution is much better than having open sockets between two apps, at least because they allow you to persist messages and guarantee delivery which is an important aspect for a chatting application.
As it is said by kha, choose one of the message queue protocols is the best solution. 3 reasons in brief,
Delivery guaranteed regardless of temporary offline or long latency.
As simple as subscribe / publish, no worry about transport layer any more.
Broker available online. You save time and money for setting up your own.
For mobile devices like in your case, I'd prioritize MQTT too. It's lightweight and stable. If you are totally new to message queue or MQTT, refer to this documentaion and example code
I have several PC's on each of them I set small swing application that get data with JSON request to one web server. Can I receive the data from web server without to send request to the web server, with other words can the Web server send the data without the Java application to ask for this?
If you have enough server resources
you can consider usage of websockets.
Every PC can open a socket to the server.
When you open the socket you need to send to the server, the pc's unique ID.
Then you need to store this ID in some database or file that will contain all online pc's and sockets .
Then the Server will be aware which pc's are online and which socket to use to communicate with this pc. After this you can send whatever information you need to this PC depending on your application.
This can be implemented in several ways. One common way would be to open a connection and do blocking read in the client application. On receiving something it will look like push from the server. Then you process the push and do another blocking read.
Another option would be doing regular checks if there is something for you on the web server. You set the retry interval frequent enough so it will look like real time push from your app point of view.
If you use HTTP i think the smartest way is to drop the realtime requirement and use a thread that polls the server every 5 seconds. Keeping a HTTP Connection open all time is expensive as it blocks a request processor thread and limits the amount of clients you can have.
You might also consider moving to something like a registration mechanism if you really need near-realtime updates which is often not the case. You would have to open a Server on the clients and have the server push the updates after clients registered their Address with the server.