0
@@ -39,6 +39,85 @@ using namespace std;
0
+ * Multi-process usage support for ApplicationPool.
0
+ * ApplicationPoolServer implements a client/server architecture for ApplicationPool.
0
+ * This allows one to use ApplicationPool in a multi-process environment (unlike
0
+ * StandardApplicationPool). The cache/pool data is stored in the server. Different
0
+ * processes can then access the pool through the server.
0
+ * ApplicationPoolServer itself does not inherit ApplicationPool. Instead, it returns
0
+ * an ApplicationPool object via the connect() call. For example:
0
+ * // Create an ApplicationPoolServer.
0
+ * ApplicationPoolServer server(...);
0
+ * // Now fork a child process, like Apache's prefork MPM eventually will.
0
+ * // Connect to the server. After connection, we have an ApplicationPool
0
+ * ApplicationPoolPtr pool(server.connect());
0
+ * // We don't need to connect to the server anymore, so we detach from it.
0
+ * // This frees up some resources, such as file descriptors.
0
+ * ApplicationPool::SessionPtr session(pool->get("/home/webapps/foo"));
0
+ * do_something_with(session);
0
+ * waitpid(pid, NULL, 0);
0
+ * <h2>Implementation notes</h2>
0
+ * <h3>Separate server executable</h3>
0
+ * The actual server is implemented in ApplicationPoolServerExecutable.cpp, this class is
0
+ * just a convenience class for starting/stopping the server executable and connecting
0
+ * In the past, the server logic itself was implemented in this class. This implies that
0
+ * the ApplicationPool server ran inside the Apache process. This presented us with several
0
+ * - Because of the usage of threads in the ApplicationPool server, the Apache VM size would
0
+ * go way up. This gave people the (wrong) impression that Passenger uses a lot of memory,
0
+ * or that it leaks memory.
0
+ * - Although it's not entirely confirmed, we suspect that it caused heap fragmentation as
0
+ * well. Apache allocates lots and lots of small objects on the heap, and ApplicationPool
0
+ * server isn't exactly helping. This too gave people the (wrong) impression that
0
+ * Passenger leaks memory.
0
+ * - It would unnecessarily bloat the VM size of Apache worker processes.
0
+ * - We had to resort to all kinds of tricks to make sure that fork()ing a process doesn't
0
+ * result in file descriptor leaks.
0
+ * - Despite everything, there was still a small chance that file descriptor leaks would
0
+ * occur, and this could not be fixed. The reason for this is that the Apache control
0
+ * process may call fork() right after the ApplicationPool server has established a new
0
+ * connection with a client.
0
+ * Because of these problems, it was decided to split the ApplicationPool server to a
0
+ * separate executable. This comes with no performance hit.
0
+ * <h3>Anonymous server socket</h3>
0
+ * Notice that ApplicationPoolServer does do not use TCP sockets at all, or even named Unix
0
+ * sockets, despite being a server that can handle multiple clients! So ApplicationPoolServer
0
+ * will expose no open ports or temporary Unix socket files. Only child processes are able
0
+ * to use the ApplicationPoolServer.
0
+ * This is implemented through anonymous Unix sockets (<tt>socketpair()</tt>) and file descriptor
0
+ * passing. It allows one to emulate <tt>accept()</tt>. ApplicationPoolServer is connected to
0
+ * the server executable through a Unix socket pair. connect() sends a connect request to the
0
+ * server through that socket. The server will then create a new socket pair, and pass one of
0
+ * them back. This new socket pair represents the newly established connection.
0
class ApplicationPoolServer {
Comments
No one has commented yet.