Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | <html> |
michael@0 | 2 | <head> |
michael@0 | 3 | <!-- |
michael@0 | 4 | /* |
michael@0 | 5 | * ==================================================================== |
michael@0 | 6 | * Licensed to the Apache Software Foundation (ASF) under one |
michael@0 | 7 | * or more contributor license agreements. See the NOTICE file |
michael@0 | 8 | * distributed with this work for additional information |
michael@0 | 9 | * regarding copyright ownership. The ASF licenses this file |
michael@0 | 10 | * to you under the Apache License, Version 2.0 (the |
michael@0 | 11 | * "License"); you may not use this file except in compliance |
michael@0 | 12 | * with the License. You may obtain a copy of the License at |
michael@0 | 13 | * |
michael@0 | 14 | * http://www.apache.org/licenses/LICENSE-2.0 |
michael@0 | 15 | * |
michael@0 | 16 | * Unless required by applicable law or agreed to in writing, |
michael@0 | 17 | * software distributed under the License is distributed on an |
michael@0 | 18 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
michael@0 | 19 | * KIND, either express or implied. See the License for the |
michael@0 | 20 | * specific language governing permissions and limitations |
michael@0 | 21 | * under the License. |
michael@0 | 22 | * ==================================================================== |
michael@0 | 23 | * |
michael@0 | 24 | * This software consists of voluntary contributions made by many |
michael@0 | 25 | * individuals on behalf of the Apache Software Foundation. For more |
michael@0 | 26 | * information on the Apache Software Foundation, please see |
michael@0 | 27 | * <http://www.apache.org/>. |
michael@0 | 28 | * |
michael@0 | 29 | */ |
michael@0 | 30 | --> |
michael@0 | 31 | </head> |
michael@0 | 32 | <body> |
michael@0 | 33 | The implementation of a thread-safe client connection manager. |
michael@0 | 34 | |
michael@0 | 35 | <center> |
michael@0 | 36 | <img src="doc-files/tsccm-structure.png" alt="Relation Diagram"/> |
michael@0 | 37 | </center> |
michael@0 | 38 | |
michael@0 | 39 | <p> |
michael@0 | 40 | The implementation is structured into three areas, as illustrated |
michael@0 | 41 | by the diagram above. |
michael@0 | 42 | Facing the application is the <i>Manager</i> (green), which internally |
michael@0 | 43 | maintains a <i>Pool</i> (yellow) of connections and waiting threads. |
michael@0 | 44 | Both Manager and Pool rely on <i>Operations</i> (cyan) to provide the |
michael@0 | 45 | actual connections. |
michael@0 | 46 | </p> |
michael@0 | 47 | <p> |
michael@0 | 48 | In order to allow connection garbage collection, it is |
michael@0 | 49 | imperative that hard object references between the areas are |
michael@0 | 50 | restricted to the relations indicated by arrows in the diagram: |
michael@0 | 51 | </p> |
michael@0 | 52 | <ul> |
michael@0 | 53 | <li>Applications reference only the Manager objects.</li> |
michael@0 | 54 | <li>Manager objects reference Pool objects, but not vice versa.</li> |
michael@0 | 55 | <li>Operations objects do not reference either Manager or Pool objects.</li> |
michael@0 | 56 | </ul> |
michael@0 | 57 | |
michael@0 | 58 | <p> |
michael@0 | 59 | The following table shows a selection of classes and interfaces, |
michael@0 | 60 | and their assignment to the three areas. |
michael@0 | 61 | </p> |
michael@0 | 62 | <center> |
michael@0 | 63 | <table border="1"> |
michael@0 | 64 | <colgroup> |
michael@0 | 65 | <col width="50%"/> |
michael@0 | 66 | <col width="50%"/> |
michael@0 | 67 | </colgroup> |
michael@0 | 68 | |
michael@0 | 69 | <tr> |
michael@0 | 70 | <td style="text-align: center; background-color: #00ff00;"> |
michael@0 | 71 | {@link org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager} |
michael@0 | 72 | </td> |
michael@0 | 73 | <td style="text-align: center; background-color: #ffff00;"> |
michael@0 | 74 | {@link org.apache.http.impl.conn.tsccm.AbstractConnPool} |
michael@0 | 75 | </td> |
michael@0 | 76 | </tr> |
michael@0 | 77 | |
michael@0 | 78 | <tr> |
michael@0 | 79 | <td style="text-align: center; background-color: #00ff00;"> |
michael@0 | 80 | {@link org.apache.http.impl.conn.tsccm.BasicPooledConnAdapter} |
michael@0 | 81 | </td> |
michael@0 | 82 | <td style="text-align: center; background-color: #ffff00;"> |
michael@0 | 83 | {@link org.apache.http.impl.conn.tsccm.ConnPoolByRoute} |
michael@0 | 84 | </td> |
michael@0 | 85 | </tr> |
michael@0 | 86 | |
michael@0 | 87 | <!-- appears on both sides! --> |
michael@0 | 88 | |
michael@0 | 89 | <tr> |
michael@0 | 90 | <td style="text-align: right; background-color: #00ff00;"> |
michael@0 | 91 | {@link org.apache.http.impl.conn.tsccm.BasicPoolEntry} |
michael@0 | 92 | </td> |
michael@0 | 93 | <td style="text-align: left; background-color: #ffff00;"> |
michael@0 | 94 | {@link org.apache.http.impl.conn.tsccm.BasicPoolEntry} |
michael@0 | 95 | </td> |
michael@0 | 96 | </tr> |
michael@0 | 97 | |
michael@0 | 98 | <!-- ====================== --> |
michael@0 | 99 | |
michael@0 | 100 | <tr style="border-width: 5px;"> |
michael@0 | 101 | </tr> |
michael@0 | 102 | |
michael@0 | 103 | <tr> |
michael@0 | 104 | <td colspan="2" style="text-align: center; background-color: #00ffff;"> |
michael@0 | 105 | {@link org.apache.http.conn.ClientConnectionOperator} |
michael@0 | 106 | </td> |
michael@0 | 107 | </tr> |
michael@0 | 108 | |
michael@0 | 109 | <tr> |
michael@0 | 110 | <td colspan="2" style="text-align: center; background-color: #00ffff;"> |
michael@0 | 111 | {@link org.apache.http.conn.OperatedClientConnection} |
michael@0 | 112 | </td> |
michael@0 | 113 | </tr> |
michael@0 | 114 | |
michael@0 | 115 | </table> |
michael@0 | 116 | </center> |
michael@0 | 117 | |
michael@0 | 118 | <p> |
michael@0 | 119 | The Manager area has implementations for the connection management |
michael@0 | 120 | interfaces {@link org.apache.http.conn.ClientConnectionManager} |
michael@0 | 121 | and {@link org.apache.http.conn.ManagedClientConnection}. |
michael@0 | 122 | The latter is an adapter from managed to operated connections, based on a |
michael@0 | 123 | {@link org.apache.http.impl.conn.tsccm.BasicPoolEntry}. |
michael@0 | 124 | <br/> |
michael@0 | 125 | The Pool area shows an abstract pool class |
michael@0 | 126 | {@link org.apache.http.impl.conn.tsccm.AbstractConnPool} |
michael@0 | 127 | and a concrete implementation |
michael@0 | 128 | {@link org.apache.http.impl.conn.tsccm.ConnPoolByRoute} |
michael@0 | 129 | which uses the same basic algorithm as the |
michael@0 | 130 | <code>MultiThreadedHttpConnectionManager</code> |
michael@0 | 131 | in HttpClient 3.x. |
michael@0 | 132 | A pool contains instances of |
michael@0 | 133 | {@link org.apache.http.impl.conn.tsccm.BasicPoolEntry}. |
michael@0 | 134 | Most other classes in this package also belong to the Pool area. |
michael@0 | 135 | <br/> |
michael@0 | 136 | In the Operations area, you will find only the interfaces for |
michael@0 | 137 | operated connections as defined in the org.apache.http.conn package. |
michael@0 | 138 | The connection manager will work with all correct implementations |
michael@0 | 139 | of these interfaces. This package therefore does not define anything |
michael@0 | 140 | specific to the Operations area. |
michael@0 | 141 | </p> |
michael@0 | 142 | |
michael@0 | 143 | <p> |
michael@0 | 144 | As you have surely noticed, the |
michael@0 | 145 | {@link org.apache.http.impl.conn.tsccm.BasicPoolEntry} |
michael@0 | 146 | appears in both the Manager and Pool areas. |
michael@0 | 147 | This is where things get tricky for connection garbage collection. |
michael@0 | 148 | <br/> |
michael@0 | 149 | A connection pool may start a background thread to implement cleanup. |
michael@0 | 150 | In that case, the connection pool will not be garbage collected until |
michael@0 | 151 | it is shut down, since the background thread keeps a hard reference |
michael@0 | 152 | to the pool. The pool itself keeps hard references to the pooled entries, |
michael@0 | 153 | which in turn reference idle connections. Neither of these is subject |
michael@0 | 154 | to garbage collection. |
michael@0 | 155 | Only the shutdown of the pool will stop the background thread, |
michael@0 | 156 | thereby enabling garbage collection of the pool objects. |
michael@0 | 157 | <br/> |
michael@0 | 158 | A pool entry that is passed to an application by means of a connection |
michael@0 | 159 | adapter will move from the Pool area to the Manager area. When the |
michael@0 | 160 | connection is released by the application, the manager returns the |
michael@0 | 161 | entry back to the pool. With that step, the pool entry moves from |
michael@0 | 162 | the Manager area back to the Pool area. |
michael@0 | 163 | While the entry is in the Manager area, the pool MUST NOT keep a |
michael@0 | 164 | hard reference to it. |
michael@0 | 165 | </p> |
michael@0 | 166 | |
michael@0 | 167 | <p> |
michael@0 | 168 | The purpose of connection garbage collection is to detect when an |
michael@0 | 169 | application fails to return a connection. In order to achieve this, |
michael@0 | 170 | the only hard reference to the pool entry in the Manager area is |
michael@0 | 171 | in the connection wrapper. The manager will not keep a hard reference |
michael@0 | 172 | to the connection wrapper either, since that wrapper is effectively |
michael@0 | 173 | moving to the Application area. |
michael@0 | 174 | If the application drops it's reference to the connection wrapper, |
michael@0 | 175 | that wrapper will be garbage collected, and with it the pool entry. |
michael@0 | 176 | <br/> |
michael@0 | 177 | In order to detect garbage collection of pool entries handed out |
michael@0 | 178 | to the application, the pool keeps a <i>weak reference</i> to the |
michael@0 | 179 | entry. Instances of |
michael@0 | 180 | {@link org.apache.http.impl.conn.tsccm.BasicPoolEntryRef} |
michael@0 | 181 | combine the weak reference with information about the route for |
michael@0 | 182 | which the pool entry was allocated. If one of these entry references |
michael@0 | 183 | becomes stale, the pool can accommodate for the lost connection. |
michael@0 | 184 | This is triggered either by a background thread waiting for the |
michael@0 | 185 | references to be queued by the garbage collector, or by the |
michael@0 | 186 | application calling a {@link |
michael@0 | 187 | org.apache.http.conn.ClientConnectionManager#closeIdleConnections cleanup} |
michael@0 | 188 | method of the connection manager. |
michael@0 | 189 | <br/> |
michael@0 | 190 | Basically the same trick is used for detecting garbage collection |
michael@0 | 191 | of the connection manager itself. The pool keeps a weak reference |
michael@0 | 192 | to the connection manager that created it. However, this will work |
michael@0 | 193 | only if there is a background thread to detect when that reference |
michael@0 | 194 | is queued by the garbage collector. Otherwise, a finalizer of the |
michael@0 | 195 | connection manager will shut down the pool and release it's resources. |
michael@0 | 196 | </p> |
michael@0 | 197 | |
michael@0 | 198 | |
michael@0 | 199 | </body> |
michael@0 | 200 | </html> |