@@ -1641,102 +1641,83 @@ Usage with Forking Servers
1641
1641
1642
1642
.. note::
1643
1643
1644
- Applications using Mongoid should follow `Mongoid's forking guidance
1645
- <https://mongodb.com/docs/mongoid/current/tutorials/mongoid-configuration/#usage-with-forking-servers>`_.
1646
- The guidance and sample code below is provided for applications using the
1647
- Ruby driver directly.
1644
+ Applications using Mongoid should follow `Mongoid's "Usage with Forking Servers" documentation
1645
+ <https://www.mongodb.com/docs/mongoid/current/reference/configuration/#usage-with-forking-servers>`_.
1646
+ The guidance below is provided for applications using the Ruby driver directly.
1648
1647
1649
1648
When using the Mongo Ruby driver in a Web application with a forking web server
1650
- such as Unicorn, Puma or Passenger, or when the application otherwise forks,
1651
- each process should generally each have their own ``Mongo::Client`` instances.
1652
- This is because:
1653
-
1654
- 1. The background threads remain in the parent process and are not transferred
1655
- to the child process.
1656
- 2. File descriptors like network sockets are shared between parent and
1657
- child processes.
1658
-
1659
- The driver attempts to detect client use from forked processes and
1660
- reestablish network connections when such use is detected, alleviating
1661
- the issue of file descriptor sharing.
1662
-
1663
- If both parent and child processes need to perform MongoDB operations,
1664
- it is recommended for each of the processes to create their own
1665
- ``Mongo::Client`` instances. Specifically, the child process should create
1666
- its own client instance and not use any of the instances that were created
1667
- in the parent.
1668
-
1669
- If the parent continues to perform MongoDB operations using an already
1670
- established client instance after forking children, this client instance will
1671
- continue to operate normally as long as no child uses it in any way.
1672
- The child processes will not inherit any of the monitoring threads, and
1673
- will not perform background operations on the client instance.
1674
-
1675
- If the parent does not need to perform MongoDB operation after forking
1676
- children (which is what typically happens in web applications), the parent
1677
- should close all of the client instances it created to free up connections
1678
- and cease background monitoring:
1649
+ such as Puma, or when the application otherwise forks, each process (parent and child)
1650
+ must have its own client connections. This is because:
1651
+
1652
+ 1. Background Ruby threads, such as those used by the Ruby MongoDB driver to
1653
+ monitor connection state, are **not** transferred to the child process.
1654
+ 2. File descriptors like network sockets **are** shared between parent and
1655
+ child processes, which can cause I/O conflicts.
1656
+
1657
+ Regarding (1), if you do not restart the driver's monitoring threads
1658
+ on the child process after forking, although your child may initially
1659
+ appear to function correctly, you will eventually see
1660
+ ``Mongo::Error::NoServerAvailable`` exceptions if/when your MongoDB cluster
1661
+ state changes, for example due to network errors or a maintenance event.
1662
+
1663
+ Regarding (2), if a child process reuses the parent's file descriptors, you
1664
+ will see ``Mongo::Error::SocketError`` errors with messages such as
1665
+ ``Errno::EPIPE: Broken pipe`` and ``EOFError: end of file reached``.
1666
+
1667
+ When the Ruby driver is used in a web application, if possible,
1668
+ we recommend to not create any ``Mongo::Client`` instances in the parent
1669
+ process (prior to the workers being forked), and instead only create client
1670
+ instances in the workers.
1671
+
1672
+ Manually Handling Process Forks
1673
+ -------------------------------
1674
+
1675
+ Certain advanced use cases, such as `Puma's fork_worker option <https://github.com/puma/puma/blob/master/docs/fork_worker.md>`_,
1676
+ require ``Mongo::Client`` instances to be open in both the parent
1677
+ and child processes. In this case, you must handle client
1678
+ reconnection manually.
1679
+
1680
+ To do this, immediately before forking, close any existing client connections
1681
+ on your parent process. This will prevent the parent process from experiencing
1682
+ network and monitoring errors due to the child's reuse of the parent's
1683
+ file descriptors.
1679
1684
1680
1685
.. code-block:: ruby
1681
1686
1682
- client.reconnect
1687
+ # Immediately before fork
1688
+ client.close
1683
1689
1684
1690
.. note::
1685
1691
1686
- If the parent process performs operations on the Mongo client and does not
1687
- close it, the parent process will continue consuming a connection slot
1688
- in the cluster and will continue monitoring the cluster for as long as the
1689
- parent remains alive.
1690
-
1691
- Reconnecting Client Instances
1692
- -----------------------------
1692
+ Calling ``Client#close`` does not disrupt database operations currently in-flight.
1693
+ Clients will automatically reconnect when you perform new operations.
1693
1694
1694
- When the Ruby driver is used in a web application, it is recommended to not
1695
- create any ``Mongo::Client`` instances in the management processes (prior to
1696
- the workers being forked), and instead only create client instances in the
1697
- workers.
1698
-
1699
- It is possible, although not recommended, to use the same ``Mongo::Client``
1700
- instances in parent and child processes. In order to do so, the instance
1701
- must be closed and reconnected in the child process so that the background
1702
- threads can be recreated:
1695
+ Then, immediately after forking, reconnect your clients in the newly
1696
+ forked child process, which will respawn the driver's monitoring threads.
1703
1697
1704
1698
.. code-block:: ruby
1705
1699
1706
- client.close
1700
+ # Immediately after fork
1707
1701
client.reconnect
1708
1702
1709
- .. note::
1710
-
1711
- This pattern should be used with Ruby driver version 2.6.2 or higher.
1712
- Previous driver versions did not recreate monitoring threads when
1713
- reconnecting.
1714
-
1715
- .. note::
1716
-
1717
- When closing and reconnecting the client instance in the child,
1718
- due to file descriptor sharing, the parent process may experience network
1719
- and monitoring errors.
1720
-
1721
- Web servers generally provide hooks that can be used by applications to
1722
- perform actions when the worker processes are forked. The recommended hooks
1723
- to use are:
1703
+ Most web servers provide hooks that can be used by applications to
1704
+ perform actions when the worker processes are forked. The recommended
1705
+ hooks are:
1724
1706
1725
- - For `Puma <https://puma.io/puma/>`_, ``before_fork`` to close clients in the
1726
- parent process and ``on_worker_boot`` to reconnect in the child processes.
1707
+ - For `Puma <https://puma.io/puma/#clustered-mode>`_,
1708
+ use ``before_fork`` and ``on_refork`` to close clients in
1709
+ the parent process and ``on_worker_boot`` to reconnect in the
1710
+ child processes.
1727
1711
- For `Unicorn <https://yhbt.net/unicorn/Unicorn/Configurator.html>`_,
1728
1712
``before_fork`` to close clients in the parent process and
1729
1713
``after_fork`` to reconnect clients in the child processes.
1730
1714
- For `Passenger <https://www.phusionpassenger.com/library/indepth/ruby/spawn_methods/#unintentional-file-descriptor-sharing>`_,
1731
1715
``starting_worker_process`` to reconnect clients in the child processes
1732
1716
(Passenger does not appear to have a pre-fork hook).
1733
1717
1734
- This documentation does not provide example code for using the aforementioned
1735
- hooks, because there is no standard for client instance management when
1736
- using the Ruby driver directly. `Mongoid documentation
1737
- <https://mongodb.com/docs/mongoid/current/tutorials/mongoid-configuration/#usage-with-forking-servers>`_
1738
- however provides examples for closing clients in the parent process and
1739
- reconnecting clients in the child processes.
1718
+ Refer to `Mongoid's "Usage with Forking Servers" documentation
1719
+ <https://www.mongodb.com/docs/mongoid/current/reference/configuration/#usage-with-forking-servers>`_
1720
+ for further examples.
1740
1721
1741
1722
Troubleshooting
1742
1723
---------------
0 commit comments