当前位置: 首页 > 知识库问答 >
问题:

如何正确管理Kubernetes中的Java Spring应用自动伸缩?

周正真
2023-03-14

我正试图在Kubernetes(托管在Google Kubernetes引擎中)中为我的Java Spring应用程序设置自动缩放。我面临两个问题:

>

  • Spring应用程序在开始时使用了大量cpu(大约250mCPU*,但有时甚至是500mCPU),这实际上打破了自动缩放,因为该应用程序的某些实例在超过或少于1分钟后(Spring上下文启动等),仅使用50mCPU。因为在某些应用程序使用少量mCPU的环境中(几乎在夜间的每个环境中),我想将请求的cpu设置为最大200mCPU(=80%限制cpu)(甚至更少!)。因此,自动缩放将更有意义。但我不能真正做到这一点,因为Spring的开始很繁重,如果我给他太少的cpu,它就不会完成。

    当应用程序开始接收流量时(当由于自动缩放事件而创建新pod时),其cpu使用量可能会跳到标准使用量的200%左右,然后再返回到100%——看起来并不是因为太多请求被推送到新pod,看起来JVM只是在开始时速度较慢,在请求时接收到太多流量。JVM似乎需要一些类似预热的功能(所以不要突然将1/n的流量推到新的pod,而是将流量缓慢地切换到新pod)。由于这种行为,自动缩放有时会变得疯狂——当它真的只需要多出一个吊舱时,它可以放大很多吊舱,然后缩小。。。

    *在GKE,1000兆CPU = 1个内核

    上传的图像上,我们可以看到cpu图表。在第一种情况下,我们可以看到启动后的cpu使用量比开始时小得多。在第二种情况下,我们可以发现两个问题:开始时cpu使用率高,然后是宽限期(就绪探测初始*延迟尚未完成),然后是在接收流量开始时的高选取。

    *我已将准备状态探测初始延迟设置为比上下文加载更长。

    图1 图2

    我在互联网上发现的唯一一件事就是将容器添加到该 pod 中,它只会执行“睡眠 x”,然后死亡。并将设置到该容器请求的mCPU添加到将在Spring应用程序启动时使用的数量(然后我必须增加该Spring应用程序容器的CPU限制,但这无论如何都不会造成伤害,因为自动缩放应该防止Spring应用程序饿死节点中的其他应用程序)。

    我真的非常感谢任何建议。

  • 共有1个答案

    慕容明煦
    2023-03-14

    诚然,Spring应用程序并不是对容器最友好的东西,但是您可以尝试的东西很少:

    1. 在启动时,Spring自动连接bean并执行依赖注入、在内存中创建对象等。所有这些都是CPU密集型的。如果您为机架分配较少的CPU,则逻辑上会增加启动时间。您可以在这里执行以下操作:

    > < li>

    使用< code>startupProbe并给应用程序留出启动时间。这里很好地解释了如何计算延迟和阈值

    调整您的部署策略中的maxSurgemaxUnavailable,因为它最适合您的情况(例如,您可能有10个副本,最大不可用的喘振/最大不可用为10%,所以您的pods将一个接一个地缓慢推出)。这将有助于减少整个应用程序副本上的流量峰值(文档在这里)。

    如果您的用例允许,您可以考虑延迟加载您的Spring应用程序,这意味着它不会在启动时创建所有对象,而是会等到它们被使用为止。这可能有点危险,因为在某些情况下可能无法在启动时发现问题。

    > < li>

    调整自动缩放阈值和时间(默认为3分钟,afaik ),以允许您的部署顺利展开,而不会触发自动缩放。

    编写自定义自动扩展指标,而不是按CPU扩展。这需要一些工作,但可能会永远解决你的缩放问题(相关文件)。

    最后,你用边车建议的东西看起来像是一个黑客:)虽然没有尝试过,所以不能真正分辨出利弊。

    不幸的是,SpringBoot(或Java)K8没有银弹,但情况比几年前好了很多。如果我找到一些有用的资源。我会回来把它们链接到这里。

    希望以上有所帮助。

    干杯

     类似资料:
    • 读完本文后您应该可以自己创建chart,并创建自己的私有chart仓库。 Helm是一个kubernetes应用的包管理工具,用来管理charts——预先配置好的安装包资源,有点类似于Ubuntu的APT和CentOS中的yum。 Helm chart是用来封装kubernetes原生应用程序的yaml文件,可以在你部署应用的时候自定义应用程序的一些metadata,便与应用程序的分发。 Helm

    • 所以比正确答案更重要的是,我真的很想知道为什么这不起作用。 下面是一些我无法使用的示例代码: 如果我像这样对着它打一个卷曲:

    • 我在努力理解错误处理是如何在Node.js流管道内工作的,最后我用一个简单的游乐场进行了实验,这让事情变得非常清楚。 我将此作为一个自我回答的问题发布。也许有人觉得这很有帮助:)

    • JS引入了集群模块来扩展应用程序以实现性能优化。我们让Kubernetes做同样的事情。 我很困惑,如果两者都是为了同一个目的?我的假设是集群最多可以产生8个进程(如果有4个cpu核,每个cpu核有2个线程),在Kubernetes中没有这样的限制。

    • 我写了一个类,其中有连接池和流水线,使用这个类的方法类似于(我删除了一个循环,但setKey将发生在循环中): 因此,一旦管道上的项目数超过200,i同步项目并清除管道,然后重新启动。问题是如何使用此设置将连接正确地返回到池。 据我所知,我必须将jedispool.getResource()包装到try块中,但我无法考虑如何将它与管道和计数器结合在一起。

    • 我正在尝试使用DWM为我的窗体制作一个自定义的窗口框架。平台是C# WinForms,Pinvoking DWM。 按照MSDN关于用DWM制作定制窗框的文章,主要步骤如下: 移除标准帧(非客户端区域),回复WM_NCCALCSIZE消息返回0 使用DwmExtenFrameIntoClientArea函数将框架扩展到客户端区域 我以下一种方式处理WM_NCCALCSIZE消息: 根据WM_ NC