You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

79 lines
2.9 KiB

  1. This module makes it possible to use PgBouncer_ as a connection pooler
  2. for odoo.
  3. .. _PgBouncer: https://pgbouncer.github.io/
  4. Why isn't odoo's connection pooling good enough?
  5. ================================================
  6. Odoo's builtin connection pooling works at process level: each Odoo process
  7. has its own ConnectionPool_, limited to ``db_maxconn``.
  8. It does the job of re-using open connections available in the pool.
  9. But it never closes these connections, `unless reaching db_maxconn`_.
  10. .. _ConnectionPool: https://github.com/odoo/odoo/blob/12.0/odoo/sql_db.py#L525
  11. .. _`unless reaching db_maxconn`: https://github.com/odoo/odoo/blob/12.0/odoo/sql_db.py#L593
  12. In practice, we observe that each odoo worker will end up
  13. with up to 3 open connection in its pool.
  14. With 10 http workers, that's up to 30 connection continuously open just
  15. for one single instance.
  16. Here comes PgBouncer
  17. ====================
  18. PgBouncer will help to limit this number of open connections,
  19. by sharing a pool of connections at the instance level, between
  20. all workers. Odoo workers will still have up to 3 open connections,
  21. but these will be connections to PgBouncer, that on its side will
  22. close unnecessary connections to pg.
  23. This has proven to help performances on Odoo deployments with
  24. multiple instances.
  25. It allows you to define how resources should be shared,
  26. according to your priorities, e.g. :
  27. * key odoo instance on host A can open up to 30 connections
  28. * while odoo instance on host B, dedicated to reports,
  29. can open up to 10 connections only
  30. And most importantly, it helps you to ensure that
  31. ``max_connections`` will never be reached on pg server side.
  32. Why is this module needed?
  33. ==========================
  34. When configuring PgBouncer, you can choose between 2 transaction pooling modes:
  35. * `pool_mode = session`
  36. * `pool_mode = transaction`
  37. If we choose `pool_mode = session`, then one server connection will be tied
  38. to a given odoo process until its death, which is exactly what we're trying
  39. to change. Thus, to release the server connection once the transaction is
  40. complete, we use `pool_mode = transaction`.
  41. This works fine, except for Odoo's longpolling features that relies
  42. on the `LISTEN/NOTIFY`_ mechanism from pg, which is `not compatible`_ with that
  43. mode.
  44. .. _`LISTEN/NOTIFY`: https://www.postgresql.org/docs/9.6/static/sql-notify.html
  45. .. _`not compatible`: https://wiki.postgresql.org/wiki/PgBouncer
  46. To be more precise, `NOTIFY` statements are properly transfered by PgBouncer
  47. in that mode; only the `LISTEN` statement isn't (because it needs to keep the
  48. server connection open).
  49. So for the unique "listening" connection per instance that requires this
  50. statement (here_), we need odoo to connect directly to the pg server, bypassing
  51. PgBouncer.
  52. That's what this module implements, by overriding the relevant method
  53. of the Dispatcher_.
  54. .. _here: https://github.com/odoo/odoo/blob/12.0/addons/bus/models/bus.py#L166
  55. .. _Dispatcher: https://github.com/odoo/odoo/blob/12.0/addons/bus/models/bus.py#L105