Open Laith-jalal opened 1 month ago
I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.
The method should not have any thread issue, because to achieve high notification throughput, we need to call the method in multiple thread.
In production, we are using the predecessor "sendmulticast" method with 6+ thread to achieve 80k+ rpm on one java process. And we didn't face with any thread safety issue.
When using FCM admin SDK v9.3.0 sendEach
api with 20 threads, 500 tokens per thread, we encountered OutOfMemoryError,
Caused by: java.lang.OutOfMemoryError: unable to create native thread: possibly out of memory or process/resource limits reached at java.base/java.lang.Thread.start0(Native Method) at java.base/java.lang.Thread.start(Thread.java:809) at java.base/java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:945) at java.base/java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1364) at com.google.common.util.concurrent.MoreExecutors$ListeningDecorator.execute(MoreExecutors.java:640) at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:145) at com.google.common.util.concurrent.AbstractListeningExecutorService.submit(AbstractListeningExecutorService.java:79) at com.google.firebase.FirebaseApp.submit(FirebaseApp.java:384) at com.google.firebase.ImplFirebaseTrampolines.submitCallable(ImplFirebaseTrampolines.java:98) at com.google.firebase.internal.CallableOperation.callAsync(CallableOperation.java:47) at com.google.firebase.messaging.FirebaseMessaging$2.execute(FirebaseMessaging.java:227) at com.google.firebase.messaging.FirebaseMessaging$2.execute(FirebaseMessaging.java:222) at com.google.firebase.internal.CallableOperation.call(CallableOperation.java:36) at com.google.firebase.messaging.FirebaseMessaging.sendEach(FirebaseMessaging.java:189)
When using FCM admin SDK v9.3.0
sendEach
api with 20 threads, 500 tokens per thread, we encountered OutOfMemoryError,Caused by: java.lang.OutOfMemoryError: unable to create native thread: possibly out of memory or process/resource limits reached at java.base/java.lang.Thread.start0(Native Method) at java.base/java.lang.Thread.start(Thread.java:809) at java.base/java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:945) at java.base/java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1364) at com.google.common.util.concurrent.MoreExecutors$ListeningDecorator.execute(MoreExecutors.java:640) at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:145) at com.google.common.util.concurrent.AbstractListeningExecutorService.submit(AbstractListeningExecutorService.java:79) at com.google.firebase.FirebaseApp.submit(FirebaseApp.java:384) at com.google.firebase.ImplFirebaseTrampolines.submitCallable(ImplFirebaseTrampolines.java:98) at com.google.firebase.internal.CallableOperation.callAsync(CallableOperation.java:47) at com.google.firebase.messaging.FirebaseMessaging$2.execute(FirebaseMessaging.java:227) at com.google.firebase.messaging.FirebaseMessaging$2.execute(FirebaseMessaging.java:222) at com.google.firebase.internal.CallableOperation.call(CallableOperation.java:36) at com.google.firebase.messaging.FirebaseMessaging.sendEach(FirebaseMessaging.java:189)
It is normal :). sendEachForMulticast
has performance issues. The method creates a thread and opens a connection per device token. You can use old API until 20 June or try to limit concurrency or device token count. Concurrent sending requests should not be high, depending on your hardware, RAM and network socket limits.
You can check the issue. https://github.com/firebase/firebase-admin-java/issues/834#issuecomment-1890969169
I was going through the
sendEachForMulticast
logic and didn't find anything to tell if it's thread safe or not, my current implementation is by calling the following in a new threadFirebaseMessaging.getInstance().sendEachForMulticast(message)
Am I messing something here ? is my implementation thread safe ?