The Grizzly’s Application Resources Allocation (ARA) extension is an implementation of a Resource Consumption Management (RCM) system. RCM system are allowing you to enable virtualization of system resources per web application, similar to Solaris 10 zone or the outcome of the upcoming JSR 284.
ARA has been implemented on top of Grizzly’s Pipeline and Algorithm interface and a new basic rule-based filtering mechanism to manipulate tcp request URLs on the fly (browse the code here). For example, you can easily add a rule to rewrite a tcp request, like mod_rewrite does in Apache.
Grizzly’s ARA currently supports two rule that can be applied to a tcp request:
- Reserve a specific percentage of the available heap memory.
- Reserve a specific percentage of the available threads.
You can configure the rule semantic using two kind of allocation policy: reservation or ceiling.
Lets say there are 100 threads in the Grizzly request processing thread pool(Pipeline). For example, we reserve 30% of the Pipeline’s threads to App A and 65% to App B. Now that leaves only 5% to other applications. So even if the other 95% threads are idle, we delay requests until the 5 unreserved threads can service requests. If the reservations are speaking for all available resources, then we may reject the request.
Ceiling has a slightly different behavior. If there are more than 30 requests to A, even if the threads set aside for B and others are idle, we delay processing the requests to A, until A’s utilized thread percentage falls below 30%. Here we may delay requests until resources become available.
Like many Grizzly and WebContainer extension, the ARA mechanism is disabled by default, and will be considered to become an official feature when the GlassFish.next discussion starts. Since this is an experimental feature right now, we also want to get community feedback and contribution before rolling it in as a supported feature. Thus, for now, you gonna need to edit directly GlassFish’s domain.xml file.
To enable ARA, you first need to tell Grizzly to use the ARA specialized Pipeline:
Then, you need to define the rule(s) you want to be applied to the tcp request:
<jvm-options>-Dcom.sun.enterprise.web.ara.rules= com.sun.enterprise.web.ara.rules.ThreadRatioRule, com.sun.enterprise.web.ara.rules.HeapRatioRule</jvm-options>
I usually apply only one rule at the time. Note that it is fairly easy to add a new Rule to the rule-based engine. All you need to do is to implement the Rule interface, and tell the rule-based engine to load it at startup using the above property. Your rule.callable() implementation will have to implement the following contract:
- Rule_OK: the rule has been successfully applied and the request can be executed. The rule result will be cached so the next request will be serviced directly, without paying the price of the rule based engine execution.
- Rule_DELAY: the rule has been successfully applied but the request execution must be delayed.
- Rule_OK_NOCACHE: the rule has been successfully applied and the request can be executed, but the rule must not be cached so next time the request is coming, the rule will be executed.
The ARA implementation will invoke rule.attach() with an NIO ByteBuffer which position and limit will delimitate the HTTP request context root, which will be used to execute the rule. Take a look here for an example
Then you need to configure the rule semantic allocation policy:
For the ceiling allocation policy, you can define the time the request will be delayed when no resource are available by adding (the value in milliseconds):
Then finaly, define the application set on which rule(s) will be applied:
The allowed values are application name, the token ‘|’, then the allowed ratio (between 0 and 1) e.g. ([yourApp|ratio] separated by a ‘,’)
Ouf…can’t wait for the admin team to implement something easier to configure🙂. Let me know if the steps are unclear (which I suspect they are). Once all the jvm-options has been entered, launch GlassFish. Grizzly will replace its default Pipeline with the above defined ARA, and starts the rule-base engine.
Now why not implementing the same behavior using a Servlet’s Filter or a Catalina’s Valve? Because performance wise, you don’t want to parse the request and then do RCM. Doing such filtering at the bytes level, although it complexity the rule implementation, reduce the performance degradation. You certainly don’t want you server to significantly slow down when RCM is enabled.
_uacct = “UA-3111670-1”;
Wants to execute CGI in GlassFish? The GlassFish CGI support is disabled by default, and it is based on the Tomcat implementation. Two ways to enable it: only inside your web application or for all web applications deployed in GlassFish. I strongly recommend you enable it inside your application only for security reason, but if you control the applications deployed in GlassFish, then enabling it to all web applications might be simpler. For your web application, you will add the information in your WEB-INF/web.xml. To enable it globally, you will add it in $glassfish.home/domains/domain1/config/default-web.xml.
First, define the CGI Servlet:
<!-- Common Gateway Includes (CGI) processing servlet, which supports --> <!-- execution of external applications that conform to the CGI spec --> <!-- requirements. Typically, this servlet is mapped to the URL pattern --> <!-- "/cgi-bin/*", which means that any CGI applications that are --> <!-- executed must be present within the web application. This servlet --> <!-- supports the following initialization parameters (default values --> <!-- are in square brackets): --> <!-- --> <!-- cgiPathPrefix The CGI search path will start at --> <!-- webAppRootDir + File.separator + this prefix. --> <!-- [WEB-INF/cgi] --> <!-- --> <!-- debug Debugging detail level for messages logged --> <!-- by this servlet.  --> <!-- --> <!-- executable Name of the exectuable used to run the --> <!-- script. [perl] --> <!-- --> <!-- parameterEncoding Name of parameter encoding to be used with --> <!-- CGI servlet. --> <!-- [System.getProperty("file.encoding","UTF-8")] --> <!-- --> <!-- passShellEnvironment Should the shell environment variables (if --> <!-- any) be passed to the CGI script? [false] --> <!-- --> <servlet> <servlet-name>cgi</servlet-name> <servlet-class>org.apache.catalina.servlets.CGIServlet</servlet-class> <init-param> <param-name>debug</param-name> <param-value>0</param-value> </init-param> <init-param> <param-name>cgiPathPrefix</param-name> <param-value>WEB-INF/cgi</param-value> </init-param> <load-on-startup>5</load-on-startup> </servlet>
Then define the servlet mapping:
<servlet-mapping> <servlet-name>cgi</servlet-name> <url-pattern>/cgi-bin/*</url-pattern> </servlet-mapping>
If you added this info in default-web.xml, you gonna need to restart GlassFish. Then in you web application, creates a folder under
and drop you CGI under than folder, then deploy your application. You will be able to execute your CGI by doing:
_uacct = “UA-3111670-1”;