Java Architecture Evolution Project: A Journey to Scalability

Java Architecture Evolution Project: A Journey to Scalability

System Architecture Evolution History

The evolution of a website’s architecture is a story of growth, innovation, and adaptation. From humble beginnings as a small site, the architecture has undergone significant changes to accommodate the increasing demands of users. In this article, we will explore the key milestones in the evolution of a Java-based system architecture.

Monomers Architecture

The journey begins with a simple monomers architecture, where all resources, applications, databases, and files reside on a single server. This setup is suitable for small sites with minimal traffic. The server operating system is typically Linux, and the application is built using Java or other languages, deployed on Apache or Nginx. The database is MySQL, an open-source technology, deployed on a cheap server.

CREATE TABLE users (
  id INT PRIMARY KEY,
  name VARCHAR(255),
  email VARCHAR(255)
);

Separation of Application Services and Data Services

As the company’s business grows, the single server architecture becomes inadequate. The increasing number of users leads to performance issues, and data storage becomes insufficient. To address this, the separation of application services and data services is introduced. Three servers are used: application servers, file servers, and database servers.

# Application Server Configuration
server {
  listen 80;
  server_name example.com;
  location / {
    proxy_pass http://localhost:8080;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
  }
}

# File Server Configuration
server {
  listen 80;
  server_name example.com;
  location /files {
    alias /var/www/files;
    autoindex on;
  }
}

# Database Server Configuration
server {
  listen 3306;
  server_name example.com;
  database mysql;
}

The Use of Cache

To reduce the pressure on the database and improve overall website performance, caching is introduced. The 80/20 rule states that 80% of the business is concentrated on 20% of the data. By caching this small portion of data in memory, the database access is reduced, and the overall website data access speed is improved.

// Cache Configuration
public class Cache {
  private static final String CACHE_NAME = "example_cache";
  private static final int CACHE_TTL = 60 * 60; // 1 hour

  public static String get(String key) {
    // Retrieve value from cache
  }

  public static void set(String key, String value) {
    // Store value in cache
  }
}

Using Cluster

While caching solves the problem of database access, it does not address the issue of concurrent pressure on the server. To address this, an application server is added to access shared storage, reducing the pressure on the original server.

# Cluster Configuration
server {
  listen 80;
  server_name example.com;
  location / {
    proxy_pass http://localhost:8080;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
  }
}

# Shared Storage Configuration
server {
  listen 8081;
  server_name example.com;
  alias /var/www/shared;
}

Database Separate Read and Write

As the system runs for some time, the cache is added, and the majority of database operations are performed through the database. However, there are still instances where cache misses or cache expiration occur, and all write operations need to access the database. To address this, the database is configured to use a hot backup function, with a master-slave relationship.

CREATE TABLE users (
  id INT PRIMARY KEY,
  name VARCHAR(255),
  email VARCHAR(255)
);

CREATE TABLE backups (
  id INT PRIMARY KEY,
  name VARCHAR(255),
  email VARCHAR(255)
);

Reverse Proxy and CDN Acceleration

To cope with the different parts of the user’s access and complex network environment, reverse proxy and CDN acceleration are introduced. The goal is to return data to the user as soon as possible, speeding up access speed and reducing the load pressure on the back-end server.

# Reverse Proxy Configuration
server {
  listen 80;
  server_name example.com;
  location / {
    proxy_pass http://localhost:8080;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
  }
}

# CDN Configuration
server {
  listen 443;
  server_name example.com;
  ssl_certificate /etc/ssl/certs/example.com.crt;
  ssl_certificate_key /etc/ssl/private/example.com.key;
  location / {
    proxy_pass http://localhost:8080;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
  }
}

Distributed Database and Distributed File

As the business grows, the single database and file system become inadequate. To address this, a distributed database and distributed file system are introduced.

# Distributed Database Configuration
server {
  listen 3306;
  server_name example.com;
  database mysql;
  replication {
    master {
      host = 'localhost';
      port = 3306;
      user = 'root';
      password = 'password';
    }
    slave {
      host = 'localhost';
      port = 3307;
      user = 'root';
      password = 'password';
    }
  }
}

# Distributed File Configuration
server {
  listen 8081;
  server_name example.com;
  alias /var/www/shared;
  replication {
    master {
      host = 'localhost';
      port = 8081;
      user = 'root';
      password = 'password';
    }
    slave {
      host = 'localhost';
      port = 8082;
      user = 'root';
      password = 'password';
    }
  }
}

NoSQL and Search Engines

As the business becomes more complex, the demand for data storage and retrieval becomes increasingly complex. To address this, NoSQL databases and search engines are introduced.

// NoSQL Database Configuration
public class NoSQLDatabase {
  private static final String DB_NAME = "example_db";
  private static final String HOST = "localhost";
  private static final int PORT = 8080;

  public static void main(String[] args) {
    // Connect to NoSQL database
  }
}

// Search Engine Configuration
public class SearchEngine {
  private static final String INDEX_NAME = "example_index";
  private static final String HOST = "localhost";
  private static final int PORT = 8081;

  public static void main(String[] args) {
    // Connect to search engine
  }
}

Business Split

As the traffic reaches a certain size, the entire system is divided into different product lines, such as home, shop, order, buyers, sellers, and payment. Each product line is a separate application, deployed independently, and maintains a connection through RPC frames (dubbo, webService, httpClient …) between applications.

// Product Line Configuration
public class ProductLine {
  private static final String HOME = "home";
  private static final String SHOP = "shop";
  private static final String ORDER = "order";

  public static void main(String[] args) {
    // Connect to product line
  }
}

Distributed Services

As the business grows, the overall complexity of the application system increases exponentially. To address this, distributed services are introduced, where each service is a separate application, deployed independently, and maintains a connection through RPC frames between applications.

// Distributed Service Configuration
public class DistributedService {
  private static final String SERVICE_NAME = "example_service";
  private static final String HOST = "localhost";
  private static final int PORT = 8080;

  public static void main(String[] args) {
    // Connect to distributed service
  }
}

Conclusion

The evolution of a Java-based system architecture is a complex process that requires careful planning, innovation, and adaptation. From humble beginnings as a small site to the current distributed services architecture, the journey has been marked by significant milestones, including the separation of application services and data services, the use of cache, and the introduction of NoSQL databases and search engines. As the business continues to grow, the architecture will continue to evolve, with the introduction of new technologies and innovations.