|
Search Solutions & Best Practices
Browse Solutions & Best Practices
|
Summary: Implementing a dynamic scalable web application with GigaSpaces XAP.
Author: Shay Hassidim, Deputy CTO, GigaSpaces
OverviewThe Administration and Monitoring API allows you to monitor the application health and its resources to enforce a specific pre-defined configurable SLA that will scale the application while it is running. This ensures deterministic response time when there is increasing amount of users accessing the system and the high-availability and robustness of the application. The activities to scale up the application (add more instances) could be starting a new GSC on remote machines and starting additional web application instances. In the same manner the scaling agent can scale down the application to terminate running GSCs and reduce the amount of web the application instances.
How the Scaling Agent works?The scaling agent sample periodically the amount of HTTP requests served by the running web application instances and compares the total amount of recent requests with the current ones (getAverageRequests). If the average amount of requests is larger than the maximum amount of Requests Per Instance threshold (which has been pre-defined as part of the processing unit configuration) the scaling agent scales up the application by starting a new GSC and increasing the amount of instances (see the scaleUp() method).
The Scaling Agent Implementationpackage com.gigaspaces.examples.webscale; import org.openspaces.admin.Admin; import org.openspaces.admin.AdminFactory; import org.openspaces.admin.gsa.GridServiceContainerOptions; import org.openspaces.admin.pu.ProcessingUnit; import org.openspaces.admin.pu.ProcessingUnitInstance; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class WebMonitor implements InitializingBean, DisposableBean, Runnable { private String processingUnitName; private long maxRequestPerInstance; private ScheduledExecutorService executorService; private ProcessingUnit pu; private Admin admin; private long scaleTimestamp = System.currentTimeMillis(); public void setProcessingUnitName(String processingUnitName) { this.processingUnitName = processingUnitName; } public void setMaxRequestPerInstance(long maxRequestPerInstance) { this.maxRequestPerInstance = maxRequestPerInstance; } public void afterPropertiesSet() throws Exception { admin = new AdminFactory().createAdmin(); admin.getLookupServices().waitFor(1,10, TimeUnit.SECONDS); System.out.println(admin.getLookupServices().getLookupServices().length); pu = admin.getProcessingUnits().waitFor(processingUnitName, 30000L, TimeUnit.SECONDS); System.out.println("PU is " + pu); if (pu != null) { executorService = Executors.newScheduledThreadPool(1); executorService.scheduleWithFixedDelay(this, 1, 1, TimeUnit.SECONDS); } } public void run() { long averageRequests = getAverageRequests(); if (averageRequests > maxRequestPerInstance) { scaleUp(); } // if there is nothing going on since it scale up/down for a minute - scale down if (System.currentTimeMillis() - scaleTimestamp > 60000) { if (averageRequests==0) { scaleDown(); scaleTimestamp = System.currentTimeMillis(); } } } private void scaleUp() { System.out.println("Scaling up..."); pu.incrementInstance(); try { Thread.sleep(10000L); scaleTimestamp = System.currentTimeMillis(); } catch (InterruptedException e) {} } private void scaleDown() { if (pu.getInstances().length == 1) return; System.out.println("Scaling down..."); pu.decrementInstance(); try { Thread.sleep(10000L); } catch (InterruptedException e) {} } public void destroy() throws Exception { executorService.shutdownNow(); admin.close(); } public long getAverageRequests() { long totalRequests = 0; long previousTotalRequests = 0; for (ProcessingUnitInstance instance : pu) { instance.getStatistics().getPrevious(); } for (ProcessingUnitInstance instance : pu) { if (instance.getStatistics().getPrevious() == null) { return 0; } totalRequests += instance.getStatistics().getWebRequests().getTotal(); previousTotalRequests += instance.getStatistics().getPrevious().getWebRequests().getTotal(); } long averageRequests = ((totalRequests - previousTotalRequests)/ pu.getTotalNumberOfInstances()); System.out.println("Average [" + averageRequests + "], Total [" + totalRequests + "] Previous Total [" + previousTotalRequests + "]"); return averageRequests; } } The Scaling Agent PU Configuration<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:lang="http://www.springframework.org/schema/lang" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd"> <bean id="scalingAgent" class="com.gigaspaces.examples.webscale.WebMonitor"> <property name="processingUnitName" value="myWebApplication"/> <property name="maxRequestPerInstance" value="300"/> </bean> </beans> |
Additional resources: XAP Application Server | XAP Data Grid | XAP for Cloud Computing | XAP J2EE Support


