比方说:
- 提供DB连接数=
X
- 应用程序的并发实例的数目=
Y
- 应用程序的每个实例中的数据库连接池的最大大小=
X/Y
这有点简单,因为你可能想连接到你的d来自其他客户的数据库(例如支持工具),所以也许一个更安全的公式是(X * 0.95)/Y
。
现在,您已确保您的应用程序层不会遇到'没有数据库连接存在'的问题。但是,如果(X * 0.95)/Y
为25,并且您有超过25个并发请求通过您的应用程序(需要同时连接数据库),那么某些请求在尝试获取数据库连接时会遇到延迟,并且如果这些延迟超过配置的超时,他们将导致失败的请求。
如果你可以限制你的应用程序的吞吐量,这样你永远不会有超过(X * 0.95)/Y
的并发'获取数据库连接'请求,那么他们就会问题消失。但是,当然,这通常不现实(事实上,因为更少是更少的......告诉你的客户停止与你交谈通常是一个奇怪的信号发送)。这使我们想到问题的症结所在:
现在应用程序具有根据负载自动缩放的能力。
向上缩放不是免费的。如果在处理100000N
并发请求时处理N
并发请求时需要相同的响应性,则必须提供;您必须扩大这些请求所需的资源。因此,如果他们使用数据库连接,那么数据库支持的并发连接数将不得不增加。如果服务器端资源不能增长到客户端使用率,那么您需要某种形式的背压,或者需要仔细管理服务器端资源。管理服务器端资源的一种常用方法是...
- 让您的服务无阻塞即代表每个客户端请求的线程池和您的服务中通过回调响应客户端(春季通过DeferredResult利于这个或它的异步框架或它的RX集成)
- 配置您的服务器端资源(如您的数据库允许使用的最大连接数)来匹配您的服务根据您的服务实例的客户端请求的总规模最大吞吐量的线程池
客户端请求的线程池的限制每个s中当前活动请求的数量它的服务实例而不是限制客户可以提交的请求数量。这种方法允许服务向上扩展(达到所有服务实例中由客户端请求线程池大小表示的限制),并且这样做允许服务所有者安全地防止资源(例如其数据库)过载。由于所有客户端请求都被接受(并委托给客户端请求线程池),客户端请求从不被拒绝,所以从他们的角度来看,就好像缩放是无缝的一样。
这种设计通过负载均衡器进一步增强了服务实例的集群,这些服务实例通过它们分配流量(循环或甚至通过一些机制,由此每个节点报告它的“忙碌”指导负载平衡器的行为,例如,将更多的流量引导到NodeA,因为它被利用不足,因为它被过度利用而导致较少的到NodeB的流量。
上述对非阻塞服务的描述只是表面划痕;他们还有很多东西(包括文档,博客文章,互联网上有用的比特币),但考虑到你的问题陈述(面对来自客户端的负载增加时对服务器端资源的担忧),这听起来像是一件好事适合。
这是一个很好的建议。将在此探索更多 – jubin