这个问题没有一个单一的答案,但我不知道还能在哪里问这个问题。
我在一个大型企业系统上工作,该系统使用 Tomcat 运行在容器中运行的 REST 服务,由 kubernetes 管理。
Tomcat,或者实际上任何请求处理器,都有一个"最大线程数"属性,这样,如果有足够的请求导致创建许多线程,如果创建的线程数达到定义的限制,它将把额外的请求放入队列中(受另一个属性的值限制(,然后可能在队列已满后请求被拒绝。
考虑是否应将此属性设置为可能达到的值,或者是否应将其设置为有效无穷大是合理的。
有许多场景需要考虑,尽管唯一有趣的情况是流量极高于正常水平时,无论是来自真实的客户流量,还是恶意的 ddos 流量。
在托管容器环境和其他类似情况下,这也引出了一个问题,即应该运行多少个实例、Pod 或容器来运行服务的副本。 我假设您希望尽可能少地使用它们,以减少每个 pod 的资源重复,这将增加每个容器中的平均线程数,但我认为这比将它们薄薄地分布在一组容器中要好。
我的团队中的一些成员认为最好将"最大线程数"属性设置为有效无穷大。
对此有什么合理的想法?
作为一般规则,我建议尝试通过运行更多 pod(可以在多个主机上轻松调度(而不是运行更多线程来扩展。 群集调度 16 个 1 核 Pod 也比计划 1 个 16 核 Pod 更容易。
就线程数而言,这有点取决于您的流程正在做多少工作。 典型的 Web 应用程序花费大部分时间与数据库通信,并执行少量本地计算,因此您通常可以将其设置为运行 50 或 100 个线程,但仍具有 1.0 CPU 的限制,并有效地使用资源。 如果它的计算量很大(比如说,它正在做真正的图像处理或机器学习工作(,那么每个 CPU 可能被限制为 1 个线程。 不好的情况是,您的进程分配了 16 个线程,但系统实际上只有 4 个可用内核,在这种情况下,您的进程将受到限制,但您确实希望它扩大规模。
另一个需要注意的重要不良状态是线程池已满。 如果是这样,请求将被排队,正如你所注意到的,但如果其中一些请求是 Kubernetes 运行状况检查探测,这可能会导致集群将您的服务记录为不正常。 这实际上可能导致一个糟糕的螺旋,其中过载的副本被终止(因为它没有及时回答运行状况检查(,因此它的负载被发送到其他副本,这些副本也会过载并停止回答运行状况检查。 您可以通过运行更多 Pod 或更多线程来逃避这种情况。 (...或者通过在运行时重写应用程序,而运行时没有像这样固定的上限容量。
还值得一读有关水平 Pod 自动缩放器的信息。 如果你可以连接一些指标(CPU 利用率、线程池计数(来表示"我需要更多 pod",那么 Kubernetes 可以自动为你创建更多,并在不需要的时候缩小它们。