Basic Apache Tomcat Features
Hello dear readers!
Apache Tomcat is open source software that implements the specifications Java Servlet, JSP And Java WebSocket thus providing a platform for running web applications written in Java. Developed and maintained by the Apache Software Foundation, Tomcat serves as a servlet container that allows web applications to use Java to create dynamic web pages.
Tomcat can run as a standalone web server, where it processes both static pages and dynamic requests via Servlets And JSP. However, Tomcat is often used in combination with traditional web servers such as Apache HTTP Server or Nginx to process static content, while dynamic content is processed through Tomcat.
In this article we will look at the main functionality of Tomcat.
Let's install
Download Apache Tomcat from the official website. Select the version suitable for the OS. After downloading, unpack the archive.
Open a terminal and go to the directory bin
inside the unpacked Tomcat directory and run startup.sh
(on Linux) or startup.bat
(on Windows). If everything is done correctly, your server will come up and you will see the Tomcat welcome page by opening localhost:8080
in your browser.
Setting up Tomcat
File server.xml
manages the entire configuration.
Let's look at the connector configuration, which is often used for HTTP/1.1:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
maxThreads="150" minSpareThreads="25"/>
maxThreads
And minSpareThreads
— parameters for optimization. Increase maxThreads
allows you to process more parallel requests, but requires more resources.
To enhance security, you can make changes to the same file server.xml
restricting access to certain functions:
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
allow="^.*[your-trusted-ip].*$" />
The setup ensures that only certain IP addresses are allowed to access your server.
Apache Tomcat uses JDBC connection pools to improve performance when working with the database. Example of setting up a connection pool in context.xml
:
<Resource name="jdbc/YourDB"
auth="Container"
type="javax.sql.DataSource"
maxTotal="100"
maxIdle="30"
maxWaitMillis="10000"
username="dbuser"
password="dbpassword"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/yourdb"/>
JMX is a standard that allows real-time monitoring and control of an application. To enable JMX in Tomcat, you will need to run it with certain JVM parameters:
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=12345
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
Tomcat uses JULI, an extension to standard Java logging, but it can be integrated with cooler logging systems such as Log4j or SLF4J:
Adding a file log4j.properties
in classpat.
We indicate log4j
as a logging factory by adding the following JVM options when starting Tomcat:
-Dorg.apache.catalina.logging.log4j.Log4jContextFactory
-Dlog4j.configurationFile=path/to/log4j.properties
Tomcat performance directly depends on JVM settings. You can optimize some parameters:
Xmx и Xms:
set the maximum and initial heap size respectively
-Xmx4G -Xms4G
XX:+UseG1GC
: Enables G1 garbage collector
XX:+UseStringDeduplication:
reduces the number of duplicate rows in the heap
Safety
Implementation of SSL/TLS for data protection
First you need a Keystore with a key and a certificate, this can be done keytool
built into the JDK:
keytool -genkey -alias tomcat -keyalg RSA -keystore /path/to/your/keystore.jks
During the Keystore creation process, keytool
will ask several identification questions. Remember your Keystore password; it will be needed later.
Open the file conf/server.xml
and find the Connector configuration. Let's modify it to enable SSL as shown below:
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS" keystoreFile="/path/to/your/keystore.jks"
keystorePass="your_keystore_password" />
We replace keystoreFile
And keystorePass
to the path to the Keystore and password, respectively.
Setting up security filters and CORS
Editing a file web.xml
applications or global conf/web.xml
in Tomcat to add a CORS filter:
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param>
<param-name>cors.allowed.origins</param-name>
<param-value>*</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.methods</param-name>
<param-value>GET,POST,PUT,DELETE,OPTIONS</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.headers</param-name>
<param-value>Content-Type,Authorization</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
This is a basic CORS setup that allows requests from any origin. In production, of course, it is recommended to set more strict rules.
For additional application, you can use<security-constraint>
V web.xml
:
<security-constraint>
<web-resource-collection>
<web-resource-name>Protected Area</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>user</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
All requests will now require authentication and use of SSL.
Secure headers
You can add secure HTTP headers using a filter web.xml
:
<filter>
<filter-name>HttpHeaderSecurityFilter</filter-name>
<filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class>
<init-param>
<param-name>antiClickJackingOption</param-name>
<param-value>SAMEORIGIN</param-value>
</init-param>
<init-param>
<param-name>xssProtectionOption</param-name>
<param-value>1; mode=block</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>HttpHeaderSecurityFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Also, do not forget to limit access to /manager
And /host-manager
with strict rules in conf/tomcat-users.xml
.
Scaling
Configuring Tomcat Clusters
Clustering in Tomcat is the process of combining multiple Tomcat instances to process requests to the same web application as a single unit.
All Tomcat instances on different servers must have the same web application version and configuration.
In file conf/server.xml
Each Tomcat instance will need to be configured with a cluster. Insert the following snippet into the element <Engine>
:
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
This configuration enables a clustering mechanism using a simple TCP cluster.
Load balancing with Apache HTTP or Nginx
You can use Apache HTTP Server or Nginx as a reverse proxy to distribute incoming requests among Tomcat cluster nodes.
Setting up Apache HTTP with mod_jk:
Need to install mod_jk
and configure workers.properties
to specify cluster nodes:
worker.list=loadbalancer
worker.tomcat1.type=ajp13
worker.tomcat1.host=server1.example.com
worker.tomcat1.port=8009
worker.tomcat2.type=ajp13
worker.tomcat2.host=server2.example.com
worker.tomcat2.port=8009
worker.loadbalancer.type=lb
worker.loadbalancer.balance_workers=tomcat1,tomcat2
Add the configuration to httpd.conf
to redirect requests to the balancer:
LoadModule jk_module modules/mod_jk.so
JkWorkersFile conf/workers.properties
JkMount /* loadbalancer
In the Nginx configuration file (nginx.conf
) you need to define an upstream for Tomcat nodes and configure the server to redirect requests:
upstream tomcat_cluster {
server server1.example.com:8080;
server server2.example.com:8080;
}
server {
listen 80;
location / {
proxy_pass http://tomcat_cluster;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Session replication and sticky sessions
In clustered environments, session replication keeps session data synchronized between nodes.
In file conf/server.xml
add cluster configuration with DeltaManager
for session replication:
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster">
<Manager className="org.apache.catalina.ha.session.DeltaManager"
expireSessionsOnShutdown="false"
notifyListenersOnReplication="true"/>
<!-- можно включить прочие настройки кластера и канала -->
</Cluster>
DeltaManager
replicates only changes in the session, making replication resource efficient.
Sticky sessions allow you to “stick” a user session to a specific server to ensure data consistency. In Apache or Nginx this is achieved through the balancer settings.
Nginx:
http {
upstream backend {
server backend1.example.com;
server backend2.example.com;
sticky;
}
server {
location / {
proxy_pass http://backend;
}
}
}
Apache HTTP Server with mod_proxy_balancer:
<Proxy "balancer://mycluster">
BalancerMember "http://backend1.example.com" route=1
BalancerMember "http://backend2.example.com" route=2
ProxySet stickysession=JSESSIONID
</Proxy>
ProxyPass / balancer://mycluster/
ProxyPassReverse / balancer://mycluster/
Apache ZooKeeper
ZooKeeper can be used to manage the configuration and state of a cluster.
Let's install ZooKeeper on a separate server or group of servers and create a configuration file conf/zoo.cfg
with basic settings:
tickTime=2000
dataDir=/var/lib/zookeeper
clientPort=2181
initLimit=5
syncLimit=2
server.1=zk1.example.com:2888:3888
server.2=zk2.example.com:2888:3888
For integration you can Apache Curator. Let's register the node:
CuratorFramework client = CuratorFrameworkFactory.newClient(zookeeperConnectionString, new ExponentialBackoffRetry(1000, 3));
client.start();
String path = "/tomcat/nodes/" + nodeId;
byte[] payload = "Some node data".getBytes();
client.create().creatingParentsIfNeeded().forPath(path, payload);
The code creates a node in ZooKeeper for each Tomcat instance.
Integrating Apache Tomcat with web servers
Integration with Tomcat is often done using a module mod_jk
which allows the HTTP Server to communicate with Tomcat via AJP.
Let's install mod_jk
and download the corresponding OS binary file or build it from source, and then add it to the Apache configuration:
LoadModule jk_module modules/mod_jk.so
File workers.properties
defines how the server will interact with Tomcat instances. Let's create this file and configure the worker in it:
worker.list=worker1
worker.worker1.type=ajp13
worker.worker1.host=localhost
worker.worker1.port=8009
IN httpd.conf
or in a separate configuration file we will add an indication of workers.properties
and configure routing:
JkWorkersFile /path/to/your/workers.properties
JkMount / worker1
This will redirect all requests to Apache HTTP Server to Tomcat via AJP.
You can get more practical skills in application architecture as part of practical online courses from industry experts.