Mapping a URL between Apache and Tomcat, using mod_jk - apache

I am using Apache/2.2.14 and Apache Tomcat/6.0.29 in a Ubuntu Server 10.04.3 LTS.
This is my jk.conf:
JkWorkersFile /etc/libapache2-mod-jk/workers.properties
JkMount /portal/* worker1
JkLogLevel debug
JkMountCopy All
And this is my workers.properties:
ps=/
# Define 1 real worker named worker1
worker.list=worker1
# Set properties for worker named worker1 to use ajp13 protocol,
# and run on port 8009
worker.worker1.type=ajp13
worker.worker1.host=localhost
worker.worker1.port=8009
worker.worker1.lbfactor=1
worker.worker1.socket_keepalive=1
worker.worker1.socket_timeout=300
The problem is that whenever I try to access tomcat via apache with: http://my.host.com/portal, tomcat replies with:
13:39:30,683 INFO [PortalImpl:3829] Current URL /portal/ generates exception: null
The problem goes away if I use a different mountpoint for the worker:
JkMount /portal/* worker1
But this forces me to access my tomcat instance here: http://my.host.com, which I do not want.
Is there any way of rewriting the URL using mod-jk?

You can skip all that configuration if you just use mod_proxy instead of mod_ajp...
ProxyPass /foo http://localhost:8080/bar
ProxyPassReverse /foo http://localhost:8080/bar
This will proxy /foo to local server URL /bar running on port 8080.

Related

Two loadbalacer with apache 2.2(for jboss and apapche tomcat)

I have a apache server with loadbalancer(apache-2.2) and two tomcat nodes(clusters). To communicate with tomcat nodes I'm using mod_jk. I've defined two loadbalancer in apache(by changing httpd.conf and worker property files). Apache is running in port 80. The configuration as follows. iSencer is one of my application.
In httpd.conf
=============
Listen localhost:80
ServerName localhost
DocumentRoot "/home/xx/projects/apache/content" (I've created a seperate root directory as content)
JkMount /iSencer loadbalancer
JkMount /iSencer/ loadbalancer
JkMount /iSencer/* loadbalancer
In worker.properites
====================
worker.list=loadbalancer
#------------------------
# iSencer node 1 - tomcat
#------------------------
worker.iSencer1.type=ajp13
worker.iSencer1.host=localhost
worker.iSencer1.port=8109
#------------------------
# iSencer node 2 - tomcat
#------------------------
worker.iSencer2.type=ajp13
worker.iSencer2.host=localhost
worker.iSencer2.port=8010
# ------------------------
# Load Balancer for yard
# ------------------------
worker.loadbalancer.sticky_session=1
worker.loadbalancer.balanced_workers=iSencer1,iSencer2
worker.loadbalancer.type=lb
worker.loadbalancer.method=B
and there are some changes in tomcat server.xml.So, cluster is working properly.
Now I want to add a jboss server to same apache. But need to run in different loadbalancer. My changes as follows as in httpd.conf in apache.
JkMount /index.html loadbalancer2
JkMount /servlet/* loadbalancer2
worker property
===============
worker.list=loadbalancer, worker.list=loadbalancer2
#------------------------
# tracker node 1
#------------------------
worker.track.port=8009
worker.track.host=localhost
worker.track.type=ajp13
worker.track.lbfactor=1
worker.track.connection_pool_size=10
# ------------------------
# Load Balancer for tracker
# ------------------------
worker.loadbalancer2.sticky_session=1
worker.loadbalancer2.balanced_workers=track
worker.loadbalancer2.type=lb
worker.loadbalancer2.method=B
But after adding jboss to apache as a cluster my tomcat cluster is not working properly ? In browser it will show two JSESSIONIDs. When I remove jboss form apache configuration still not working. Browser still showing two JSESSIONIDs. After clearing cookies in browser cluster is working fine. so what is the reason not to work cluster with jboss ?

Apache web server multiple workers

We have a webserver running apache 2.2, which connects to tomcat 5.5 in another server (say, repserver). This is done through ajp1.3 protocol, with mod_jk workers.properties file defining an ajp13 worker.
The workers.properties file contains:
ps=\
worker.ajp13.type=ajp13
worker.list=ajp13
worker.ajp13.port=8009
worker.ajp13.host=#HOSTNAME
The httpd.conf file is using these three lines:
JkMount /* ajp13
JkMount /#Link1/* ajp13
JkMount /#Link2/* ajp13
Now we have another instance of tomcat 7 in the repserver, and we need the webserver to connect to this instance as well. I have defined the listening port for ajp as 9009 in this instance of tomcat.
This contains link3 and link4.
How can I define another worker to connect to these links?
You need to define a load balancer in that case:
Change your workers.properties to this:
worker.list=balancer
#lb config
worker.balancer.type=lb
worker.balancer.sticky_session=1
worker.balancer.balance_workers=ajp13,tomcat7
#(ajp13 is not a good name for a worker/server node)
worker.ajp13.type=ajp13
worker.ajp13.port=8009
worker.ajp13.host=#HOSTNAME
worker.tomcat7.type=ajp13
worker.tomcat7.port=9009
worker.tomcat7.host=#IP/HOSTNAME
Open server.xml of Tomcat 7 and define the jvmRoute (do that in Tomcat 5 too, if not still happend):
<Engine jvmRoute="tomcat7" name="Catalina" ...>
Map applications to the new Tomcat 7:
JkMount /APPLICATION_NAME balancer
JkMount /APPLICATION_NAME/* balancer

Sticky Session in apache doesn't work

This is currently my environment setup.
Apache Tomcat: Apache-Tomacat-7.0.21
Apache HTTP Server: c. Apache HTTP Server 2.2.19
Tomcat Connector JK 1.2.32 for Apache HTTP Server 2, mod_jk
I'm trying to implement sticky session but i still can't get it to work. I'm able to load balance between 2 machines in a cluster. Please advise what else i have missed out!
Following is my workers.properties file
# Define 2 real workers using ajp13 & 1 balancer
worker.list=balancer
#
worker.balancer.type=lb
worker.balancer.balance_workers=worker1,worker2
worker.balancer.sticky_session=True
# Set properties for worker1 (ajp13)
worker.worker1.type=ajp13
worker.worker1.host=localhost
worker.worker1.port=8009
worker.worker1.lbfactor=50
worker.worker1.cachesize=10
worker.worker1.cache_timeout=600
worker.worker1.socket_keepalive=1
worker.worker1.recycle_timeout=300
# Set properties for worker2 (ajp13)
worker.worker2.type=ajp13
worker.worker2.host=X.X.X.X
worker.worker2.port=8009
worker.worker2.lbfactor=50
worker.worker2.cachesize=10
worker.worker2.cache_timeout=600
worker.worker2.socket_keepalive=1
worker.worker2.recycle_timeout=300
I've also set the jvmRoute in server.xml to:
<Engine name="Catalina" defaultHost="localhost" jvmRoute="worker1">

Apache - Tomcat ProxyPass VirtualHost - Context Path

I have a problem configuring apache tomcat ProxyPass directive for two applications that have two different Context Paths in tomcat. The tomcat is running behind an apache and I use the apache to proxy path the requests to tomcat. In apache I want to access both application via a hostname instead of a context path.
Scenario:
tomcat
https://domain:8443/app1
https://domain:8443/app2
in tomcat the applications have the context path app1 and app2
in apache I want to enable both application as follow:
https://app1.host/
https://app2.host/
In apache I have created a configuration for each domain:
ProxyPass / https://localhost:8443/app1
ProxyPassReverse / https://localhost:/8443/app1
The strange thing is app1 is only available through apache using the context path:
https://app1.host/app1
Is it possible to realize such a setup with apache ProxyPass module?
Thx for your help.
You should be able to achieve the result you want by using virtual hosting. Also it's a good idea to pass the requests to tomcat via the AJP protocol instead of HTTPS. Try adding this to the Apache configuration
NameVirtualHost *:443
<VirtualHost *:443>
ServerName app1.host
ProxyPass / ajp://localhost:8009/app1/
</VirtualHost>
<VirtualHost *:443>
ServerName app2.host
ProxyPass / ajp://localhost:8009/app2/
</VirtualHost>
If you haven't changed the default server settings for Tomcat this should work just as it is. Otherwise make sure to specify the AJP port that is configured in Tomcat's conf/server.xml file. There should be a line similar to this:
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
Make sure that you have the mod_proxy and mod_proxy_ajp modules loaded in Apache configuration, this may vary depending on your Apache installation. Also remove any previously configured 'ProxyPass / ...' lines as they will interfere with the new configuration. Hope this works for you.
you can try
ProxyPass / https://localhost:8443/app1/
ProxyPassReverse / https://localhost:8443/app1/
with the final /

Removing Tomcat context from URLs for a virtual host (mod_jk, mod_rewrite)

I have a single Tomcat instance containing a number of webapps, each accessible via it's /Context. Tomcat is behind httpd (actually Debian Apache2), configured with virtual hosts to serve each app/Context. Tomcat connectivity is with mod_jk.
This works fine when I don't care about removing the context from urls: when the root of a virtual domain is requested, the requested is redirected to domain.com/Context.
However for one app I do want to remove the context. I believe this can be done by using mod_rewrite, and passing the re-written url to mod_jk for passing on to the correct Tomcat context. So my Debian Apache2 sites-available file looks like this:
NameVirtualHost *
<VirtualHost *>
ServerName domain.be
DocumentRoot /home/webapp/app/static/domain/
RewriteEngine on
RewriteRule ^/(.*)$ /Context/$1 [L,PT]
RewriteLog "/var/log/apache2/domain-rewrite.log"
RewriteLogLevel 4
JkLogFile /var/log/apache2/domain-mod_jk.log
JkLogLevel debug
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
JkMount /Context w1
JKMount /Context* w1
JkOptions +ForwardURICompat
ErrorLog /var/log/apache2/domain_error.log
CustomLog /var/log/apache2/domain_access.log combined
LogLevel warn
</VirtualHost>
According to the docs, the [PT] flag and +ForwardURICompat options should result in the rewritten URL being passed to jk_mod. However that doesn't seem to be happening.
The URL is being re-written, but it seems as if mod_jk is ignoring it: A request for domain.be/Context for example gets rewritten as /Context/Context - but is still handed to mod_jk as /Context.
Any ideas? Incidentally, I cannot use mod_proxy at the moment.
Thanks
#Josh, I think this solution won't work if tomcat performs any redirects. This is the typical case for example in an application demanding a login. When the user is not authenticated the app will redirect to something like /login however tomcat will append the current context like in /context/login so at the end the context does show in the URL.
As you mentioned in your other question/response using just mod-jk plus tomcat virtual hosts is an option but there you will need to deploy your applications as ROOT.war which might not be that straightforward. There is a workaround so your application can be just dropped into tomcat webapps folder but as I described here the server will deploy the app at least twice.
It would be great if RewriteRule[P] plus JkOptions +ForwardURICompat could work but it doesn't. BTW I have tested this and I know mod_proxy does work as I proxied my site to cnn.com and I got their page under my site URL. Below are the logs BTW for the requests where you can see a proxy is being used:
127.0.0.1 - - [15/Dec/2011:12:56:34 --0500] [localhost/sid#1008ef278][rid#1009980a8/initial] (2) forcing proxy-throughput with http://localhost/nestorurquiza-app/
127.0.0.1 - - [15/Dec/2011:12:56:34 --0500] [localhost/sid#1008ef278][rid#1009980a8/initial] (1) go-ahead with proxy request proxy:http://localhost/nestorurquiza-app/ [OK]
127.0.0.1 - - [15/Dec/2011:12:56:49 --0500] [localhost/sid#1008ef278][rid#1009aaca8/initial] (2) forcing proxy-throughput with http://localhost/nestorurquiza-app/login
127.0.0.1 - - [15/Dec/2011:12:56:49 --0500] [localhost/sid#1008ef278][rid#1009aaca8/initial] (1) go-ahead with proxy request proxy:http://localhost/nestorurquiza-app/login [OK]
127.0.0.1 - - [15/Dec/2011:12:57:15 --0500] [localhost/sid#1008ef278][rid#1009980a8/initial] (2) forcing proxy-throughput with http://localhost/nestorurquiza-app/j_spring_security_check
127.0.0.1 - - [15/Dec/2011:12:57:15 --0500] [localhost/sid#1008ef278][rid#1009980a8/initial] (1) go-ahead with proxy request proxy:http://localhost/nestorurquiza-app/j_spring_security_check [OK]
127.0.0.1 - - [15/Dec/2011:13:08:41 --0500] [localhost/sid#1008ef278][rid#1009980a8/initial] (2) forcing proxy-throughput with http://localhost/nestorurquiza-app/
127.0.0.1 - - [15/Dec/2011:13:08:41 --0500] [localhost/sid#1008ef278][rid#1009980a8/initial] (1) go-ahead with proxy request proxy:http://localhost/nestorurquiza-app/ [OK]
I've been using this with great success:
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/(Context/.*)$
RewriteRule ^/(.*)$ /Context/$1 [P,L]
Notes on your situation:
You will need to get mod_proxy working or the [P] will be ignored and the request will be forwarded instead of proxied. There is no way around this.
+ForwardURICompat is part of mod_jk and will take effect after the rewriting.
mod_jk is ignoring the request because it never gets there. You need a RewriteCond (above) to prevent requests to /Context from being rewritten.
I'm currently looking for a way to do this without mod_rewrite and using, instead, just mod_jk and Tomcat <Host>'s. But I'm having trouble with apache, mod_jk and Tomcat hosts playing nicely together. The above should work fine for you.
I'll leave my original answer up but it is wrong. The proper way to do this would be with a Tomcat VirtualHost:
http://tomcat.apache.org/tomcat-6.0-doc/virtual-hosting-howto.html
The official walk-through in the link above is exactly what I've used several times now. I won't attempt to boil it down here.
The concept is the same as an Apache Vhost. Create a virtual host (eg. for something.yourtdomain.com) and deploy your webapp to the ROOT application (/) for that vhost and you're all set. This way, if you already have a ROOT webapp, you can have another at a different domain and the prior will remain unaffected.
As Nestor mentioned, an Apache rewrite rule will not handle things like tag libs and frameworks that automatically create links/form actions/etc for you based on the context root. In this case they will create the correct context root (/).
Following hints given by Nestor Urquiza's answer, i managed to solve the issue by defining additional Host in tomcat's server.xml because as said, the j_security_check request is answered by tomcat with a forward instruction to the browser which inevitably contains the context name so that users trying to login gets 408 errors. Therefore, a real passthrough inside Apache VirtualHost JkMount /* worker1 directive is achievable by making the intended context, a ROOT one.
The Apache httpd.conf [ and/or an included *.conf ] file :
<!-- the subdomain -->
<VirtualHost *:80>
ServerName appWelcome.example.org
ServerAlias www.appWelcome.example.org
JKMount /* worker1
</VirtualHost>
<!-- with mod_jk set up -->
LoadModule jk_module modules/mod_jk.so
JWorkersFile /etc/apache2/workers.properties
JkShmFile /var/log/apache2/mod_jk.shm
So to map all request made to subdomain http://appWelcome.example.org/ directly to the in-charge /appWelcome tomcat context, the appWelcome context must be addressable with request to http://appWelcome.example.org:8080/
So the tomcat server.xml file would then wear a separate Host for the app you are wiling to expose: .
<Server ...>
<Service>
<Engine defaultHost="localhost" ...>
<Host name="appWelcome.example.org" appBase="appWelcomeBase" ... >
<Valve ... />
</Host>
<Host name="localhost" appBase="webapps" ...>
<!-- this Host is typically shipped with manager, host-manager, docs,
sample, examples and a default ROOT context that shows tomcat default home. -->
<Valve ... />
</Host>
</Engine>
</Service>
</Server>
Note that the permissions ( and selinux context if enabled ) have to be adjust to mimic the default Host ones as follows :
$CATALINA_HOME/conf/Catalina/app.example.org as $CATALINA_HOME/conf/Catalina/localhost
$CATALINA_HOME/appWelcomeBase as $CATALINA_HOME/webapps
Whence this is done all that is left to do is issue rename and move the appWelcome.war web archive for it to auto-deploy in the created appBase ( replacing $CATALINA_HOME with its value, e.g. /var/www/tomcat7) :
# mv $CATALINA_HOME/webapps/appWelcome.war $CATALINA_HOME/appWelcomeBase/ROOT.war
Voila !
Use mod_proxy_ajp instead mod_jk like below:
<VirtualHost *:80>
ServerName domain.be
DocumentRoot /home/webapp/app/static/domain/
...
ProxyPass /Context ajp://localhost:8009/Context
ProxyPass / ajp://localhost:8009/Context/
...
</VirtualHost>