Apache Native Client

If you do any development or even production testing with Apache Tomcat, you may have seen the following message in your logs.

“The Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path”

Here’s a quick solution that will leave you with greatly improved performance.

  1. Go to the following URI’s:
  2. Download the appropriate version of tcnative-1.dll
  3. For Windows, place that file in c:\windows\system32\ 
  4. Restart your Tomcat server
  5. You are done!

Cheers

Enabling the Apache2 – Tomcat5 mod_jk Connector

Often you want to use Apache HTTP for static content, yet use Tomcat for JSP and other Java type work.  This is a very common infrastructure for enterprise applications, particularly when using ‘pools’ of servers for performance, redundancy and security.  

In order to accomplish this, all connections need to be handled by the Apache webserver, which will delegate appropriate requests to Tomcat for it to process.

Here’s a simple setup to get you started:

  • First you need to get the connector appropriate to your installation:

    http://tomcat.apache.org/connectors-doc/

  • Next make sure the connector file is in the /conf folder of your Apache installation.

    NOTE: I prefer to use this path and leave the version name to make maintenance and backups easier.

  • Add the following line to httpd.conf

    LoadModule jk_module conf/mod_jk-1.2.26-httpd-2.2.4.so

  • Now, add the following to http.conf

    <IfModule jk_module>
    Include “c:/TOMCATPATH/conf/auto/mod_jk.conf”
    JkWorkersFile conf/workers.properties
    JkLogFile “c:/LOGSPATH/tomcat55_mod_jk.log”
    </IfModule>

  • Add the c:/APACHEPATH/conf/workers.properties file with the following (minimal) contents:

    worker.list=ajp13
    worker.ajp13.port=8009
    worker.ajp13.host=localhost
    worker.ajp13.type=ajp13

  • Finally, restart both Apache and Tomcat
  • The following file should have been created in c:/TOMCATPATH/conf/auto/mod_jk.conf

    ########## Auto generated on …some datetime… ##########

    <IfModule !mod_jk.c>
      LoadModule jk_module “C:/APACHEPATH/conf/mod_jk-1.2.26-httpd-2.2.4.so”
    </IfModule>

    JkWorkersFile “C:/TOMCATPATH/conf/jk/workers.properties”
    JkLogFile “c:/LOGSPATH/mod_jk.log”

    JkLogLevel emerg

    <VirtualHost localhost>
        ServerName localhost

        JkMount /webdav ajp13
        JkMount /webdav/* ajp13

        JkMount /servlets-examples ajp13
        JkMount /servlets-examples/* ajp13

        JkMount /jsp-examples ajp13
        JkMount /jsp-examples/* ajp13

        JkMount /balancer ajp13
        JkMount /balancer/* ajp13

        JkMount /host-manager ajp13
        JkMount /host-manager/* ajp13

        JkMount /tomcat-docs ajp13
        JkMount /tomcat-docs/* ajp13

        JkMount /manager ajp13
        JkMount /manager/* ajp13
    </VirtualHost>

If all went well, you should be able to access  your Tomcat server webapps on the regular HTTP port used by your Apache installation.

Cheers!

Improving network performance with server side HTTP Compression

I spend a lot of my time tweaking the performance of web applications, in addition to optimizing code it’s also necessary to verify that your server settings are also optimized for network performance to reduce bandwidth usage and thus client response times.

NOTE: This is a tradeoff between CPU and network performance, it works by compressing the content on the server just before it is sent over the wire…. when the client receives it, it then also spends some of it’s resources to decompress the content.

The Apache HTTP server provided mod_deflate (for 2.x) or mod_gzip (for 1.3).

Here’s a quick start as well as a few references:

In httpd.conf:

1. Uncomment the module:

LoadModule deflate_module modules/mod_deflate.so

2. Add the following (modify if required):

<IfModule deflate_module>
#AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript
AddOutputFilterByType DEFLATE text/*
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
#AddOutputFilterByType DEFLATE application/x-javascript

<Location />
# Insert filter
SetOutputFilter DEFLATE

# Netscape 4.x has some problems…
BrowserMatch ^Mozilla/4 gzip-only-text/html

# Netscape 4.06-4.08 have some more problems
BrowserMatch ^Mozilla/4\.0[678] no-gzip

# MSIE masquerades as Netscape, but it is fine
# BrowserMatch \bMSIE !no-gzip !gzip-only-text/html

# NOTE: Due to a bug in mod_setenvif up to Apache 2.0.48
# the above regex won’t work. You can use the following
# workaround to get the desired effect:
BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html

# Don’t compress images or ZIP/GZ/7Z
SetEnvIfNoCase Request_URI \
\.(?:gif|jpe?g|png|zip|7z|gz)$ no-gzip dont-vary

# Make sure proxies don’t deliver the wrong content
Header append Vary User-Agent env=!dont-vary
</Location>
</IfModule>

REFERENCES:

Cheers!

Add HTTP Headers in Apache Response

This can be used to for several reasons:

  1. To add headers to modify the behavior of a specific ‘misbehaving’ browser or client.
  2. To replace headers that you don’t want leaked to the Internet.
  3. To add monitoring information to your server responses.

Changes can be accomplished in the Apache2 ‘httpd.conf’ file.

  1. Verify that the module is not disabled or commented out:

    LoadModule headers_module modules/mod_headers.so

  2. To add some common metrics:

    <IfModule headers_module>
    Header append MyHeader “%D %t”
    </IfModule>

  3. To Hide the HTTP Server header that you send in your responses (often done for security through obscurity):
    <IfModule headers_module>
    Header unset Server
    </IfModule>
  4. You could also replace the Server Header like this:

    <IfModule headers_module>
    Header set Server “ScottServer 1.0”
    </IfModule>

Cheers!
REFERENCES:

Configuring Apache webserver for browser caching of web content…

This is a HUGE topic, I’ve outlined some simple steps below as well as my initial configuration for you to start with…

NOTE: this is for simple ‘static’ content such as images, additional work is required for dynamic (program generated) content, such as that generated in PHP.

1. In ‘httpd.conf’ make sure the following line is uncommented.

LoadModule expires_module modules/mod_expires.so

2.  In ‘httpd.conf’ add the following:

ExpiresActive On
### Expire images 1 day from when they’re accessed
ExpiresByType application/java-archive “access plus 1 day”
ExpiresByType image/gif “access plus 1 day”
ExpiresByType image/png “access plus 1 day”
ExpiresByType image/jpg “access plus 1 day”
ExpiresByType image/jpeg “access plus 1 day”
ExpiresByType image/x-icon “access plus 1 day”
ExpiresByType text/css “access plus 1 day”
ExpiresByType text/javascript “access plus 1 day”
ExpiresByType text/xml “access plus 1 day”
ExpiresByType application/xml “access plus 1 day”
ExpiresByType text/plain “access plus 1 month”
 

3. (Optional) Set default expiry of content in ‘httpd.conf’:

### Expire everything else 1 day from when it’s last modified
ExpiresDefault “modified plus 1 day”

NOTE: These we’re my original settings, you may want to add attitional MIME type and expiry configurations particular to your web content.

REFERENCES:

Open Source Operating Systems

I’ve posted a lot of information about the common ‘free’ open-source software that I routinely use, however… I just realized that I missed one of the most important applications you use, the Operating System itself.

While my “day job” relegates me to use Windows products for much of my work, I do a lot of additional work at home and for friends.

Currently I use and highly recommend Ubuntu Linux for most users, it’s got most of the usability features of Microsofr Windows and Apple OS/X, but without all of the additional baggage. It’s updated regularly, with new releases every 6 months and software patches made available almost daily. Updates are as non-intrusive as the Windows Update process, and only a very few ever require a reboot.

To quiet the other Linux users out there, I’ve used a lot of Linux ‘flavors’ in the past… each has had it’s place and may do so again…. this is my opinion for the moment and will likely change again in a few years. 🙂

Here’s the list:

Cheers!


Javascript ‘Response Time’ measurement (latency)

Here’s another ‘fun’ trick. When you build complex web applications, performance metrics start to become an issue. Unfortunately, web tools for this are not typically available within the browser itself and ‘testers’ often rely of such non-technical solutions as stop-watch timing. Not only is this time consuming, but it is nearly impossible to reproduce as the ‘time’ includes the hand-eye coordination of the person using the watch.

In defense of the software itself, there are several Mozilla add-ons to help with this issue, but my solution is in your application code and as such can be enhanced to provide notification or logging with some additional work.

If you’ve ever used a 3270 Emulator (Mainframe “Green Screen”) you’re probably familiar with seeing this data as most 3270 clients expose it somewhere on the screen.

The trouble here is that there is no good API to do this, and no javascript variables are persisted across page loads. (cookies would be overkill). What we’re left with is the browser window-name itself, while it’s normally used when naming ‘popup’ windows and is not visible directly to the user, it provides a ‘safe’ place to store this transient data between pages.
When leaving a page we store the current time, to be sure that we can find the correct data in the window name we use unique prefix and suffix values and add the current name so that it can be restored later.

When the new page is loaded we have to compare the current time with the stored time, then we have to be sure to restore the window ‘name’ as can’t be sure about what other reason it may be named, and we don’t want to interfere.

NOTE: If you also have access to the server code (PHP or Servlet for example) or can wrap calls to external systems like databases, you can make this much more granular by including those times. In that case you could report total time, extract database time, then extract servlet time, then ‘deduce’ network latency itself! This goes a long way when troubleshooting vague user experiences when they indicate that the “site is slow” as you can now pinpoint the problem area(s) to focus on.

WARNING: For Mozilla/Firefox the default security settings prevent JavaScript from modifying the ‘window status’ used in the example code. In a real implementation you might consider using DHTML to insert the output somewhere else. Otherwise changing Mozilla Firefox 2.x’s settings is found at Tools, Options, Content Tab, Advanced JavaScript settings.

<html>
<head>
<script>
var build=’GiantGeek Example’; // you could put build label information here 🙂
var PRE=”MMSpre”;
var SUF=”MMSsuf”;

function xload(){
var tim=grvGetDuration();
build=build + tim;
grvWindowStatus(build);
}
function xclose(){
grvWindowStatus(”);
}
function xlinkObj(obj,url){ // this is for all valid links
grvSetTimeclean();
window.location.replace(uniqueUrl(url)); // ‘replace’ has side-effect of ‘restricting’ back-button, or ‘location’
return false;
}
function grvMillis(){
return new Date().getTime();
}
function grvSetTimeclean(){
var dummy=grvGetTimeclean(); // get any remainder (dupes?)
var x=grvGetName() + grvMms();
grvSetName(x);
}
function grvMms(){
return PRE + grvMillis() + SUF;
}
function grvGetDuration(){
var rc=”;
var old=grvGetTimeclean();
if(old!=”){
rc=” [” + (grvMillis() – old)/1000 + “]”;
}
return rc;
}
function grvGetTimeclean(){
var x=grvGetName();
var pre = x.indexOf(PRE);
var suf = x.indexOf(SUF);
var rc=”;
if((pre >= 0) && (suf > pre)){
rc=x.substring(pre+PRE.length,suf);
// get the garbage in the name (around mms)
var p=x.substring(0,pre);
//var s = x.substr(suf+SUF.length);
//assemble new name (without mms)!
grvSetName(p);
}
if(pre==0){
grvSetName(”);
}
return rc;
}
function grvGetName(){
var rc = window.name;
if(rc==undefined){rc=”};
return rc;
}
function grvSetName(x){
window.name=x;
}
function grvWindowStatus(txt){
window.defaultStatus=txt;
}
function uniqueUrl(x){ // this adds a timestamp to URLs
var mms = grvMillis();
var delim = “?”;
if(x.indexOf(“?”) >=0) { delim = “&”; }
return x + delim + ‘time=’ + mms;
}
</script>
</head>
<body onunload=”xclose();” onload=”xload();”>
</body>
</html>

Private Caching/Relay DNS Server

Since I’ve run a few small websites (like this one) out of my home for years, I’ve found it useful to run a DNS server inside of my firewall. Not only does this make it easier to maintain the websites, but it allows me to lock down security and increase performance of many of my applications.

I run a the following services that use DNS:

  • Apache JAMES – mail server that does lookups to send email and filter inbound SPAM.
  • Analog – web server log analysis.
  • Apache HTTPD – web server, used to host websites, private domains used for internal purposes.

To make things more efficient, I currently have my DNS setup to forward all requests to OpenDNS, allowing for ‘adult’ website filters and analysis of DNS activity.

Some open-source/free DNS servers that I recommend:

Cheers!

Unreal Tournament 2004

I’m not much of a game player, but a group of guys from the office decided that it would be fun to blow off some steam by fragging each other once in a while. I’ve got a dedicated server setup, but for obvious reasons it’s password protected. If you are a regular reader of this blog and are interesting in joining us on occasion, please drop me an email or reply to this post. Even better… see me IRL.

Happy fragging!

Installing Perl CGI on Apache (for Windows)

Installing Perl on a Win32 installation of Apache is trivial. Just a few short years ago (roughly the year 2000) most commercial website still ran large amounts of Perl code. Several open-source projects like BugZilla still rely on this powerful scripting language.

Here’s a few simple steps and advice to consider when the need comes to add this feature to your installation.

  1. Download Perl for Win32 – ActiveState Perl is the standard distribution to use, and installation is a snap.URL = http://www.activestate.com/Products/ActivePerl/a) Get the MSI file version as it’s executable (the AS version is a ZIP file for manual installs)

    b) The default path it chooses is “C:\Perl”, I advise that you use “c:\usr” instead as it makes it easier to port programs to and from UNIX/LINUX.

    c) The MSI installer takes care of the PATH file settings, so you should have no other work for installation.

  2. Modify the Apache httpd.conf file to enable (uncomment or add the following lines).

    AddHandler cgi-script .cgi
    AddHandler cgi-script .pl

  3. Restart Windows to ensure that the new configuration is available to the operating system.
  4. Test your install…a) Create a new file on the server named /cgi-bin/hello.pl with the following content:

    #!/usr/bin/perl
    print “Content-type:text/html\n\n”;
    print “hello world”;

    b) Start (or restart) the Apache service.

    c) Access the file in the browser, example:

    URL = http://localhost/cgi-bin/hello.pl

    d) If everything works, you should see the words “hello world”, otherwise, if you see the source code or ‘500 Server Error’ then the config has a problem.

Happy Scripting.