firebase / firebase/firebase-admin-java

connection keepAlive does not apply.

Offen
#880 1 Kommentar 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen
needs-triage
Vorherrschende Sprache
Java
Sterne
620
Forks
305
Ø Merge
3 Std. 23 Min.
Gemergte PRs (30 T.)
1

Beschreibung

### [REQUIRED] Step 2: Describe your environment

* Operating System version: linux
* Firebase SDK version: firebase-admin-8.1.0.jar
* Library version: 8.1.0.jar
* Firebase Product: Cloud Messaging (auth, database, storage, etc)

### [REQUIRED] Step 3: Describe the problem
We confirmed that keepAlive is applied when using firebase-admin version 6.8.0.
However, after upgrading to firebase-admin 8.1.0, keepAlive is not applied and the connection is immediately disconnected.

#### Steps to reproduce:
firebase-admin 6.8.0 FirebaseMessagingClient.sendSingleRequest()
![image](https://github.com/firebase/firebase-admin-java/assets/5026821/0344f4e8-b2aa-49a4-b76d-508b22c68cfe)
(apache httpclient-4.5.11) ConnectionHolder.releaseConnection() is called due to line 129.
At this time, this.released changes from false to true.
After that, ApiClientUtils.disconnectQuietly(response) -> (apache httpclient-4.5.11) ConnectionHolder.abortConnection() on line 132 is called, but the connection is not disconnected because ConnectionHolder.released = true.
![image](https://github.com/firebase/firebase-admin-java/assets/5026821/8cec24c6-4e52-4c9b-9954-e095daeee24e)
![image](https://github.com/firebase/firebase-admin-java/assets/5026821/67d9df90-b7e5-43cf-acf0-1e7e82ae7275)

However, in firebase-admin 8.1.0, ConnectionHolder.releaseConnection() is not called, but ConnectionHolder.abortConnection() is called, so the connection is disconnected.
![image](https://github.com/firebase/firebase-admin-java/assets/5026821/0896d325-4948-4d2f-8dcd-160e0f3fc2a6)

What happened? How can we make the problem occur?
Establishing connections is expensive. Therefore, recycling connections for a certain period of time can help improve performance. According to what I have checked, the code of the latest version, 9.2.0, is also the same.

#### Relevant Code:

```
private FirebaseMessaging initializeFirebaseMessaging()
throws IOException {
CloseableHttpClient httpClient = newHttpClient(proxyHost, proxyPort);

HttpTransport httpTransport = new ApacheHttpTransport(httpClient);

FirebaseOptions options = FirebaseOptions.builder()
// need credentials etc
.setHttpTransport(httpTransport)
.build();

FirebaseApp.initializeApp(options);
return FirebaseMessaging.getInstance();
}

private CloseableHttpClient newHttpClient(String proxyHost, int proxyPort) {
HttpClientBuilder httpClientBuilder = ApacheHttpTransport.newDefaultHttpClientBuilder()
.evictExpiredConnections()
.setKeepAliveStrategy(
new CustomConnectionKeepAliveStrategy(
TimeUnit.MINUTES.toMillis(3)))
.setConnectionTimeToLive(10, TimeUnit.MINUTES)
.setDefaultRequestConfig(requestConfig())
.disableCookieManagement();
return httpClientBuilder.build();
}

public class CustomConnectionKeepAliveStrategy implements ConnectionKeepAliveStrategy {

public static final CustomConnectionKeepAliveStrategy INSTANCE =
new CustomConnectionKeepAliveStrategy(TimeUnit.SECONDS.toMillis(50),
DefaultConnectionKeepAliveStrategy.INSTANCE);

public static final ConnectionKeepAliveStrategy NO_KEEPALIVE = (response, context) -> 0;

private static final long KEEP_ALIVE_SAFE_GAP = 500L;
private final ConnectionKeepAliveStrategy defaultConnectionKeepAliveStrategy;
private final long defaultKeepAliveTimeoutInMillis;

public CustomConnectionKeepAliveStrategy(long defaultKeepAliveTimeoutInMillis) {
this(defaultKeepAliveTimeoutInMillis, DefaultConnectionKeepAliveStrategy.INSTANCE);
}

public CustomConnectionKeepAliveStrategy(long defaultKeepAliveTimeoutInMillis,
ConnectionKeepAliveStrategy defaultConnectionKeepAliveStrategy) {
Args.notNegative(defaultKeepAliveTimeoutInMillis, "defaultKeepAliveTimeoutInMillis");
Args.notNull(defaultConnectionKeepAliveStrategy, "defaultConnectionKeepAliveStrategy");
this.defaultKeepAliveTimeoutInMillis = defaultKeepAliveTimeoutInMillis;
this.defaultConnectionKeepAliveStrategy = defaultConnectionKeepAliveStrategy;
}

public static long adjustKeepAliveTimeout(long keepAliveTimeoutInMillis) {
return Math.max(0L, (keepAliveTimeoutInMillis - KEEP_ALIVE_SAFE_GAP));
}

@Override
public long getKeepAliveDuration(final HttpResponse response, final HttpContext context) {
long keepAliveDuration = defaultConnectionKeepAliveStrategy.getKeepAliveDuration(response, context);
if (keepAliveDuration == -1L) {
return defaultKeepAliveTimeoutInMillis;
}
if (keepAliveDuration > 0L) {
return adjustKeepAliveTimeout(keepAliveDuration);
}
return keepAliveDuration;
}
```

Beitragsleitfaden

Beitragsleitfaden öffnen

Rechercherichtung

Beginnen Sie mit dem Vergleich des Verhaltens von FirebaseMessagingClient.sendSingleRequest() in firebase-admin 6.8.0 und 8.1.0, wobei Sie sich auf ApiClientUtils.disconnectQuietly(response) und die im Bericht beschriebenen Apache HttpClient ConnectionHolder-Aufrufe konzentrieren. Reproduzieren Sie den Verbindungslebenszyklus mit der bereitgestellten benutzerdefinierten Keep-Alive-Strategie und überprüfen Sie, dass Verbindungen entsprechend den konfigurierten Zeitdauern beibehalten und recycelt werden.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
java
Bereich
networking
Issue-Typ
Bug
Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Aktivitätsstatus
Veraltet
Klarheit
Muss geklärt werden
Anfängerfreundlichkeit
30/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.