-
Notifications
You must be signed in to change notification settings - Fork 363
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Best practices on if and when you should close HTTP connections in flutter apps? #422
Comments
No response? I'm interested in this as well. |
i wanna know this too as i have an application with a lot of api requests and which takes time in getting the response and whenever abruptly the screen is changed or another api is called before the earlier request was completed it hangs and shows an error Connection Closed Before Full Header was received. I have been stuck on this for very long any help is appreciated! |
I have been facing the same issue when making api requests. I couldn't close the connection when my app navigate to other pages which makes my app to be hanging. Any form of help or explanation will be appreciated |
Hmm. I'm also following this. In my app I have a singleton http client that I initialize once. I then call this client synchronously with get/post/puts. I never close it. This seems to work just fine and I've made several hundreds calls without any issues. However. My end users have reported that the app seemed to stop talking to the server after a while but the animations and buttons were still working. Just that all requests times out. This problem occured after a while and what seems to be at random. I've debugged this for quite some time and at one point I got a state where I called myHttpClient.get() but I did not receive the request server side. After 30 seconds (my configured timeout) the request timed out. I could keep on sending requests to the server but none of these requests reached the server. It seemed like that http client was disposed but I did not get any exception other than requests timing out. So I figured, this is probably what my end users are experiencing. That all http requests suddenly just time out. Could this be because of some pool of requests being "filled up" with broken requests? If the wifi is shaky and a requests break, maybe that pool slot is "broken" and after a while all pool slots are broken and the http client is completely broken? Would a better practice be to initialize a new HttpClient for every request and closing that after each request? Any downsides? |
@mikeesouth one obvious downside is that it's much slower than using an existing client (about 2x slower in my rough testing). I also have a production app that I never close the connection and it seems that it doesn't have your problem. |
What i will do is keep open a persistent connection by using a Client rather than making a one-off request since multiple requests are sent to the same server
|
In terms of network traffic, it's better to use the same client throughout the app lifecycle. Establishing a new connection for each api is very expensive. However, as per the documentation,
Also, if client.close() isn't called, it doesn't mean that the server will keep the connection open forever. The server will close the connection if it is idle for a period more than the HTTP Keep-Alive Timeout. In this case, if the client sends a new request over the connection closed by server, he'll get a 408 Request Timeout. So, if you decide to use the same client throughout the app lifecycle, keep in your mind the two possible issues that you may run into. |
From @mikeesouth comment
We encountered this issue as well and narrowed it down to the following problem: https://stackoverflow.com/questions/66063913/socketexception-failed-host-lookup-com-os-error-nodename-nor-servname-p In our case we had a HttpService class to perform get, put, post, etc. requests (adding headers etc.) - that was used throughout the app. We added a counter to record the request count and instanciate a new instance every 200 times (or something like that) and only if no pending calls are present (otherwise the request fails with ...
import 'package:http/http.dart' as http;
...
class HttpService {
// api call threshold
// create a new instance of http client after a minimum given number of calls have been made
// needed, because otherwise SocketException occurs after some time
static int _calls = 0;
static int _minCallsBeforeNewInstance = 200;
// record ongoing calls - needed otherwise a forced close and new instance of http client may cause problems with pending calls
static int _ongoingCallsCount = 0;
static http.Client _httpClient = http.Client();
static final HttpService _instance = HttpService._();
HttpService._();
factory HttpService() {
return _instance;
}
...
Future<http.Response> get(
Uri url, {
Map<String, String>? headers,
}) async {
_calls++;
_ongoingCallsCount++;
Logger.debug('GET ($_calls): $url');
return _httpClient
.get(
url,
headers: await _headers(headers),
)
.whenComplete(_handleCallComplete);
}
...
void _handleCallComplete() {
if (_ongoingCallsCount > 0) _ongoingCallsCount--;
if (_ongoingCallsCount < 0) _ongoingCallsCount = 0;
// create new instance only if no pending calls are out there and the minimum calls have been reached
if (_ongoingCallsCount == 0 && _calls >= _minCallsBeforeNewInstance) {
Logger.debug('Closing existing http client and create new one');
_httpClient.close();
_httpClient = http.Client();
// reset calls
_calls = 0;
}
}
} |
@RANSoftRA , Have you found that your posted solution resolves the host lookup exception issue that you linked to? |
Yes, the linked issue was solved with this approach. |
It is
Line 46 in 06649af
Line 68 in 06649af
Line 166 in 06649af
refshttps://pub.dev/packages/http#using |
Same issue for me, have implemented the suggested. Could it be the addition of background_fetch, background_processing capabilities that keep the http instance alive so long? |
4 years :| |
@natebosch @brianquinlan @kevmoo I just dug deeper into this issue because I'm trying to use the new cronet and cupertino Httpclients.
What is the best strategy to keep connections alive? |
Aren't some of/those questions answered by the comments on the http methods? Ref: https://github.com/dart-lang/http/blob/06649afbb5847dbb0293816ba8348766b116e419/pkgs/http/lib/http.dart#L121C30-L123C4 |
This still doesn't give a clear answer at least not for my understanding see this full thread
Am 12. Juni 2024, 21:19 +0100 schrieb Pedro Massango ***@***.***>:
… Aren't some of/those questions answered by the comments on the http methods? Ref: https://github.com/dart-lang/http/blob/06649afbb5847dbb0293816ba8348766b116e419/pkgs/http/lib/http.dart#L121C30-L123C4
Screenshot.2024-06-12.at.10.12.15.PM.png (view on web)
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you commented.Message ID: ***@***.***>
|
You mean a new instance of the
Probably one would be fine for most applications. You may need more if you have different use cases where
No.
That should not be necessary except in the case of the exception that I mentioned above.
You will need a new
You should call
I think that we covered this one.
I think that we covered this one.
I'm don't have a good answer for that. |
thanks a lot @brianquinlan If you don't need some special behavior clients 1 Client for the full app should be anough and it doesn't have any impact of the performance even if we do multiple async network calls on the same client in parallel and one client is able to handle multiple Http conenctions that use the keep-alive feature. The second paragraph in the API dos might be the reason people are not sure what to do: |
Programs run using the Dart CLI will not exit while there are pending asynchronous operations. Other clients have different behavior. If I understand correctly, Flutter doesn't care about pending asynchronous operations when deciding whether the application should terminate (and mobile operation systems can kill an application at anytime anyway). |
Ah, that makes sense. I was already guessing that this might only apply to Dart clip clients.
And if they will maximal block whole a connection is still active that should rarely make a problem.
Maybe that API comment could get addition that explains this.
Will write an article over the weekend
Am 14. Juni 2024, 19:59 +0100 schrieb Brian Quinlan ***@***.***>:
… > Could you explain what is really meant by this because it seems to contradict what I understand from your reply.
> I hope the connection pool will shrink once the connections are no longer used?
Programs run using the Dart CLI will not exit while there are pending asynchronous operations. IOClient maintains a connection pool so the Dart CLI will not exit while there are still connections in the connection pool. How long a connection is kept active when not used is controlled by HttpClient.idleTimeout but the default is 15 seconds.
Other clients have different behavior.
If I understand correctly, Flutter doesn't care about pending asynchronous operations when deciding whether the application should terminate (and mobile operation systems can kill an application at anytime anyway).
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you commented.Message ID: ***@***.***>
|
in 2025 and there is no clear answer , im facing a hanging issue after multiple requests , i use client.close() when request is done and it works fine and never faced hanging again but i got a new problem , every request being slow when use close function |
I recommend my article https://blog.burkharts.net/everything-you-always-wanted-to-know-about-httpclients |
According to the docs it says:
However, in most mobile apps, you tend to send most requests to a single server.
Does that mean, for an app that does a lot of API calls to a server, that we should keep the connection up throughout the app lifetime?
Also should we close and re-open the connection when the app suspends and resume states?
The text was updated successfully, but these errors were encountered: