1 7 package org.jboss.web.loadbalancer; 8 9 import java.io.IOException ; 10 import java.io.InputStream ; 11 import java.io.OutputStream ; 12 import java.util.Enumeration ; 13 import java.util.HashSet ; 14 import java.util.Set ; 15 import javax.management.ObjectName ; 16 import javax.servlet.ServletException ; 17 import javax.servlet.http.Cookie ; 18 19 import org.apache.commons.httpclient.Header; 20 import org.apache.commons.httpclient.HttpClient; 21 import org.apache.commons.httpclient.HttpMethod; 22 import org.apache.commons.httpclient.HttpState; 23 import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; 24 import org.apache.commons.httpclient.cookie.CookiePolicy; 25 import org.apache.commons.httpclient.methods.DeleteMethod; 26 import org.apache.commons.httpclient.methods.GetMethod; 27 import org.apache.commons.httpclient.methods.HeadMethod; 28 import org.apache.commons.httpclient.methods.OptionsMethod; 29 import org.apache.commons.httpclient.methods.PostMethod; 30 import org.apache.commons.httpclient.methods.PutMethod; 31 import org.jboss.logging.Logger; 32 import org.jboss.web.loadbalancer.scheduler.NoHostAvailableException; 33 import org.jboss.web.loadbalancer.scheduler.SchedulerMBean; 34 import org.jboss.web.loadbalancer.util.Constants; 35 import org.jboss.web.loadbalancer.util.Request; 36 37 45 public class Loadbalancer 46 implements LoadbalancerMBean 47 { 48 protected static Logger log = Logger.getLogger(Loadbalancer.class); 49 50 protected MultiThreadedHttpConnectionManager connectionManager; 52 53 protected static Set ignorableHeader = new HashSet (); 55 56 protected int connectionTimeout = 20000; 57 58 protected SchedulerMBean scheduler; 59 protected ObjectName schedulerName; 60 61 protected static final int MAX_RETRIES = 5; 62 63 static 64 { 65 ignorableHeader.add("content-length"); 70 ignorableHeader.add("server"); 71 ignorableHeader.add("transfer-encoding"); 72 ignorableHeader.add("cookie"); 73 ignorableHeader.add("set-cookie"); 74 ignorableHeader.add("host"); 75 } 76 77 protected Loadbalancer(SchedulerMBean scheduler, int timeout) throws ServletException 78 { 79 this.scheduler=scheduler; 80 this.connectionTimeout=timeout; 81 82 connectionManager = new MultiThreadedHttpConnectionManager(); 83 84 connectionManager.setMaxConnectionsPerHost(Integer.MAX_VALUE); 86 connectionManager.setMaxTotalConnections(Integer.MAX_VALUE); 87 } 88 89 97 protected void createMethod(Request schedRequest) throws NoHostAvailableException 98 { 99 String url = null; 100 HttpMethod method = null; 101 102 scheduler.getHost(schedRequest); 103 104 url = schedRequest.getHost().getUrl().toExternalForm(); 106 107 String path = url.substring(0, url.length() - 1) + schedRequest.getRequest().getRequestURI(); 108 109 switch (schedRequest.getRequestMethod()) 110 { 111 case Constants.HTTP_METHOD_GET: 112 method = new GetMethod(path); 113 break; 114 case Constants.HTTP_METHOD_POST: 115 method = new PostMethod(path); 116 break; 117 case Constants.HTTP_METHOD_DELETE: 118 method = new DeleteMethod(path); 119 break; 120 case Constants.HTTP_METHOD_HEAD: 121 method = new HeadMethod(path); 122 break; 123 case Constants.HTTP_METHOD_OPTIONS: 124 method = new OptionsMethod(path); 125 break; 126 case Constants.HTTP_METHOD_PUT: 127 method = new PutMethod(path); 128 break; 129 default: 130 throw new IllegalStateException ("Unknown Request Method " + 131 schedRequest.getRequest().getMethod()); 132 } 133 schedRequest.setMethod(method); 134 } 135 136 142 protected void addRequestData(Request schedRequest) 143 { 144 HttpMethod method=schedRequest.getMethod(); 145 146 if (schedRequest.getRequest().getQueryString() != null) 148 { 149 method.setQueryString(schedRequest.getRequest().getQueryString()); 150 } 151 152 if (method instanceof PostMethod) 154 { 155 PostMethod postMethod = (PostMethod) method; 156 157 Enumeration paramNames = schedRequest.getRequest().getParameterNames(); 158 while (paramNames.hasMoreElements()) 159 { 160 String paramName = (String ) paramNames.nextElement(); 161 postMethod.addParameter(paramName, schedRequest.getRequest().getParameter(paramName)); 162 } 163 } 164 } 165 166 173 protected void prepareServerRequest(Request schedRequest) 174 { 175 HttpMethod method=schedRequest.getMethod(); 176 177 HttpClient client = new HttpClient(connectionManager); 179 client.setStrictMode(false); 180 client.setTimeout(connectionTimeout); 181 client.setConnectionTimeout(connectionTimeout); 182 client.getState().setCookiePolicy(CookiePolicy.COMPATIBILITY); 183 184 method.setFollowRedirects(false); 186 method.setDoAuthentication(false); 187 188 Enumeration reqHeaders = schedRequest.getRequest().getHeaderNames(); 190 while (reqHeaders.hasMoreElements()) 191 { 192 String headerName = (String ) reqHeaders.nextElement(); 193 String headerValue = schedRequest.getRequest().getHeader(headerName); 194 195 if (!ignorableHeader.contains(headerName.toLowerCase())) 196 { 197 method.setRequestHeader(headerName, headerValue); 198 } 199 } 200 201 Cookie [] cookies = schedRequest.getRequest().getCookies(); 203 HttpState state = client.getState(); 204 for (int i = 0; cookies != null && i < cookies.length; ++i) 205 { 206 Cookie cookie = cookies[i]; 207 208 org.apache.commons.httpclient.Cookie reqCookie = 209 new org.apache.commons.httpclient.Cookie(); 210 211 reqCookie.setName(cookie.getName()); 212 reqCookie.setValue(cookie.getValue()); 213 214 if (cookie.getPath() != null) 216 { 217 reqCookie.setPath(cookie.getPath()); 218 } 219 else 220 { 221 reqCookie.setPath("/"); 222 } 223 224 reqCookie.setSecure(cookie.getSecure()); 225 226 reqCookie.setDomain(method.getHostConfiguration().getHost()); 227 state.addCookie(reqCookie); 228 } 229 schedRequest.setClient(client); 230 } 231 232 240 protected void handleRequest(Request schedRequest) throws ServletException , IOException 241 { 242 243 boolean reschedule = false; 244 245 try 246 { 247 prepareServerRequest(schedRequest); 249 250 int tries = 0; 251 while (tries < MAX_RETRIES) 253 { 254 try 255 { 256 long t1=System.currentTimeMillis(); 258 schedRequest.getHost().incCurrentConnections(); 259 260 schedRequest.getClient().executeMethod(schedRequest.getMethod()); 261 262 schedRequest.getHost().decCurrentConnections(); 263 264 long t2=System.currentTimeMillis(); 265 schedRequest.getHost().addRequest((int)(t2-t1)); 266 break; 267 } 268 catch (IOException ex) 269 { 270 try 271 { 272 schedRequest.getHost().decCurrentConnections(); 273 schedRequest.getMethod().recycle(); 274 } 275 catch (Exception e) 276 { 277 } 279 280 tries++; 281 log.info("Connect retry no. " + tries, ex); 282 } 283 } 284 if (tries < MAX_RETRIES) 286 { 287 parseServerResponse(schedRequest); 289 } 290 else 291 { 292 log.error("Max retries reached - giving up. Host will be marked down"); 293 294 schedRequest.getHost().markNodeDown(); 296 reschedule = true; 297 } 298 } 299 finally 300 { 301 try 302 { 303 schedRequest.getMethod().recycle(); 304 } 305 catch (Exception e) 306 { 307 } 309 } 310 if (reschedule) 312 { 313 String redirectURI = schedRequest.getRequest().getRequestURI(); 314 315 if (schedRequest.getRequest().getQueryString() != null) 316 { 317 redirectURI += "?" + schedRequest.getRequest().getQueryString(); 318 } 319 schedRequest.getResponse().sendRedirect(redirectURI); 321 } 322 } 323 324 333 protected void parseServerResponse(Request schedRequest) throws ServletException , IOException 334 { 335 schedRequest.getResponse().setStatus(schedRequest.getMethod().getStatusCode()); 336 337 org.apache.commons.httpclient.Cookie[] respCookies = 339 schedRequest.getClient().getState().getCookies(); 340 341 for (int i = 0; i < respCookies.length; ++i) 342 { 343 Cookie cookie = 344 new Cookie (respCookies[i].getName(), respCookies[i].getValue()); 345 346 if (respCookies[i].getPath() != null) 347 { 348 cookie.setPath(respCookies[i].getPath()); 349 } 350 schedRequest.getResponse().addCookie(cookie); 351 } 352 353 Header[] header = schedRequest.getMethod().getResponseHeaders(); 355 356 for (int i = 0; i < header.length; ++i) 357 { 358 if (!ignorableHeader.contains(header[i].getName().toLowerCase())) 359 { 360 schedRequest.getResponse().setHeader(header[i].getName(), header[i].getValue()); 361 } 362 } 363 364 copyServerResponse(schedRequest); 365 } 366 367 373 protected void copyServerResponse(Request schedRequest) throws IOException 374 { 375 376 InputStream bodyStream = schedRequest.getMethod().getResponseBodyAsStream(); 377 378 if (bodyStream == null) 380 { 381 log.debug("No request body"); 382 return; 383 } 384 385 byte[] buffer = new byte[2048]; 386 int numBytes; 387 OutputStream out = schedRequest.getResponse().getOutputStream(); 388 389 while ( (numBytes = bodyStream.read(buffer)) != -1) 391 { 392 out.write(buffer, 0, numBytes); 393 if (log.isDebugEnabled()) 394 { 395 log.debug("Copied " + numBytes + " bytes"); 396 } 397 } 398 } 399 400 405 public int getConnectionTimeout() 406 { 407 return this.connectionTimeout; 408 } 409 410 414 public void setConnectionTimeout(int newTimeout) 415 { 416 this.connectionTimeout = newTimeout; 417 } 418 419 423 public int getConnectionsInUse() 424 { 425 return connectionManager.getConnectionsInUse(); 426 } 427 } 428 | Popular Tags |