DEV Community

damilola lawal
damilola lawal

Posted on

A Multi-Tier web Application Stack using; Nginx, Tomcat, Memcached, RabbitMQ on AWS EC2 instance

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.

web-stack flow

  • 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

  1. The centos which will host the Tomcat service, memcache, Mysql and RabbitMQ.
  2. 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
Enter fullscreen mode Exit fullscreen mode
  • Set Repository
sudo yum install epel-release -y
Enter fullscreen mode Exit fullscreen mode
  • Install MariaDB package
yum install git mariadb-server -y
Enter fullscreen mode Exit fullscreen mode

start MariaDB service and enable to start automatically at boot time.

 systemctl start mariadb
 systemctl enable mariadb
Enter fullscreen mode Exit fullscreen mode

Run the **mysql secure installation **script, to enable us secure our database.

mysql_secure_installation
Enter fullscreen mode Exit fullscreen mode

Also, I will be using admin123 as root password but you can use any password but ensure its strong ( containing alphabet, numeric and characters).

mysql secure installation

Next, set the database name, create user and grant all remote privilege.

 mysql -u root -padmin123
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

db_backup.sql script create all necessary schema and table on the database.

mysql> show tables;
mysql> exit;
Enter fullscreen mode Exit fullscreen mode

Image description

Restart mariadb,

systemctl restart mariadb
Enter fullscreen mode Exit fullscreen mode

Check the mariadb status

systemctl status mariadb

Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

SET UP RABBITMQ

update OS to latest patches.

 yum update -y
Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

*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
Enter fullscreen mode Exit fullscreen mode

Install maven ( to build our application from source code) and also install git

 dnf install git maven wget -y
Enter fullscreen mode Exit fullscreen mode

Change directory to /tmp

cd /tmp/
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Extract package

tar xzvf apache-tomcat-9.0.75.tar.gz
Enter fullscreen mode Exit fullscreen mode

Add tomcat user to run tomcat services and add user to a home directory.

useradd --home-dir /usr/local/tomcat --shell /sbin/nologin tomcat
Enter fullscreen mode Exit fullscreen mode

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/
Enter fullscreen mode Exit fullscreen mode

new

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
Enter fullscreen mode Exit fullscreen mode

tomcat

Setup systemctl command for tomcat

Create tomcat service file

vi /etc/systemd/system/tomcat.service
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Start and Enable service

systemctl start tomcat
systemctl enable tomcat
Enter fullscreen mode Exit fullscreen mode

Build code and Deploy

Update configuration,

cd vprofile-project
Enter fullscreen mode Exit fullscreen mode
vim src/main/resources/application.properties
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Build code
Run below command inside the repository
Make sure you are in the vprofile directory & run the mvn install

mvn install
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
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
Enter fullscreen mode Exit fullscreen mode

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.

tomcat

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
Enter fullscreen mode Exit fullscreen mode

Install nginx

apt install nginx -y
Enter fullscreen mode Exit fullscreen mode

Create Nginx conf file

vi /etc/nginx/sites-available/vproapp
Enter fullscreen mode Exit fullscreen mode
upstream vproapp {
    server <public_IP_of_Centos_instance>:8080;
}

server {
    listen 80;
    location / {
        proxy_pass http://vproapp;
    }
}
Enter fullscreen mode Exit fullscreen mode

Remove default nginx conf

 rm -rf /etc/nginx/sites-enabled/default
Enter fullscreen mode Exit fullscreen mode

Create link to activate website and make our website default

ln -s /etc/nginx/sites-available/vproapp /etc/nginx/sites-enabled/vproapp
Enter fullscreen mode Exit fullscreen mode

Restart Nginx

 systemctl restart nginx
Enter fullscreen mode Exit fullscreen mode

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 page

Login using admin_vp as user admin-vp as password

Website page

Click on RabbitMQ

RabbitMQ

Click on All_user and this will fetch all user on databse

Users

Thank you for reading...

Top comments (0)