We are building a chat application on Android. We are thinking of using HTTP REST API to send outbound messages. Wanted to know if it's a good approach or has any downsides compared to using WebSockets or XMPP (which seems to be more of a defacto standard for transferring chat messages)?
Some of the pros/cons I can think of are:
HTTP endpoint is easy to scale horizontally on the server side (This is the main concern)
Learning curve for Websockets is steeper compared to HTTP
HTTP messages would have a larger payload compared to WebSockets
As per this document, it seems even Facebook used AJAX to handle chat messages initially:
https://www.erlang-factory.com/upload/presentations/31/EugeneLetuchy-ErlangatFacebook.pdf
We can use REST API for chat messaging, but IMHO, XMPP is a better alternative. Let's consider what XMPP has to offer.
XMPP beside supporting TCP transport also provides HTTP (via polling and binding) and websocket transports. Read XMPP via HTTP and WebSocket transports
It would be interesting to understand pros and cons of each transport from XMPP perspective.
XMPP could use HTTP in two ways: polling[18] and binding.
XMPP over HTTP Polling
The polling
method, now deprecated, essentially implies messages stored on a
server-side database are being fetched (and posted) regularly by an
XMPP client by way of HTTP 'GET' and 'POST' requests.
XMPP over HTTP Binding (BOSH)
The binding method is considered more efficient than the regular HTTP 'GET' and 'POST' requests in Polling method because it reduces latency and bandwidth consumption over other HTTP polling techniques
However, this also poses a disadvantage that sockets remain open for an extended length of time, awaiting the client's next request
The binding method, implemented using Bidirectional-streams Over Synchronous HTTP
(BOSH),[19] allows servers to push messages to clients as soon as they
are sent. This push model of notification is more efficient than
polling, where many of the polls return no new data.
It would be good if we understand how the BOSH technique works.
The technique employed by BOSH, which is sometimes called "HTTP long
polling", reduces latency and bandwidth consumption over other HTTP
polling techniques. When the client sends a request, the connection
manager does not immediately send a response; instead it holds the
request open until it has data to actually send to the client (or an
agreed-to length of inactivity has elapsed). The client then
immediately sends a new request to the connection manager, continuing
the long polling loop.
If the connection manager does not have any data to send to the client
after some agreed-to length of time [12], it sends a response with an
empty . This serves a similar purpose to whitespace keep-alives
or XMPP Ping (XEP-0199) [13]; it helps keep a socket connection active
which prevents some intermediaries (firewalls, proxies, etc) from
silently dropping it, and helps to detect breaks in a reasonable
amount of time.
XMPP over WebSocket binding
XMPP supports WebSocket binding which is a more efficient transport
A perhaps more efficient transport for real-time messaging is
WebSocket, a web technology providing for bi-directional, full-duplex
communications channels over a single TCP connection. XMPP over
WebSocket binding is defined in the IETF proposed standard RFC 7395.
Speaking of the learning curve, yes, you might be tempted to use the REST API, but now there are several resources to learn about Android and XMPP, and XMPP server softwares that you can use to run your own XMPP service, either over the Internet or on a local area network. It would be worth spending this effort before you decide your architecture.
I think a REST approach can work for chat. Let's assume:
http://chat.example.com/conversations references all conversations
GET fetches the list
POST creates a new one
http://chat.example.com/conversations/123 references conversation #123
GET fetches messages in this conversation
POST adds a message in the conversation
If I understand correctly, your question is about the last point.
Once the client has posted an outboud message to http://chat.example.com/conversations/123, it will close the http connection.
The drawback is that receiving inbound messages is simply not possible in that case. You will need a different channel (maybe simply Google cloud messaging).
On the contrary, WebSockets and XMPP keep the connection alive, hence they can receive messages with no delay. But the drawback of both of them is indeed that this represents a cost on the server, in terms of scalability ; and a cost on the client in terms of battery usage.
On the server:
sockets are a relative scarce resource
it's not possible to move clients for load balancing if they have an open connection (but can you really move clients anyway? this depends on the responsibility of tiers)
On the client:
maintaining a network connection is extremely expensive. 1 s network ≈ 5 min sleep.
the XMPP librairies are not necessarily working very well on Android.
And I've no idea of support of WebSockets on android.
It is not suggested to use HTTP Rest API for a chat or similar real-time applications.
Some overview...
Chat Client requirements
Friend list fetch
Check online/offline friends
Get chat messages in real-time and send messages.
Receive notifications of delivery/reading etc.
Point 1 is sort of one time job after you start the chat client so can be done with a simple rest call so requires no complicated overhead.
Rest all the points will need persistent checking of data from the server or other parts in case of p2p client also. Which will make you create either long or short polling rest calls to watch for new data or other updates.
Problem with HTTP Rest client
It is not a keep-alive type of communication due to which you will have to make multiple HTTP connections which will have so much overhead that it will become overly laggy. As reconnecting is very costly in HTTP calls.
Web sockets or XMPP
They are duplex mode of communication and are very good at handling incremental data pushes and you are not creating new HTTP connections again so it gives a really smooth performance.
Another solution
In case you are stuck with some legacy systems in case of which you are bound to use the rest API mode.
Try CometD it is a hybrid approach of WebSockets and ajax polling which will give you near real-time communications as well as work on clients which do not support WebSockets by falling back on ajax polling mechanisms. Also, it uses various optimizations to avoid reconnecting again and again.
CometD link
You can also try Socket.io which is also an amazing technology to solve these kinds of use cases
Short answer No.
I would not start a new project or recommend starting a new project (since you mentioned start afresh) that needs a live bi-directional communication that relies on HTTP - as stateless protocol. You may take comfort that the connection is kept alive but there is no guarantee.
Your + HTTP endpoint is easy to scale horizontally on server side pro is a pro in the context when HTTP is used as request and response style and when it is considered stateless. It becomes somewhat moot (although not entirely) when you inherently need to keep the connection alive.
HTTP does offer another following benefit that you have not mentioned in here.
HTTP is easy to deal with corporate firewall proxies when other ports may be blocked.
This is where WebSockets or XMPP over HTTP will have better success rate as mentioned by others.
It depends. Do you consider your application to be "live chat"? Do you require a presence indicator, or typing indicator? Features such as those require continuous connection. But there's another set of chat applications that you'd describe as "in-app messaging" enabled. These applications store conversations and conversation lists on some sort of backend; just install the app on another device and log in, and you'll see your conversations on this type of app. These apps don't have any presence indicator, or feeling of liveness.
Although I haven't implemented any applications with XMPP, it looks like as far as message persistence, the most persistence you'll find with XMPP (out of the box) is persist-until-delivered, similar to SMS. Perhaps you could build a storage/recovery mechanism for XMPP by capturing stanzas as they pass through and storing them in your own DB. But if you don't need the full "chat" experience, using a database, HTTP service and push notifications (to notify of updated threads) seems like a solid path for apps with messaging functionality — which I intend to implement in an iOS & Android app of my own right now.
Let me know if you've found any good open-source schemas/API design for this.
Related
I am developing client application on Android, which uses REST API to get JSON.
App sends a lot of requests to different URLs. This way is somehow slow - takes 30~60 seconds. This article says that WebSocket works faster. Now I am wondering whether I can use WebSockets for this purpose. So I have several questions about this:
Is it a good practice to use WebSocket to get JSON data from server?
If not, what can be better(faster/more secure) than regular HTTP?
Can I send request to regular HTTP REST API using WebSocket?(this question may seem strange, but I really do not know)? Or guys on
backend should change/modify something to make this enable?
What can be disadvantage(eg. battery drain) for using WebSocket?
You can use WebSocket to get JSON data from a server. However both the client and server must "talk" WebSocket. If the server only understands REST calls, you will not be able to directly connect with WS from a browser to that REST server.
No, you cannot use WebSocket to directly connect to an HTTP REST API. Your browser must use the same protocol as the server. That's why protocols were invented. right? :)
WebSocket is a persistent connection between a client and a server. Its like a TCP socket connection in that way. HTTP is fundamentally not persistent (although there are tricks to keep the connection for a long time). An HTTP client usually calls an HTTP server, gets the data, returns and then the connection is terminated. There are advantages and disadvantages to both (like anything else). A WebSocket connection by itself will not drain your smartphone battery quickly. If you are constantly sending data over that WebSocket that has to be rendered by the GPU on your screen, then your battery will drain. An HTTP connection by itself will not drain your smartphone battery either. But if your phone is polling some REST server and is in a low bandwidth area, your battery will drain from constantly going from low-power mode to high-power mode. So its not the connection that is affecting the battery; its what's happening with that connection that affects the battery.
You still send HTTP requests. It is a good practice if you have a bunch of them that you want to send in a burst or want to have two-way interaction with the server. You simply avoid rebuilding a fresh Session everytime and multiple handshake protocols. If you want to visit a webpage with lots of resources (e.g. images) it is a good idea. Also the server can send request to you without being polled.
WebSockets need to be enabled on the server side (they are by default), but to keep the connection alive the webserver stores some references which need to be managed. So you allocate resources even if there is no messaging. When you have lots of clients, it can become challenging to handle the resource allocations.
Battery drain is not an issue since you are not sending lots of data, but for you as a developer you need to add extra logic to handle the cases when the network or wifi are no longer available. This is when the Websocket is terminated and you need to reconnect with the server.
As a personal comment: Use it if you need server to interact with you (if something happens e.g. a new message has arrived for you at the server, the server can use the websocket to let you know) or if you are expecting lots of requests being send to the server in a short time from your client.
Hope it helps! I am not an expert.
Before ask my question, I want to let you know what stage I am on. I have already implemented TCP/IP socket on my android app, it works fine(so far...).The connection between client(my android app) side and server side is short connection which is when a user submit information, a new thread will be created to send the message out, on the server side, once the server got the message, the server will respond "RCVD", after that the socket will be closed and then the connection is closed. My app has a lot of interactions between user side and server side, therefore it does many connect and disconnect between clients and server, so I always worry about the socket communications will drain phone battery and the performance will be affected.
Recently I find OkHttp on github and a lot of people suggest using it. Im not quite familiar with Http, only knows it is a higher level network protocol.
Can anyone tell me which way is better? which is more efficient for exchanging data(Object/Json/String) and media(Images)? Which is more faster and which use less battery?
Many thanks.
Basically, the comparison between Http and tcp socket is meaningless, But in your situation it really matters.
As you described, in your tcp socket way, you may create new connection each time receiving new push from server, which is not that efficient, If you use OkHttp, when your client exchange message with the same server, the same tcp socket is reused each time rather than make a new one.
By the way, As for the push service, use XMPP(over tcp) may be better cause Http is not optimized for such short message exchange model(You should use some extra strategy on the server side to keep the connection from being closed), but you may have to handle some implements about XMPP server and client.
I am an android user and of course I use whatsapp, twitter for android, facebook and many other apps that notify me of events.
As a proogramer whats keeps me wondering is how fast notifications or whatsapp messages arrive.
My intuition tells me that is not possible for the whatsapp or twitter server to open a TCP connection with my cellphone by a given port to deliver a new message. If i am in wifi mode the router would block that connection.
And if my whatsapp client is pooling the server every second.... Poor server if it has 1000 clients making request every second.
What is the approach to face this issue?.
Is there some other protocol involved?.
Those apps use services that utilize "long polling" - primarily based on XMPP or some variation of XMPP (like jabber - http://www.jabber.org/). The client does not poll often. A quote for the Wiki page:
The original and "native" transport protocol for XMPP is Transmission
Control Protocol (TCP), using open-ended XML streams over long-lived
TCP connections.
It sends a message to the server that basically is a mechanism for the server to send a message back at any time (as long as the client is available). It's like sending a request to an HTTP server and the server "time-out" does not occur for a very long time (hours), so the client just waits. If the server receives a message destined for the client, it sends a "response" to that request. After the time out does occur, the client sends another request and waits.
GCM does the same thing - but does not require you to setup servers for all portions of the connection. It's easy to search for GCM, AWS, etc. to see examples.
Typically GCM should be used if you dont want to guarantee immediate delivery and it is okay for your app to miss out on certain messages.
This is because GCM tries to optimize by bundling several messages (even from other apps) into a single package. And it has a limited buffer to maintain the messages per device (in case the device is not reachable).
Here is just one way to do the job.
I just completed an Android application that uses web services to connect to a remote database. I was working on localhost.
Now, I plan to host my web services on a server. Let's say I have my Android application installed on any number of different client smartphones. Each smartphone user calls the web service at the same time.
Now how does the server handle these requests? Does it execute one thread per request? I want to know about the server processing in detail. Considering, all phones use GPRS, will there be any sort of delay in such a situation?
BTW, my web services are all SOAP based and the server I plan to use later will be an SQL Server. I have used .NET framework for creating web services.
Its for the general concept, not a Android specific
Usually, each of the users sends an HTTP request for the page. The server receives the requests and delegates them to different workers (processes or threads).
Depending on the URL given, the server reads a file and sends it back to the user. If the file is a dynamic file such as a PHP file, the file is executed before it's sent back to the user.
Once the requested file has been sent back, the server usually closes the connection after a few seconds.
Look at How Web Servers Work
EDIT:
For HTTP uses TCP which is a connection-based protocol. That is, clients establish a TCP connection while they're communicating with the server.
Multiple clients are allowed to connect to the same destination port on the same destination machine at the same time. The server just opens up multiple simultaneous connections.
Apache (and most other HTTP servers) have a multi-processing module (MPM). This is responsible for allocating Apache threads/processes to handle connections. These processes or threads can then run in parallel on their own connection, without blocking each other. Apache's MPM also tends to keep open "spare" threads or processes even when no connections are open, which helps speed up subsequent requests.
Note:
One of the most common issues with multi-threading is "race conditions"-- where you two requests are doing the same thing ("racing" to do the same thing), if it is a single resource, one of them is going to win. If they both insert a record into the database, they can't both get the same id-- one of them will win. So you need to be careful when writing code to realize other requests are going on at the same time and may modify your database, write files or change globals.
The server will maintain a thread pool listening for incoming requests. Upon receiving a request, the thread will process the request and return the response. If all the requests are received at the same time and they're fewer than the maximum number of threads in the pool, they will all be services in parallel (though the actual processing will be interleaved based on the number of cores/cpus). If there are more requests than threads, the request will be queued (waiting for a connection) until either a thread frees up or the client request times out.
If you're connecting to the service from a mobile network, there is higher latency in the initial connection but not enough to make a difference.
Your question is not really related to Android but to mobile development with web backend.
I don't know how to use .NET for server app development but if you take the example of a Apache/PHP/MySQL, each requests are run in a separated thread.
There might be small latency delays while the request reach the server but this shouldn't affect the time taken by your server to process the request and the data.
One of the thing to think about is to avoid sending multiple requests from one same client. This is a common implementation problem : since you have no data already returned, you think there are no pending request and you launch a new request. This can basically create unnecessary load on your server.
Hope that helps !
a) one instance of the web service( example: spring boot micro service) runs/listens in the server machine at port like 80.
b) This webservice(Spring boot app) needs a servlet container like mostly tomcat.
This container will have thread pool configured.
c) when ever request come from different users simultaneously, this container will
assign each thread from the pool for each of the incoming requests.
d) Since the server side web service code will have beans(in case java) mostly
singleton, each thread pertaining to each request will call the singleton API's
and if there is a need for Database access , then synchronization of these
threads is needed which is done through the #transactional annotation. This
annotation synchronizes the database operation.
I'm building native mobile applications in both iOS and Android. These apps require "realtime" updates from and to the server, same as any other network-based application does (Facebook, Twitter, social games like Words with Friends, etc)
I think using HTTP long polling for this is over kill in the sense that long polling can be detrimental to battery life, especially with a lot of TCP setup/teardown. It might make sense to have the mobile applications use persistent TCP sockets to establish a connection to the server, and send RPC style commands to the server for all web service communication. This ofcourse, would require a server to handle the long-lived TCP connection and be able to speak to a web service once it makes sense of the data passed down the TCP pipe. I'm thinking of passing data in plain text using JSON or XML.
Perhaps an Erlang based RPC server would do well for a network based application like this. It would allow for the mobile apps to send and receive data from the server all over one connection without multiple setup/teardown that individual HTTP requests would do using something like NSURLConnection on iOS. Since no web browser isn't involved, we don't need to deal with the nuances of HTTP at the mobile client level. A lot of these "COMET" and long-polling/streaming servers are built with HTTP in mind. I'm thinking just using a plain-text protocol over TCP is good enough, will make the client more responsive, allow for receiving of updates from the server, and preserve battery life over the traditional long polling and streaming models.
Does anyone currently do this with their native iOS or Android app? Did you write your own server or is there something open sourced out there that I can begin working with today instead of reinventing the wheel? Is there any reason why using just a TCP based RPC service is a worse decision than using HTTP?
I also looked into HTTP pipelining, but it doesn't look to be worth the trouble when it comes to implementing it on the clients. Also, I'm not sure if it would allow for bi-directional communication in the client<->server communication channel.
Any insight would be greatly appreciated.
Using TCP sockets with your own protocol rolled down is quite better than HTTP especially with the nature of resources on the mobile devices. Erlang will do quite well, however lets start from your protocol. Erlang excels well at this especially with the Bit Syntax expressions. However still, you could use plain text as you wish. JSON (would need a parser: Mochijson2.erl found in Mochiweb library) and XML (will need a parser: Erlsom).
I have personally worked on a project in which we were using raw TCP Sockets with our Erlang Servers and Mobile Devices. However, depending on the Port numbers you choose, Routers along the way would block/Drop packets depending on the security policies of service providers. However, i still think that HTTP can work. People chat on Facebook Mobile, send Twits e.t.c from their devices and am sure these social engines use some kind of Long Polling or Server Push or whatever but using HTTP. The mobile devices have advanced in capability of late.
Rolling your own TCP Based protocol comes with a number of challenges: Port selection, Parsing of data both at the client and server, Security issues e.t.c. Using HTTP will let you think of the actual problem than spending time correcting protocol issues at client or server. The Devices you've mentioned above like Android and IOS (Ipad, Iphone e.t.c) are very capable of handling HTTP COMET (Long polling). Am sure when you follow the standards for Web Applications on Mobile devices as well as these W3C Mobile Web Best Practices, your app will function well using HTTP.
Using HTTP methods will quicken the work and there are a lot of libraries on the SDKs of these Devices which would assist you prototype the solution you want as compared to the situation of rolling your own TCP-based plain text protocol. To back up this reasoning, look through these W3C findings.
Let me finally talk of the HTTP benefits on these Devices. If you are to use Web technologies for Mobile devices, such as Opera Widgets, Phone Gap, Sencha Touch, and JQuery Mobile, their SDKs and Libraries have Optimizations already done for you or have well documented ways in which your app can be made efficient. Further still, these technologies have the APIs to access the native Devices' resources like Battery check, SMS, MMS, GSM broadcast channels, Contacts, Lighting, GPS , and Memory; all as APIs in the JavaScript classes. It would become hard (inflexible) if you use native programming languages like J2ME, Mobile Python or Symbian C++ / Qt as compared to using Web technologies like CSS3, HTML5 and JavaScript tools mentioned above. Using the Web tools mentioned above will make your app easily distributable by say Ovi Store or Apple Store, from experience.
Take note that if you use HTTP, testing will be easy. All you need is a public Domain so the Widgets on the mobile device locates your servers over the Internet. If you role your own TCP/IP protocol, the Network Routers may be disruptive against the Port number you use unless you plan on using port 80 or another well known port, but then still your Server IP would have to be made Public. There is a short cut to this: if you put your TCP Server behind the same ISP as your testing Mobile's Internet connection, the ISP routers will see both source and destination as behind its Network. But all in all, there are challenges with rolling your own protocol.
Edit: Using HTTP, you will benefit from REST. Web Servers implemented in Erlang (especially Yaws and Mochiweb) excel at REST services. Look at this article: RESTFUL services with Yaws. For mochiweb, there is an interesting article about: A million User comet application using Mochiweb which is broken into 3 parts. Further still, you could look at the solution given to this question.
There are ZeroMQ builds for android and iOS. Java and ObjC bindings exist as well.
HTTP was created for infrequent requests with large responses. It is highly inefficient for transferring very big amounts of small data chunks. In typical situation, http headers can be twice in size of actual payload. The only strong side of HTTP is its habitualness, its 'One size fits all' karma.
If you want lightweight and fast solution, I guess ZeroMQ can be a perfect solution.
One reason to go with HTTP instead of a custom service is that it's widely supported on a transport level.
With mobile devices, a user might be on Wi-Fi at a hotel, airport, coffee shop, or corporate LAN. In some cases this means having to connect via proxy. Your application's users will be happiest if the application is able to use the device's proxy settings to connect. This provides the least surprise -- if web browsing works, then the application should work also.
HTTP is simple enough that it isn't difficult to write a server that will accept HTTP requests from a custom client. If you decide to go this route, the best solution is the one that you don't have to support. If you can write something in Erlang that is supportive of application changes, then it sounds like a reasonable solution. If you're not comfortable doing so then PHP or J2EE gets bonus points for the availability of cheap labor.
While HTTP does benefit from being widely supported, some successful projects are based on other protocols. The Sipdroid developers found that persistent TCP connections do greatly improve battery life. Their article on the topic doesn't address the server side but it does give a high-level description of their approach on the client.
Erlang is very well suited for your use case. I'd prefer using TCP over HTTP for the sake of saving battery life on the phone as you noted already.
Generally getting the communication between device and server up and running will be very easy. The protocol which you are using between the two is what will require most work. However writing protocols in Erlang is strikingly straight forward when using gen_fsm
You should checkout metajack's talk at the Erlang Factory which highlights his solution to a very similar use case for his iPhone game Snack Words.
I work on a application that connects to a Microsoft http server with long lived http/https connections to mobile devices to allow for push type data to be sent to the mobile. It works but there are lots of little gotcha's on the mobile side.
For the client to get 'packets' of data, we put the http connection into Chucked Encoding mode so that each packet is in one chucked packet.
Not all native http API services on each mobile will support calling you back when a 'chuck' of data has arrived, on the ones that don't normally wait until all the data from the server has arrived before calling the application back with the data. Platforms that support callbacks with partial data are (that I have found):
Symbian
Windows Mobile
Platforms that don't support partial data callbacks:
IOS
Blackberry
For the platforms that don't support partial callbacks, we have written our own http connection code with chucked encoding support using the native sock support. It's actually not very hard.
Don't rely on the fact that one chuck is one of your packets, http proxies or the native http api implementations may break that assumption.
On IOS with this background multitasking rules, means you can't keep this connection going while your application is in the background. You really need to use Apples Push Notification service and live by it's limitations.
Never trust mobile cellular networks, I have seen the weirdest stuff going on like the server side seeing the http connection drop and then reconnect (and replay of the original http request) while on the mobile end you don't see any drop in the connection. Basically treat the connection as unreliable where data can go missing. We ended up implementing a 'tcp' like sequence number scheme to ensure we didn't lose data.
Using http/https makes it easier to get past firewall rules on customer sites.
I'm not sure using http/https long-lived connections was the wisest decision we ever made, but it was made long before I turned up so I have to live with the fall-out of it.
As a alterative, we are looking at web sockets as well, but with the web-socket spec in the state of flux atm and generally being not to good to follow, I don't know if it will work out or not.
So that is my experience with using http/https as a long-lived realtime connection.
Your milage may vary.
It all depends on what data you are sending - the size of it, the criticality of timeliness, frequency of update etc.
If you are looking for a reasonably lazy update and verbose data (JSON say) then go with a HTTP comet pattern, as you will find it much easier to navigate standard network gear as other answers have highlighted. If you are behind a corporate firewall/proxy for example, http will be a much safer bet.
However, if you are doing fast things with small data sizes then go with something homegrown and leverage a TCP connection. It's much more to the point and you'll find the performance in real terms much better. Simple data structures and use fast operators to slice you data up as you need it.
Again as other posters have noted, battery usage is a big concern. You will eat a battery by literally burning a hole in your pocket if you are not careful. It is very easy to turn a battery that lasts 2 days into one that will last 6hours.
Lastly, don't trust the network if you are time sensitive. If you are not then a long poll over HTTP will be just fine for you. But if you are looking for high performance messaging, then be acutely aware that a mobile network is not an end-to-end TCP connection. Your requests will varying in trip time and latency.
So back to what you want to do with the app. As you are building for iOS (native obviously dictated) and Andriod, I would leverage Apple Push Services and their notification framework. Build you back end services to talk to that and also provide interfaces for non-apple devices (i.e. http or tcp level listeners). That way one platform and multiple 'gateways' for your apps. You can then do RIM via their push service too if you wanted to.