简体   繁体   English

多个请求 go 进入 Java gRPC 服务器的同一线程

[英]Multiple requests go into same thread of Java gRPC Server

I have some micro services written by java, communicating with each other by gRPC, and are put into AWS ECS for running.我有一些java写的微服务,通过gRPC相互通信,放到AWS ECS中运行。 When I run the service and use a client program to call these services, I have noticed a very strange thing.当我运行服务并使用客户端程序调用这些服务时,我注意到了一件很奇怪的事情。

Normally, Tomcat's thread pool setting will make sure multiple requests will be handled by same amount of threads.通常,Tomcat 的线程池设置将确保多个请求将由相同数量的线程处理。 But when I run my program sometimes it will happen a thread start handling a new request when it is already handling a previous request.但是当我运行我的程序时,有时它会发生一个线程开始处理一个新请求,而它已经在处理一个先前的请求。 It makes the process thread-unsafe and thus errors were happened.它使进程线程不安全,因此发生了错误。 It happens very rare on normal services, and must happens when I send 10 requests into same service at the same time.它在正常服务上很少发生,并且必须在我同时向同一个服务发送 10 个请求时发生。

May I ask is there any setting that I have missed?请问有没有遗漏的设置? What I can search on the internet is I can only increase thread pool size.我可以在互联网上搜索的是我只能增加线程池大小。

----------2020/12/22 Edited---------- ----------2020/12/22 编辑----------

By entering debug mode, I have seen that one RPC request will be split to two tasks.通过进入调试模式,我看到一个 RPC 请求将被拆分为两个任务。 One for message itself and another for listener returned from the first task.一个用于消息本身,另一个用于从第一个任务返回的侦听器。 90% of my previous errors were happened between the time gap of these two tasks.我之前 90% 的错误发生在这两个任务的时间间隔之间。 Moreover, when running listener, ServerImpl class will use context to handle each RPC message, and each step in unit of methods that covers all written codes within over-rided listeners.此外,在运行侦听器时,ServerImpl class 将使用上下文来处理每个 RPC 消息,以及方法单元中的每个步骤,涵盖覆盖侦听器中的所有编写代码。 Therefore it will happen thread-switching during listener's run.因此它将在侦听器运行期间发生线程切换。

In StreamObserver 's documentation :StreamObserver的文档中

Implementations are not required to be thread-safe (but should be thread-compatible).实现不需要是线程安全的(但应该是线程兼容的)。

The "thread-compatible" is the important part for your question. “线程兼容”是您问题的重要部分。 It means you can't assume that every call to your instance will happen on the same Thread.这意味着您不能假设对您的实例的每次调用都会发生在同一个线程上。 This is true for virtually all of the gRPC API that is not-thread-safe.几乎所有非线程安全的 gRPC API 都是如此。 That doesn't matter to most code, but would impact things like ThreadLocal s.这对大多数代码无关紧要,但会影响ThreadLocal类的东西。

Basically, a thread is not "owned" by an RPC.基本上,线程不属于 RPC。 Instead, the RPCs share all the threads and when a callback needs to be delivered it just finds a thread to run the callback on.相反,RPC 共享所有线程,当需要传递回调时,它只是找到一个线程来运行回调。 This an async model that allows greater scaling compared to the mostly-blocking model used with servlets, as you can service more RPCs with fewer threads.这是一个异步 model,与与 servlets 一起使用的主要阻塞 model 相比,它允许更大的扩展,因为您可以用更少的线程服务更多的 RPC。 But it means as soon as you return from a callback that same thread may be used for some other RPC callback.但这意味着一旦您从回调中返回,同一线程可能会用于其他一些 RPC 回调。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM