Caucho Technology
documentation
examples
changes

overview
quick start
installation
command-line
configuration
guide: admin
admin
amber
bam
caching
clustering
database
deployment
ejb 3.0
embedding
filters
hessian
ioc
jsf
jsp
logging
messaging
performance
quercus/php
remoting
scheduled tasks
security
server push
servlets
third-party
troubleshooting
virtual hosting
watchdog
webapp
xml and xslt

user guide: administration


Overview and introduction to Resin from an administration perspective.

Terminology

  • cluster - A set of servers configured to serve identical content. Even a solo server will belong to its own cluster.
  • default host - A virtual host configured to handle any requests not maching a specified host.
  • host - An internet domain like www.slytherin.com whose content is handled by a cluster. Also called virtual host.
  • keepalive - A HTTP connection kept open after a request finishes so the next request to the server will be more efficient.
  • load-balancer - A Resin server which forwards requests to an application cluster for increased scalability and reliability.
  • machine - A physical computer. Multiple servers can run on the same machine.
  • port - A server's internet connection handling a specific protocol, e.g. a HTTP port 80 or HTTPS port 443 or XMPP (Jabber) port 5222.
  • proxy cache - A content cache in front of a web application, storing the content and returning it quickly without running the application. Speedups for some applications can be 10x or 100x.
  • server - A Resin instance running on a single JVM. One or more servers can run on the same machine.
  • servlet - A Java program responsible for serving web content. All content is handled by a servlet, including static files, JSPs and PHP content.
  • thread - An active execution of a Java program. Because Java is multithreaded, multiple Java programs are running simultaneously. For example, each HTTP user/request is handled by its own Java thread.
  • watchdog - A Resin Java process responsible for starting and restarting Resin servers for reliability.
  • webapp - A web application is a content collection, like a Drupal or Mediawiki site. All content belongs to a webapp.

In the previous figure:

  • The servers are "web-a", "app-a" and "app-b".
  • The clusters are "web-tier" and "app-tier".
  • The virtual hosts are "foo.com" and "bar.com".
  • The webapps are "/", "/wiki" and "/drupal".
  • Both servers "app-a" and "app-b" in the cluster "app-tier" serve identical content, i.e. the same virtual hosts and webapps.
  • web-a has a proxy-cache and load balancer.
  • web-a listens to HTTP port 80.
  • app-a and app-b listen to cluster port 6800 and 6801.
  • All three servers could be on the same machine or on separate machines.

Dispatching Content

All HTTP content in Resin is ultimately handled by a servlet. If Resin can't find a servlet for a URL, it will return a 404 Not Found to the browser. So, if you see an unexpected 404 Not Found, you not only need to check that the file exists, but make sure that the servlet and its URL mapping is properly configured. If you turn on logging to "finer", you can trace the request to figure out why the servlet is not getting called.

To match up the URL to its final servlet and the content, you need all of the following properly configured:

  1. Server. The Resin server must be active to do anything. Because servers belong to a cluster, you'll automatically have a cluster even if it only has a single server.
  2. HTTP port. The server must be listening to the internet for HTTP requests just to get started. If the HTTP port is missing or misconfigured, you will get connection failure messages because the browser cannot connect to your server at all.
  3. Host. Resin must first match the <host> specified by the HTTP request, e.g. www.slytherin.com. If no hosts match, Resin will use the default host. If no default host exists, Resin will return a 404 Not Found to the browser.
  4. WebApp. Inside the host, Resin finds a web-application to handle the request by looking for the <web-app> with the longest URL prefix. So, http://www.slytherin.com/drupal/index.php might match the /drupal/. The ROOT web-app matches all URLs. If Resin can't find a web-app, it will return 404 Not Found to the browser.
  5. servlet-mapping. Inside the web-app, Resin searches for a <servlet-mapping> matching the URL. For example, test.php would match the QuercusServlet and test.jsp would match the JSP servlet. If none match, Resin will try the default mapping, which is normally the FileServlet to handle static pages. If the default servlet isn't configured, Resin will return a 404 Not Found to the browser.
  6. Servlet. Finally, the selected servlet processes the request and returns the content. The servlet itself might not find the requested content, e.g. if /foo.php does not exist in the expected location. The servlet itself is responsible for error handling, but most servlets will return a 404 Not Found if any expected files are missing.

Based on Resin's dispatching flow, here's a minimal resin.xml to serve some content out of /var/www/htdocs. Resin's philosophy of configuration files is that 1) for maintainability, all configuration should be traceable to the resin.xml, i.e. no magic defaults or hidden state are allowed and 2) for security, if something is not configured, it doesn't exist. In Resin, you need to enable things explicitly, not disable hidden defaults. The slight extra verbosity is outweighed by the improved security and maintainability.

The following resin.xml specifies an Apache-style structure where all content is served from the /var/www/htdocs directory, and is useful when upgrading from an old PHP site to use Quercus for security and performance. When organizing a site from scratch, you'll typically use a more structured dynamic hosting directory structure.

Example: minimal /etc/resin/resin.xml for HTTP
<resin xmlns="http://caucho.com/ns/resin"
       xmlns:resin="http://caucho.com/ns/resin/core">
	
  <cluster id="app-tier">
    <development-mode-error-page/>

    <server id="" address="127.0.0.1" port="6800">
      <http port="8080"/>
    </server>

    <resin:import path="/etc/resin/app-default.xml"/>

    <host id="">
      <web-app id="">
        <root-directory>/var/www/htdocs</root-directory>
      </web-app>
    </host>
  </cluster>

</resin>
  • <resin> starts a Resin configuration file and declares the validation namespaces.
  • <cluster> encloses the single-server cluster containing our content.
  • <development-mode-error-page> reports configuration and runtime errors to the browser, which is very helpful during development. On a production server, you may want to remove this tag so errors don't expose information to the internet.
  • <server> configures the Resin server, including its ports. The id matches the command-line -server argument at startup. The address and port open Resin's cluster port, which is used for deployment, management, clustering, and distributed caching.
  • <http> listens for HTTP requests. Production servers will change the port to 80.
  • <resin:import> defines the standard servlet like JSP, PHP and the static file servlet. If you omit this <resin:import>, Resin will return 404 Not Found because the <servlet-mapping> and servlets would not be defined.
  • <host> defines a default virtual host. The default host will handle any host domain given by a HTTP request.
  • <web-app> defines a ROOT web-app, serving all URLs for the host. The servlets in the web-app are defined by the app-default.xml specified by the <resin:import>.
  • <root-directory> specifies the content directory, here matching a standard Apache directory.

rewrite-dispatch replaces mod_rewrite

For many applications like Drupal and Mediawiki, it's important to rewrite a user-friendly URL to an internal servlet or PHP URL. Resin's <rewrite-dispatch> replaces the capabilities of mod_rewrite for Apache.

Example: WEB-INF/resin-web.xml Drupal rewriting
<web-app xmlns="http://caucho.com/ns/resin">

  <rewrite-dispatch>
    <dispatch regexp="\.(php|gif|css|jpg|png|ico|js|htm|html)"/>
    <forward regexp="^/" target="/index.php?q="/>
  </rewrite-dispatch>

</web-app>
  • <web-app> configures the /drupal web-application.
  • <rewrite-dispatch> starts the URL rewriting configuration.
  • <dispatch> passes the URL untouched for content handling, e.g. static files or php.
  • <forward> rewrites the URL and forwards.

Resin Processes

  • command-line - the command-line process (ResinBoot) only exists long enough to send a message to the watchdog or the Resin process, like a "start", "deploy", or "stop". If necessary, the command-line process will start the watchdog.
  • watchdog - the watchdog process manages and monitors Resin server processes. If the Resin server exits, the watchdog will automatically restart Resin, providing extra reliability in case of server failure.
  • Resin server - the Resin server handles the HTTP requests and serves the content.

Because the Resin server is started as a child of the watchdog process, its own JVM arguments come from the resin.xml, not from the command-line of ResinBoot. The JVM configuration arguments are supplied as <jvm-arg> in the <server> configuration.

Files and Directories

Resin's configuration allows for great flexibility in choosing a directory structure for your site, or adapting Resin to your existing site configuration if you're upgrading from Apache/PHP for a Drupal or MediaWiki site. There are three main directory styles:

  • Resin dynamic virtual host - the most general solution, letting you easily add virtual hosts without modifying the configuration files.
  • Apache upgrade - all content is placed in a /var/www/htdocs directory.
  • Servlet war style - all content is deployed with .war files in a webapps directory. The .war file is automatically expanded and deployed from the webapps.

Dynamic Virtual Host

In the dynamic virtual host configuration, your content is placed in /var/www/hosts/foo.com/webapps/ROOT. /var/www is the standard location for HTTP documents. hosts/foo.com contains your virtual host root directory. webapps/ROOT contains the root web-app for the virtual host.

Adding a new virtual host is easy just by adding a new hosts/bar.com directory. The special directory hosts/default creates a default virtual host, which will serve pages for anything not matching a specific host. If you need to configure the host, or add <host-alias> tags, you can add them to a hosts/bar.com/host.xml file.

Deploying a web-application is also straightforward by adding a .war file to webapps/foo.war or webapps/ROOT.war. webapps/ROOT is a special web-app which handles the root URL, "/".

In a standard Unix deployment, your configuration files go in /etc/resin and typically includes the resin.xml and the app-default.xml. app-default.xml contains standard configuration like the static file servlet, JSP, PHP servlets, as well as the standard mime-type mappings.

The Resin jars, JNI libraries and licenses go in /usr/lib/resin, typically owned by root. The resin directory itself will normally be a symbolic link to the Resin version, so you can upgrade easily.

Example: Unix dynamic virtual host
/etc/resin/
  resin.xml                 - main Resin configuration file
  app-default.xml           - default servlet configuration
  admin-users.xml           - /resin-admin users

/etc/init.d/resin           - startup script

/usr/lib/resin/             - ${resin.home}
   lib/*.jar                - Resin's Java classes
   libexec/*.so             - native JNI libraries
   libexec64/*.so           - JNI for 64-bit systems
   licenses/*               - Resin Pro licenses
   win32/*.dll              - Win32 JNI
   win64/*.dll              - Win64 JNI
   
/var/www/                   - ${resin.root}
   admin/                   - Resin database and cache storage
   doc/admin/               - /resin-admin source
   ivy2/                    - ivy2 jar repository
   lib/                     - Shared application jars
   log/                     - watchdog and Resin debug logging
   hosts/foo.com/           - dynamic host contents
     log/                   - access logging per virtual host
     host.xml               - optional host-specific configuration
     webapps/ROOT/          - web-app content
       index.php            - web-app content
       WEB-INF/             - web-app classes and configuration
         web.xml            - servlet-standard configuration
	 resin-web.xml      - Resin-specific configuration
	 lib/*.jar          - application jars
	 classes/**/*.class - application classes
	 work/              - work directory for JSP, PHP, etc.
Example: /etc/resin/resin.xml
<resin xmlns="http://caucho.com/ns/resin"
       xmlns:resin="http://caucho.com/ns/resin/core">
  <root-directory>/var/www</root-directory>
  
  <cluster id="">
    <server id="" address="127.0.0.1" port="6800">
      <http port="8080"/>
    </server>

    <resin:import path="/etc/resin/app-default.xml"/>

    <host-default>
      <resin:import path="host.xml" optional="true"/>
    
      <web-app-deploy path="webapps"/>
    </host-default>

    <host-deploy path="hosts"/>
  </cluster>
</resin>

Apache Upgrade

In an Apache upgrade, you have an existing site that you're upgrading to use Quercus or just evaluating the performance improvement for an existing side. The content is placed in /var/www/htdocs directory, and there's only a single virtual host and single root web-app.

For Apache-style sites with multiple virtual hosts, you can add new <host> tags for each host, and add a <root-directory> to set the host's root.

Example: Unix Apache upgrade
/etc/resin/
  resin.xml                 - main Resin configuration file
  app-default.xml           - default servlet configuration

/etc/init.d/resin           - startup script

/usr/local/share/resin/     - ${resin.home}
   lib/*.jar                - Resin's Java classes
   ...
   
/var/www/                   - ${resin.root}
   admin/                   - Resin database and cache storage
   log/                     - watchdog and Resin debug logging
   logs/                    - HTTP access logging
   htdocs/
     index.php              - web-app content
     WEB-INF/               - web-app classes and configuration
       resin-web.xml        - Resin-specific configuration
       lib/*.jar            - application jars
       classes/**/*.class   - application classes
       work/                - work directory for JSP, PHP, etc.
Example: /etc/resin/resin.xml
<resin xmlns="http://caucho.com/ns/resin"
       xmlns:resin="http://caucho.com/ns/resin/core">
  <root-directory>/var/www</root-directory>
  
  <cluster id="">
    <server id="" address="127.0.0.1" port="6800">
      <http port="8080"/>
    </server>

    <resin:import path="/etc/resin/app-default.xml"/>

    <host id="">
    
      <web-app id="" root-directory="htdocs"/>
      
    </host>
  </cluster>
</resin>

