将内存或进程或线程池资源限制到 spring 控制器
Limit memory or process or thread pool resources to a spring controller
我有 Spring 带有 3 个控制器的应用程序,每个都支持一些用例集,比如
SmallController - supports 1 usecase
MediumController - supports 3 usecases
LargeController - Supports 20 usecases
问题是,如果我最终收到 SmallController
的大量请求,比如说 1000 TPS,消耗了我 50-60% 的资源,它最终会耗尽我剩下的 23 个用例吗?
如果是这样,有没有一种方法可以配置我的 Spring 应用程序,使我发送到 SmallController
的请求激增不会为它分配 memory/threads 等超出特定预定义的资源值,以便 MediumController
和 LargeController
不会开始挨饿?
基本上,如果我有 100 Mbs 的内存,假设有 100 个线程池限制,
是否可以防止 SmallController
超过 50 Mbs 的内存并说最多 40 个线程,同时保证 MediumController
和 LargeController
的剩余资源?
如果根本没有现成的工具来控制资源的使用,有人可以建议一种可以探索的方法来开始构建一个吗?
Java 没有特定线程拥有的内存量的概念。内存由整个进程拥有。 运行 堆转储上的堆分析器可能允许您将分配归因于特定线程或线程池,但这是一种离线分析,无法在运行时廉价地执行。
因此,如果您想对资源进行分区,您应该启动多个应用程序并为每个应用程序设置资源限制。
我的建议是引入“节流”(Rate Limit)。
你可以有自己的实现或者你可以使用像 Buket4j 这样的东西
例如:https://www.baeldung.com/spring-bucket4j.
如果你不想污染控制器的源代码,你可以在 MVC 拦截器级别这样做(更干净的解决方案,在拦截器 preHandle
方法中处理)。
如果您想控制 SmallController
中的许可数,那么您可以尝试使用 Semaphore。请注意,这只是一个建议,如果这不符合要求,您可以探索其他选项。
@RestController
public class SmallController{
private Semaphore semaphore = new Semaphore(10);//no of calls allowed
@GetMapping("/someaction")
public ResponseEntity<T> action(){
semaphore.acquire(); // this will block the request until permit is available.
try{
//resource intensive operation
}finally{
semaphore.release();
}
// return response entity object
}
}
如果你想要非阻塞信号量,你可以使用semaphore.tryAcquire()
。您可以检查它是否 returns false
然后回复说 'resource busy'
内存在运行时间级别,不是控制器级别。让我们备份。您想要管理资源以使应用程序仍然响应
即使可能,在应用程序级别执行此操作也会让您头疼。听起来您真的很想实施 API 使用计划。然后,您可以限制和/或拒绝使系统过载的请求,以保持系统响应。希望你有这种或另一种口味的(AWS APIGW、Kong 等)
否则,您可能需要考虑使用不同的配置文件部署您的应用程序,以便控制器 运行 在不同的盒子上隔离故障并保持应用程序响应,或者将其分解为单独的微服务。这应该会产生更好的性能,并使您能够扩展应用程序的各个部分。
我知道这些答案假设您有这些选项可用,希望您有。
我有 Spring 带有 3 个控制器的应用程序,每个都支持一些用例集,比如
SmallController - supports 1 usecase
MediumController - supports 3 usecases
LargeController - Supports 20 usecases
问题是,如果我最终收到 SmallController
的大量请求,比如说 1000 TPS,消耗了我 50-60% 的资源,它最终会耗尽我剩下的 23 个用例吗?
如果是这样,有没有一种方法可以配置我的 Spring 应用程序,使我发送到 SmallController
的请求激增不会为它分配 memory/threads 等超出特定预定义的资源值,以便 MediumController
和 LargeController
不会开始挨饿?
基本上,如果我有 100 Mbs 的内存,假设有 100 个线程池限制,
是否可以防止 SmallController
超过 50 Mbs 的内存并说最多 40 个线程,同时保证 MediumController
和 LargeController
的剩余资源?
如果根本没有现成的工具来控制资源的使用,有人可以建议一种可以探索的方法来开始构建一个吗?
Java 没有特定线程拥有的内存量的概念。内存由整个进程拥有。 运行 堆转储上的堆分析器可能允许您将分配归因于特定线程或线程池,但这是一种离线分析,无法在运行时廉价地执行。
因此,如果您想对资源进行分区,您应该启动多个应用程序并为每个应用程序设置资源限制。
我的建议是引入“节流”(Rate Limit)。 你可以有自己的实现或者你可以使用像 Buket4j 这样的东西 例如:https://www.baeldung.com/spring-bucket4j.
如果你不想污染控制器的源代码,你可以在 MVC 拦截器级别这样做(更干净的解决方案,在拦截器 preHandle
方法中处理)。
如果您想控制 SmallController
中的许可数,那么您可以尝试使用 Semaphore。请注意,这只是一个建议,如果这不符合要求,您可以探索其他选项。
@RestController
public class SmallController{
private Semaphore semaphore = new Semaphore(10);//no of calls allowed
@GetMapping("/someaction")
public ResponseEntity<T> action(){
semaphore.acquire(); // this will block the request until permit is available.
try{
//resource intensive operation
}finally{
semaphore.release();
}
// return response entity object
}
}
如果你想要非阻塞信号量,你可以使用semaphore.tryAcquire()
。您可以检查它是否 returns false
然后回复说 'resource busy'
内存在运行时间级别,不是控制器级别。让我们备份。您想要管理资源以使应用程序仍然响应
即使可能,在应用程序级别执行此操作也会让您头疼。听起来您真的很想实施 API 使用计划。然后,您可以限制和/或拒绝使系统过载的请求,以保持系统响应。希望你有这种或另一种口味的(AWS APIGW、Kong 等)
否则,您可能需要考虑使用不同的配置文件部署您的应用程序,以便控制器 运行 在不同的盒子上隔离故障并保持应用程序响应,或者将其分解为单独的微服务。这应该会产生更好的性能,并使您能够扩展应用程序的各个部分。
我知道这些答案假设您有这些选项可用,希望您有。