The firebase-admin-java 9.4.0 does not work with NIO (Non-blocking I/O).
Les mainteneurs répondent en général sous 4 jours
Personne n'a encore pris cette issue.
Évaluation
- Difficulté
- 4/5
- Temps estimé
- 3-5 jours
- Accessibilité débutants
- 30/100
Piste de recherche
Commencez par suivre FirebaseMessaging.sendAsync à travers la configuration de FirebaseOptions ThreadManager et FirebaseThreadManagers.DefaultThreadManager.doInit(). Comparez le cycle de vie du thread firebase avec le comportement de httpclient-dispatch et de IO selector décrit dans les intercepteurs. L’issue ne spécifie ni fichier, ni test, ni résolution acceptée ; confirmez donc le relais prévu et l’échec reproductible avant de définir ce que signifie “done”.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
[READ] Step 1: Are you in the right place?
- For issues or feature requests related to the code in this repository
file a Github issue.- If this is a feature request make sure the issue title starts with "FR:".
- For general technical questions, post a question on StackOverflow
with the firebase tag. - For general Firebase discussion, use the firebase-talk
google group. - For help troubleshooting your application that does not fall under one
of the above categories, reach out to the personalized
Firebase support channel.
[REQUIRED] Step 2: Describe your environment
- Operating System version: ubuntu
- Firebase SDK version: firebase-admin-java 9.4.0
- Library version: java 17
- Firebase Product: fcm
[REQUIRED] Step 3: Describe the problem
Hello,
I am testing the firebase-admin-java SDK 9.4.0 with the following configuration:
FirebaseOptions options = FirebaseOptions.builder()
.setCredentials(googleCredentials(firebaseCredential, httpTransport))
.setDatabaseUrl(firebaseDatabaseUrl)
.setHttpTransport(httpTransport)
.setConnectTimeout(FIREBASE_CONNECT_TIMEOUT)
.setReadTimeout(FIREBASE_READ_TIMEOUT)
.setThreadManager(new CustomFirebaseThreadManager(
firebaseTaskExecutor.getThreadPoolExecutor()))
.build();
The reason I explicitly added ThreadManager is to monitor the ThreadPoolExecutor. Without this configuration, the ThreadPoolExecutor generated by FirebaseThreadManagers.DefaultThreadManager.doInit() will be used, which has a queue size of Integer.MAX_VALUE. If FCM responses are delayed, the queue can pile up, potentially causing an OOM (OutOfMemoryError).
Below is the configuration for H2AsyncClientBuilder:
H2AsyncClientBuilder h2AsyncClientBuilder = H2AsyncClientBuilder.create()
.setDefaultConnectionConfig(connectionConfig)
.evictIdleConnections(TimeValue.of(Duration.ofMinutes(10)))
.setDefaultRequestConfig(requestConfig())
.setIOReactorConfig(IOReactorConfig.custom()
.setSoTimeout(FIREBASE_READ_TIMEOUT, TimeUnit.MILLISECONDS)
.build())
.addRequestInterceptorFirst(
(HttpRequest request, EntityDetails entity, HttpContext context) -> {
activeStream.incrementAndGet();
if (context != null) {
context.setAttribute("startTime", System.nanoTime());
}
})
.addResponseInterceptorFirst(
(HttpResponse response, EntityDetails entity, HttpContext context) -> {
if (context == null || context.getAttribute("startTime") == null) {
return;
}
long startTime = Long.parseLong(context.getAttribute("startTime").toString());
long endTime = System.nanoTime();
if (startTime < endTime) {
Timer.builder(FCM_RESPONSE_TIMER_NAME)
.publishPercentiles(0.50, 0.95, 0.99)
.tags(
Lists.newArrayList(
Tag.of("host", ((HttpRoute) context.getAttribute("http.route")).getTargetHost().getHostName()),
Tag.of("http_version", context.getProtocolVersion().toString())
)
)
.register(meterRegistry)
.record(endTime - startTime, TimeUnit.NANOSECONDS);
}
activeStream.decrementAndGet();
})
.disableCookieManagement()
.setH2Config(H2Config.custom().setMaxConcurrentStreams(500 * 10).build())
.disableRedirectHandling()
.disableAutomaticRetries();
Here is the code for sending FCM messages. The postProcessExecutor is simply responsible for logging the send results:
ApiFuture<String> responseApiFuture = firebaseMessaging.sendAsync(fcmMessage);
responseApiFuture.addListener(() -> {
try {
responseApiFuture.get();
message.setResponseCode(FcmResult.SUCCESS.getCode());
postProcessor.postProcess(MessageStatus.SENT, message);
} catch (Exception e) {
log ~~~
}
}, postProcessorExecutor);
When testing this, if I set a breakpoint inside addRequestInterceptorFirst (or addResponseInterceptorFirst) in the second code block, the thread executing addRequestInterceptorFirst is the httpclient-dispatch thread.
At this point, firebaseThreadPoolTask.getActiveCount() (as set in FirebaseOptions.builder().setThreadManager()) is 1.
In other words, it seems like the firebaseThread is staying active while the httpclient-dispatch thread is running.
I would like the behavior to work as follows:
The firebaseThread performs tasks (such as SDK validation) before the HTTP call.
After handing over to httpclient-dispatch, the firebaseThread is released.
The httpclient-dispatch makes the request to the FCM server, and the IO selector detects when a response is received.
Once the IO selector detects the response, it hands over to httpclient-dispatch, which processes operations like interceptors and then passes it to postProcessorExecutor.
This behavior should prevent the firebaseThread from getting blocked when the FCM server is down or latency is high.
If the firebaseThread gets blocked, it means that the queue in the thread pool fills up, which can lead to OOM or RejectedExecutionException.
If I have misunderstood anything, please let me know.
If my understanding is correct, how can I resolve this issue?
- Langage dominant
- Java
- Étoiles
- 620
- Forks
- 306
- Merge moyen
- 4 j 7 h
- PR mergées (30 j)
- 13
Préparer son environnement
- Aucun Dockerfile ni fichier Docker Compose
- Propose un modèle de pull request
- Lire le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de firebase/firebase-admin-java
-
google-http-client-jackson2 cannot be excluded even when a JsonFactory is configured via FirebaseOptionsPeut-être pris @lahirumaramba l’a pris il y a 6 jours. Ouverte
Difficulté 4/5 3-5 jours Accessibilité débutants 48/100
firebase/firebase-admin-java#1231 · 1 personne assignée ·
Les mainteneurs répondent en général sous 4 jours
-
[BUG] RemoteConfig unit tests fail in non-English (e.g., Korean) Locales due to Date ParsingPeut-être pris @rathovarun1032 l’a pris il y a 204 jours. Ouverteapi: remoteconfig
firebase/firebase-admin-java#1196 · 1 commentaire · 2 personnes assignées ·
Les mainteneurs répondent en général sous 4 jours
-
Auth list tenants is not pageablePeut-être pris @siddharthmohan619-eng l’a pris il y a 209 jours. Ouverte
Difficulté 3/5 1-2 jours Accessibilité débutants 45/100
firebase/firebase-admin-java#1192 · 3 commentaires ·
Les mainteneurs répondent en général sous 4 jours
-
needs-triage type: feature request
Difficulté 3/5 1-2 jours Accessibilité débutants 45/100
firebase/firebase-admin-java#1149 · 1 commentaire ·
Les mainteneurs répondent en général sous 4 jours
-
needs-triage type: feature request
Difficulté 5/5 Plus d'une semaine Accessibilité débutants 45/100
firebase/firebase-admin-java#1142 · 2 commentaires ·
Les mainteneurs répondent en général sous 4 jours
Toutes les issues de firebase/firebase-admin-java
Issues similaires
-
Difficulté 2/5 1-3 heures Accessibilité débutants 72/100
-
area/docs
Difficulté 1/5 Moins d'une heure Accessibilité débutants 88/100
Les mainteneurs répondent en général sous 1 jour
-
BoxChart rejects valid List.of data with NullPointerExceptionPeut-être pris @PHJ2000 l’a pris aujourd’hui. Ouverte
Difficulté 2/5 1-3 heures Accessibilité débutants 76/100