1 7 package org.jboss.web.loadbalancer.scheduler; 8 9 import java.net.MalformedURLException ; 10 import java.net.URL ; 11 import java.util.ArrayList ; 12 import java.util.Iterator ; 13 import javax.management.MBeanServer ; 14 import javax.management.Notification ; 15 import javax.management.NotificationFilter ; 16 import javax.management.NotificationListener ; 17 import javax.management.ObjectName ; 18 import javax.servlet.http.Cookie ; 19 20 import org.jboss.mx.util.MBeanServerLocator; 21 import org.jboss.util.xml.XmlHelper; 22 import org.jboss.web.loadbalancer.util.Constants; 23 import org.jboss.web.loadbalancer.util.Request; 24 import org.w3c.dom.Element ; 25 import org.jboss.system.*; 26 27 36 public abstract class AbstractScheduler 37 extends ServiceMBeanSupport 38 implements AbstractSchedulerMBean, NotificationListener 39 { 40 protected ArrayList hostsUp = new ArrayList (); 41 protected ArrayList hostsDown = new ArrayList (); 42 protected String stickyCookieName; 43 protected boolean useStickySession = false; 44 protected Element config; 45 46 50 protected abstract Host getNextHost(); 51 52 protected void stopService() throws java.lang.Exception 53 { 54 deregisterHostMBeans(); 56 } 57 58 62 public void setConfig(Element config) 63 { 64 this.config = config; 65 } 66 67 protected void createService() throws java.lang.Exception 68 { 69 addHostsFromConfig(config); 71 72 if (XmlHelper.getUniqueChildContent(config, "sticky-session"). 74 equalsIgnoreCase("true")) 75 { 76 useStickySession = true; 77 stickyCookieName = XmlHelper.getUniqueChildContent(config, 78 "sticky-session-cookie-name"); 79 } 80 81 if (log.isDebugEnabled()) 82 { 83 if (useStickySession) 84 { 85 log.debug("Using sticky sessions with Cookie name=" + stickyCookieName); 86 } 87 else 88 { 89 log.debug("Using NO sticky sessions"); 90 } 91 } 92 } 93 94 protected synchronized void addHostsFromConfig(Element config) throws 95 Exception 96 { 97 Iterator hostIterator = XmlHelper.getChildrenByTagName(XmlHelper. 98 getUniqueChild(config, "hosts"), "host"); 99 100 while (hostIterator.hasNext()) 101 { 102 Element hostElement = (Element ) hostIterator.next(); 103 String hostUrl = XmlHelper.getUniqueChildContent(hostElement, "host-url"); 104 105 if (!hostUrl.endsWith("/")) 107 { 108 hostUrl += "/"; 109 } 110 111 Host host = addHost(hostUrl); 112 113 try 114 { 115 host.setLbFactor(Integer.parseInt(XmlHelper.getUniqueChildContent( 116 hostElement, "lb-factor"))); 117 } 118 catch (Exception e) 119 { 120 log.debug("Could read LbFactor for Host " + host.getUrl() + 121 " - assuming LbFactor 1"); 122 host.setLbFactor(1); 123 } 124 } 125 } 126 127 protected ObjectName genObjectNameForHost(Host host) throws Exception 128 { 129 return new ObjectName ("jboss.web.loadbalancer: type=Node, protocol=" + 130 host.getUrl().getProtocol() + ", host=" + 131 host.getUrl().getHost() + ", port=" + 132 (host.getUrl().getPort() == -1 ? 133 host.getUrl().getDefaultPort() : 134 host.getUrl().getPort())); 135 } 136 137 protected void registerHostMBean(Host host) 138 { 139 MBeanServer mbs = MBeanServerLocator.locateJBoss(); 140 try 141 { 142 mbs.registerMBean(host, genObjectNameForHost(host)); 143 host.addNotificationListener(this, 144 new NotificationFilter () 145 { 146 public boolean isNotificationEnabled(Notification notification) 147 { 148 return (notification instanceof HostStateChangedNotification); 149 } 150 } 151 152 , host); 153 } 154 catch (Exception ex) 155 { 156 log.error("Could not register HostMBean", ex); 157 } 158 } 159 160 protected void deregisterHostMBean(Host host) 161 { 162 MBeanServer mbs = MBeanServerLocator.locateJBoss(); 163 try 164 { 165 mbs.unregisterMBean(genObjectNameForHost(host)); 166 host.removeNotificationListener(this); 167 } 168 catch (Exception ex) 169 { 170 log.error("Could not unregister HostMBean", ex); 171 } 172 } 173 174 protected synchronized void deregisterHostMBeans() throws Exception 175 { 176 Iterator hostIterator = hostsUp.iterator(); 177 178 while (hostIterator.hasNext()) 179 { 180 Host host = (Host) hostIterator.next(); 181 deregisterHostMBean(host); 182 } 183 184 hostIterator = hostsDown.iterator(); 185 while (hostIterator.hasNext()) 186 { 187 Host host = (Host) hostIterator.next(); 188 deregisterHostMBean(host); 189 } 190 } 191 192 public void getHost(Request schedRequest) throws 193 NoHostAvailableException 194 { 195 Host host = null; 196 197 host = findStickyHost(schedRequest); 199 200 while (host == null) 202 { 203 if (hostsUp.size() == 0) 204 { 205 throw new NoHostAvailableException("No host to schedule request"); 206 } 207 host = getNextHost(); 208 } 209 210 schedRequest.setHost(host); 211 212 if (useStickySession) 214 { 215 setStickyCookie(schedRequest); 216 } 217 } 218 219 222 protected void setStickyCookie(Request schedRequest) 223 { 224 Cookie cookie = new Cookie (stickyCookieName, 225 Integer.toString(schedRequest.getHost().hashCode())); 226 cookie.setPath("/"); 227 cookie.setMaxAge( -1); 228 schedRequest.getResponse().addCookie(cookie); 229 } 230 231 236 protected Host findStickyHost(Request schedRequest) 237 { 238 Host host = null; 239 if (useStickySession) 240 { 241 Cookie [] cookies = schedRequest.getRequest().getCookies(); 242 243 for (int i = 0; cookies != null && i < cookies.length; ++i) 244 { 245 Cookie cookie = cookies[i]; 246 247 if (cookie.getName().equals(stickyCookieName)) 248 { 249 log.debug("Sticky Cookie found!"); 250 int cookieHash = Integer.parseInt(cookie.getValue()); 251 Iterator iter = hostsUp.iterator(); 252 253 while (iter.hasNext()) 254 { 255 Host tempHost = (Host) iter.next(); 256 if (tempHost.hashCode() == cookieHash) 257 { 258 host = tempHost; 259 if (log.isDebugEnabled()) 260 { 261 log.debug("Sticky Cookie sticks client to host with URL " + 262 tempHost.toString()); 263 } 264 break; 265 } 266 } 267 break; 268 } 269 } 270 return host; 271 } 272 else 273 { 274 return null; 275 } 276 } 277 278 protected synchronized void markNodeDown(Host host) 279 { 280 int index = hostsUp.indexOf(host); 281 if (index == -1) 282 { 283 return; 284 } 285 hostsUp.remove(index); 286 hostsDown.add(host); 287 288 } 290 291 protected synchronized void markNodeUp(Host host) 292 { 293 int index = hostsDown.indexOf(host); 294 if (index == -1) 295 { 296 return; 297 } 298 hostsDown.remove(index); 299 hostsUp.add(host); 300 301 } 303 304 309 public ArrayList getHostsDown() 310 { 311 return hostsDown; 312 } 313 314 318 public ArrayList getHostsUp() 319 { 320 return hostsUp; 321 } 322 323 327 public synchronized Host addHost(String hostString) throws 328 MalformedURLException 329 { 330 if (hostString == null) 331 { 332 return null; 333 } 334 if (!hostString.endsWith("/")) 335 { 336 hostString += "/"; 337 } 338 Host host = new Host(new URL (hostString)); 339 340 if (hostsUp.indexOf(host) > -1 || hostsDown.indexOf(host) > -1) 342 { 343 log.info("Host " + hostString + " already there. Ignored"); 344 return null; 345 } 346 347 hostsUp.add(host); 348 registerHostMBean(host); 349 350 return host; 351 } 352 353 357 public synchronized void removeHost(URL url) 358 { 359 if (url == null) 360 { 361 return; 362 } 363 Host host = new Host(url); 364 365 int index = hostsUp.indexOf(host); 366 if (index > -1) 367 { 368 deregisterHostMBean( (Host) hostsUp.get(index)); 369 hostsUp.remove(index); 370 } 371 372 index = hostsDown.indexOf(host); 373 if (index > -1) 374 { 375 deregisterHostMBean( (Host) hostsDown.get(index)); 376 hostsDown.remove(index); 377 } 378 } 379 380 public void handleNotification(Notification notification, Object handback) 381 { 382 HostStateChangedNotification hscn=(HostStateChangedNotification)notification; 383 384 Host host=(Host)hscn.getSource(); 385 386 switch (host.getState()) 387 { 388 case Constants.STATE_NODE_UP: 389 markNodeUp(host); 390 break; 391 case Constants.STATE_NODE_DOWN: 392 case Constants.STATE_NODE_FORCED_DOWN: 393 markNodeDown(host); 394 break; 395 } 396 } 397 } 398 | Popular Tags |