Java App-Server directory structure

A common Java app-server deployment structure looks like a mixture of the full dynamic host configuration and the Apache-style static configuration. The virtual hosts are configured statically like Apache, but webapps are created dynamically by dropping .war files in a webapps directory.

Example: Java app-server structure
/etc/resin/
  resin.xml                 - main Resin configuration file
  app-default.xml           - default servlet configuration

/etc/init.d/resin           - startup script

/usr/local/share/resin/     - ${resin.home}
   lib/*.jar                - Resin's Java classes
   ...
   
/var/www/                   - ${resin.root}
   admin/                   - Resin database and cache storage
   log/                     - watchdog and Resin debug logging
   logs/                    - HTTP access logging
   webapps/
     ROOT/                  - web-app for "/"
       index.php            - web-app content
       WEB-INF/             - web-app classes and configuration
         resin-web.xml      - Resin-specific configuration
         lib/*.jar          - application jars
         classes/**/*.class - application classes
         work/              - work directory for JSP, PHP, etc.
     wiki/                  - web-app for "/wiki"
       ...
     drupal/                - web-app for "/wiki"
       index.php
Example: /etc/resin/resin.xml
<resin xmlns="http://caucho.com/ns/resin"
       xmlns:resin="http://caucho.com/ns/resin/core">
  <root-directory>/var/www</root-directory>
  
  <cluster id="">
    <server id="" address="127.0.0.1" port="6800">
      <http port="8080"/>
    </server>

    <resin:import path="/etc/resin/app-default.xml"/>

    <host id="">
    
      <web-app-deploy path="webapps"/>
      
    </host>
  </cluster>
</resin>

Threads, Memory and Sockets

A Resin server needs to have enough memory, threads, and sockets to handle the user load. For the most part, the defaults provide a good starting point, but it's a good idea to become familiar with the primary resources.

  • memory - divided into heap, thread stack, PermGen space, and some specialized JVM/JNI space. With a 32-bit machine, you are likely to run into virtual memory limits. Even with a 64-bit machine, you need enough swap to handle your virtual memory size.
  • sockets - a TCP connection to the browser. Each user uses one or sockets as long as the browser is connected. Sockets use up file descriptors on Unix, which are also used by database connections, and open files. The netstat command is important for threading.
  • threads - an program execution, taking up CPU and virtual memory (for the thread stack). Active requests use CPU, while even blocked threads take up memory.

Memory

Memory is the most important configuration item for the machine. You need enough virtual memory to handle heap, stack, and permanent memory, and enough physical memory to avoid swapping. If the JVM runs out of memory, it may throw OutOfMemoryError and force a restart of the server.

  • heap - Java memory used for all application objects. Heap memory is garbage collected periodically, causing the JVM to stop or slow while finding unused memory. The maximum heap is set by the -Xmx512m command-line argument in <jvm-arg>.
  • PermGen (permanent generation) is JVM memory for permanent data like Java class code, JNI code, shared libraries, mmapped memory (jars), and the JVM itself. Configured by -XX:PermGen=128M. The JVM default usually needs to be increased.
  • thread stack - Each thread takes up virtual memory for its execution stack. Since the default is 1M and having 1000 threads is fairly common, you can use 1G of virtual memory just for the thread stack. The thread stack is configured by -Xss1m
  • virtual memory is total memory allocated to the JVM by the operating system. VM = heap + stack + PermGen. For a 32-bit system, you might have as little as 2G for all the heap, stack, and PermGen. You also need to have enough swap memory to handle your virtual memory, especially if you have a large heap, lots of threads, or even lots of large jars.

Notifications

Resin can notify you by email when it detects something wrong with the server. The main mechanism is adding a new logging handler sending mail for warning and severe messages. When a log entry is added at the WARNING or SEVERE level, Resin will send a mail containing the log information. You can then look at the administration console to debug any problems.

The configuration is described in the logging configuration section.

Example: resin.xml with mail logging
<resin xmlns="http://caucho.com/ns/resin">

  <log-handler name="" level="warning" uri="mail:">
    <init>
      <to>admin@foo.com</to>
      <properties>
        mail.smtp.host=127.0.0.1
        mail.smtp.port=25
      </properties>
    </init>
  </log-handler>
  
</resin>

Copyright © 1998-2008 Caucho Technology, Inc. All rights reserved.
Resin ® is a registered trademark, and Quercustm, Ambertm, and Hessiantm are trademarks of Caucho Technology.