A Multi-Tier web Application Stack using; Nginx, Tomcat, Memcached, RabbitMQ on AWS EC2 instance
damilola lawal
Posted on July 15, 2024
Welcome, this project will show how to create a simple multi-tier web application application hosted ec2-instance.
These stack consist of the web layer, application layer and database layer.
Each of these services have its functionality which include;
Nginx: Nginx is a high-performance web server and reverse proxy server that efficiently handles HTTP and other web traffic, known for its stability, rich feature set, and low resource consumption.
Tomcat:Apache Tomcat is an open-source Java Servlet container. It is a web server and servlet container that serves as a platform for running Java applications.
MySQL: MySQL is a widely-used open-source relational database management system (RDBMS) that allows for the efficient storage, retrieval, and management of data using SQL (Structured Query Language).
Memcached: Mem-cached is a distributed memory caching system designed to speed up dynamic web applications by reducing database load through caching data and objects in RAM.
RabbitMQ: RabbitMQ is a robust, open-source message broker that facilitates the efficient handling of message queuing for distributed systems and microservices, supporting multiple messaging protocols.
In web development,
STACKS are collection of services working together to create an experience
Example MERN, LAMP etc.
The image below shows the workflow of these project.
User enters the URL of the website (ip-address will be used for this project).
The request goes to Nginx (act as a load balancer which route request to the Apache Tomcat service- a JAVA web application service).
The web application is hosted on the tomcat server.
The user information will be logged into the MYSQL database.
RabbitMQ serves as a broker/queuing agent, enabling seamless communication and message queuing between distributed systemsRead more.
Memcached service is a database caching agent connected to MySQL and previously accessed information from the database is cached to it reducing database hit and increase performance.
PREREQUISITE
- Two EC2 instance ( one centos and one ubuntu).
- Gitbash or an IDE.
Create two medium EC2 instance
- The centos which will host the Tomcat service, memcache, Mysql and RabbitMQ.
- The ubuntu will be hosting Nginx.
- MySQL (Database SVC)
- Memcache (DB Caching SVC)
- RabbitMQ (Broker/Queue SVC)
- Tomcat (Application SVC)
- Nginx (Web SVC)
We are going to start the configuration from the database to the web layer as its custom to do so.
Setting up MYSQL service:
SSH into the Centos EC2 instance & update OS
sudo yum update -y
- Set Repository
sudo yum install epel-release -y
- Install MariaDB package
yum install git mariadb-server -y
start MariaDB service and enable to start automatically at boot time.
systemctl start mariadb
systemctl enable mariadb
Run the **mysql secure installation **script, to enable us secure our database.
mysql_secure_installation
Also, I will be using admin123 as root password but you can use any password but ensure its strong ( containing alphabet, numeric and characters).
Next, set the database name, create user and grant all remote privilege.
mysql -u root -padmin123
where user is root and password is admin123
mysql> create database accounts;
mysql> grant all privileges on accounts.* TO 'admin'@'%' identified by 'admin123';
mysql> FLUSH PRIVILEGES;
mysql> exit;
In the above code, we grant all privilege ( SELECT, DELETE, INSERT, UPDATE e.t.c ) on database name "accounts" to a user "admin" who can connect from any host ( % ).
Next, we will clone the Repo that has the source code for our application and initialize database.
git clone -b main https://github.com/lasdapharm/vprofile-project.git
cd vprofile-project
mysql -u root -padmin123 accounts < src/main/resources/db_backup.sql
mysql -u root -padmin123 accounts
db_backup.sql script create all necessary schema and table on the database.
mysql> show tables;
mysql> exit;
Restart mariadb,
systemctl restart mariadb
Check the mariadb status
systemctl status mariadb
SET UP MEMCACHE SERVICE
Install, start & enable memcache
sudo dnf install epel-release -y
sudo dnf install memcached -y
sudo systemctl start memcached
sudo systemctl enable memcached
sudo systemctl status memcached
sudo systemctl restart memcached
SET UP RABBITMQ
update OS to latest patches.
yum update -y
Install dependencies,
sudo yum install wget -y
cd /tmp/
dnf -y install centos-release-rabbitmq-38
dnf --enablerepo=centos-rabbitmq-38 -y install rabbitmq-server
systemctl enable --now rabbitmq-server
Setup access to user "test" and make it "admin"
sudo sh -c 'echo "[{rabbit, [{loopback_users, []}]}]." > /etc/rabbitmq/rabbitmq.config'
sudo rabbitmqctl add_user test test
sudo rabbitmqctl set_user_tags test administrator
sh -c '...': Invokes the shell to execute the command within the single quotes.
[{rabbit, [{loopback_users, []}]}]. is the content being written to the RabbitMQ configuration file. This configuration tells RabbitMQ not to restrict the guest user to only loopback (localhost) connections.
By default, RabbitMQ restricts the guest user to only connect from localhost (loopback).
Setting loopback_users to an empty list ([]) removes this restriction, allowing the guest user to connect from any IP address.
Restart RabbitMQ
sudo systemctl restart rabbitmq-server
*SET UP TOMCAT SERVICE
*
When we install other services, we use the package managers (yum and dnf) and this way, we automatically get the systemctl command to manage the service ( start, stop, enable service ) and place the configuration, binaries e.t.c in the rigt directory but for tomcat we are going download the package and configure the systemctl ourselves.
Tomcat service need JDK (openjdk11 : to develop our application) as dependencies so we going install that as well.
dnf -y install java-11-openjdk java-11-openjdk-devel
Install maven ( to build our application from source code) and also install git
dnf install git maven wget -y
Change directory to /tmp
cd /tmp/
Download and install tomcat package
wget https://archive.apache.org/dist/tomcat/tomcat-9/v9.0.75/bin/apache-tomcat-9.0.75.tar.gz
Extract package
tar xzvf apache-tomcat-9.0.75.tar.gz
Add tomcat user to run tomcat services and add user to a home directory.
useradd --home-dir /usr/local/tomcat --shell /sbin/nologin tomcat
The tomcat user created will be used by tomcat process so we don't need login (--shell /sbin/nologin).
Copy all file in apache-tomcat-9.0.75 to /usr/local/tomcat/
cp -r /tmp/apache-tomcat-9.0.75/* /usr/local/tomcat/
When we do this, the copy command will copy the folder and file as root user and all files and folder will automatically be owned by root.
We need to change the ownership of the files and folder to tomcat user and tomcat group.
This changes is required for systemctl otherwise using systemctl to start, stop or enable tomcat service will fail.
chown -R tomcat.tomcat /usr/local/tomcat
Setup systemctl command for tomcat
Create tomcat service file
vi /etc/systemd/system/tomcat.service
Update the tomcat.srvice with this configuration
[Unit]
Description=Tomcat
After=network.target
[Service]
User=tomcat
WorkingDirectory=/usr/local/tomcat
Environment=JRE_HOME=/usr/lib/jvm/jre
Environment=JAVA_HOME=/usr/lib/jvm/jre
Environment=CATALINA_HOME=/usr/local/tomcat
Environment=CATALINE_BASE=/usr/local/tomcat
ExecStart=/usr/local/tomcat/bin/catalina.sh run
ExecStop=/usr/local/tomcat/bin/shutdown.sh
SyslogIdentifier=tomcat-%i
[Install]
WantedBy=multi-user.target
When we say systemctl start, "ExecStart=/usr/local/tomcat/bin/catalina.sh run" _get executed and for systemctl stop _"ExecStop=/usr/local/tomcat/bin/shutdown.sh" get executed.
Reload the configuration
systemctl daemon-reload
Start and Enable service
systemctl start tomcat
systemctl enable tomcat
Build code and Deploy
Update configuration,
cd vprofile-project
vim src/main/resources/application.properties
Update file with backend server details.
#JDBC Configutation for Database Connection
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://<pubilc_IP_address>:3306/accounts?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
jdbc.username=admin # database username
jdbc.password=admin123 # databse password
#Memcached Configuration For Active and StandBy Host
#For Active Host
memcached.active.host=<pubilc_IP_address>
memcached.active.port=11211
#For StandBy Host
memcached.standBy.host=127.0.0.2
memcached.standBy.port=11211
#RabbitMq Configuration
rabbitmq.address=<pubilc_IP_address>
rabbitmq.port=5672
rabbitmq.username=test
rabbitmq.password=test
Build code
Run below command inside the repository
Make sure you are in the vprofile directory & run the mvn install
mvn install
The command will read the source code and build the artifact ( A deployable product )
Artifact is basically an archive ( in java, archive format is var, jar , war )
Deploy artifact, first stop the tomcat service
systemctl stop tomcat
rm -rf /usr/local/tomcat/webapps/ROOT*
cp target/vprofile-v2.war /usr/local/tomcat/webapps/ROOT.war
systemctl start tomcat
chown tomcat.tomcat /usr/local/tomcat/webapps -R
systemctl restart tomcat
what we did was to remove the default app in java (ROOT) and replace it with our artifact (target/vprofile-v2.war )
We restart tomcat and when tomcat find a war file its will extract it to ROOT.
Finally,
SET UP NGINX
For our nginx which route request to our tomcat service.
We are going to host it on our Ubuntu EC2 instance,
So SSH into the instance,
apt update
Install nginx
apt install nginx -y
Create Nginx conf file
vi /etc/nginx/sites-available/vproapp
upstream vproapp {
server <public_IP_of_Centos_instance>:8080;
}
server {
listen 80;
location / {
proxy_pass http://vproapp;
}
}
Remove default nginx conf
rm -rf /etc/nginx/sites-enabled/default
Create link to activate website and make our website default
ln -s /etc/nginx/sites-available/vproapp /etc/nginx/sites-enabled/vproapp
Restart Nginx
systemctl restart nginx
Security.
- Allow inbound rule for our EC2 instance
- For the Centos, allow inbound traffic on port 3306 (Mysql), 11211 (memcached), 5672 ( RabbitMQ) from Ubuntu.
- Allow inbound traffic from 0.0.0.0 on port 80 on the Ubuntu instance since its public-facing.
Validation
Access the website from web browser by :80
Login using admin_vp as user admin-vp as password
Click on RabbitMQ
Click on All_user and this will fetch all user on databse
Thank you for reading...
Posted on July 15, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 27, 2024