简体   繁体   English

微服务的数据库连接池策略

[英]Database connection pool strategy for micro services

We are trying to convert our monolithic application to a micro services based architecture.我们正在尝试将我们的单体应用程序转换为基于微服务的架构。 We use Postgresql as one of our database in the monolithic application with BoneCP for connection pooling.我们在单片应用程序中使用 Postgresql 作为我们的数据库之一,使用 BoneCP 进行连接池。

When this monolith is split to a number of independent micro-services with each of them running in a different JVM, I can think about two options for connection pooling当这个单体被拆分为多个独立的微服务,每个微服务都在不同的 JVM 中运行时,我可以考虑两种连接池的选择

  1. BoneCP or any decent connection pool for each microservice - My initial research shows that this is the primary choice. BoneCP 或每个微服务的任何像样的连接池 - 我的初步研究表明这是主要选择。 It is possible to have a fine grained control of connection requirements for each service.But, down side is that as the number of services increase, number of connection pool also increases and eventually there will be too many idle connections assuming that minimum connections in each pool is greater than 0.可以对每个服务的连接需求进行细粒度控制。但是,缺点是随着服务数量的增加,连接池的数量也会增加,假设每个服务中的最小连接数,最终会有太多空闲连接池大于 0。
  2. Rely on database specific extensions like PGBouncer - This approach has the advantage that connection pool is managed by a central source rather than a pool for each micro service and hence number of idle connections can be brought down.依赖于数据库特定的扩展,如 PGBouncer - 这种方法的优点是连接池由中央源管理,而不是每个微服务的池,因此可以减少空闲连接的数量。 It is also language/technology agnostic.它也是语言/技术不可知的。 Down side is that these extensions are database specific and some of the functionalities in JDBC may not work.不利的一面是这些扩展是特定于数据库的,JDBC 中的某些功能可能不起作用。 For eg: Prepared statments may not work with PGBouncer in Transaction_Pooling mode.例如:准备好的语句可能无法在 Transaction_Pooling 模式下与 PGBouncer 一起使用。

In our case most of the micro-services(at least 50) will be connecting to the same Postgres server even though the database can be different.在我们的例子中,大多数微服务(至少 50 个)将连接到同一个 Postgres 服务器,即使数据库可能不同。 So, if we go with option 1, there is a higher chance of creating too many idle connections.The traffic to most of our services are very moderate and the rationale behind moving to micro-service is for easier deployment, scaling etc.因此,如果我们选择选项 1,则更有可能创建过多的空闲连接。我们大多数服务的流量非常适中,迁移到微服务的基本原理是为了更容易部署、扩展等。

Has anyone faced a similar problem while adopting micro-services architecture?有没有人在采用微服务架构时遇到过类似的问题? Is there a better way of solving this problem in micro-service world?在微服务世界有没有更好的方法来解决这个问题?

I don't see how pgbouncer will solve any of the problems you would have with the first approach. 我不知道pgbouncer将如何解决您在第一种方法中遇到的任何问题。 There are many reasons to use pgbouncer but I don't think they are really applicable here. 使用pgbouncer的原因有很多,但我认为它们并不适用于此。

Also, in my experience, while idle connections can be an issue, they probably will not be on the scale you are talking about. 另外,根据我的经验,虽然空闲连接可能是一个问题,但它们可能不会达到你所说的规模。 I mean we are not talking hundreds of idle connections right? 我的意思是我们不是在谈论数百个闲置连接吗?

More critically, one key thing that a microservices approach would give you is an ability to move dbs off to other servers. 更重要的是,微服务方法给你的一个关键是能够将dbs移到其他服务器上。 If you do this, then having your connection pool centrally managed makes this harder to do. 如果这样做,那么集中管理连接池会使这更难做到。

Per-service pool is generally more flexible and it makes your infrastructure quite a bit more flexible too. 每服务池通常更灵活,它使您的基础架构也更加灵活。

I have responded a similar question here: Microservices - Connection Pooling when connecting to a single legacy database 我在这里回答了类似的问题:微服务- 连接到单个遗留数据库时的连接池

"I am facing a similar dilemma at my work and I can share the conclusions we have reached so far. “我的工作面临着类似的两难困境,我可以分享迄今为止所得出的结论。

There is no silver bullet at the moment, so: 目前没有银弹,所以:

1 - Calculate the number of connections dividing the total desired number of connections for the instances of microservices will work well if you have a situation where your microservices don't need to drastically elastic scale. 1 - 如果您的微服务不需要具有极大的弹性比例,那么计算微服务实例所需的总连接数的连接数将很有效。

2 - Not having a pool at all and let the connections be opened on demand. 2 - 根本没有游泳池,可以按需打开连接。 This is what is being used in functional programming (like Amazon lambdas). 这就是函数式编程中使用的东西(如亚马逊lambdas)。 It will reduce the total number of open connections but the downside is that you lose performance as per opening connections on the fly is expensive. 它将减少打开连接的总数,但缺点是你失去了性能,因为开启的连接是昂贵的。

You could implement some sort of topic that let your service know that the number of instances changed in a listener and update the total connection number, but it is a complex solution and goes against the microservice principle that you should not change the configurations of the service after it started running. 您可以实现某种主题,让您的服务知道在侦听器中更改实例的数量并更新总连接数,但这是一个复杂的解决方案,违反微服务原则,您不应更改服务的配置它开始运行后。

Conclusion: I would calculate the number if the microservice tend to not grow in scale and without a pool if it does need to grow elastically and exponentially, in this last case make sure that a retry is in place in case it does not get a connection in the first attempt. 结论:如果微服务倾向于没有规模增长而没有池,如果它确实需要弹性地和指数地增长,我将计算数量,在最后一种情况下确保重试已到位,以防它没有得到连接在第一次尝试。

There is an interesting grey area here awaiting for a better way of controlling pools of connections in microservices. 这里有一个有趣的灰色区域,等待更好的方法来控制微服务中的连接池。

In time, and to make the problem even more interesting, I recommend reading the article About Pool Sizing from HikariCP: https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing The ideal concurrent connections in a database are actually smaller than most people think." 及时,为了使问题更加有趣,我建议阅读HikariCP上关于池大小的文章: https//github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing数据库中理想的并发连接是实际上比大多数人想象的要小。“

Let's say you have the limiting requirement - only 10 connections to the database. 假设您有限制要求 - 只有10个数据库连接。 You can run 10 instances of the microservice with the connection pool limited to 1 connection max. 您可以运行10个微服务实例,连接池最多只能连接1个连接。 Or you can run 3 instances with pool max=3. 或者,您可以使用pool max = 3运行3个实例。 The centralized connection pool, which would serve multiple services in the cloud, sounds bad (the typical single point of failure). 集中式连接池可以为云中的多个服务提供服务,听起来很糟糕(典型的单点故障)。

Maybe group some smaller number of microservices into modulith and use karaf, or other osgi container as a runtime for them.也许将一些较少数量的微服务分组到模块中,并使用 karaf 或其他 osgi 容器作为它们的运行时。 Then you can create bundle that will represent a connection-pool for your database so other bundles — microservices can use it.然后,您可以创建代表数据库连接池的包,以便其他包——微服务可以使用它。 But I'm not sure if it will solve your architecture problem.但我不确定它是否会解决您的架构问题。

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

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