Java实现Nginx类似的服务转发

简介

在本文中,我将向你介绍如何使用Java实现类似Nginx的服务转发功能。我们将使用Java的Socket编程来实现这个功能,通过一个简单的示例来演示整个过程。

整体流程

下面是实现服务转发的整体流程。我们将使用一个中间服务器来接收客户端请求,并将其转发到多个目标服务器上。

sequenceDiagram
    participant Client
    participant Proxy Server
    participant Target Server1
    participant Target Server2
    
    Client ->> Proxy Server: 发送请求
    Proxy Server ->> Target Server1: 转发请求
    Proxy Server ->> Target Server2: 转发请求
    Target Server1 -->> Proxy Server: 返回响应
    Target Server2 -->> Proxy Server: 返回响应
    Proxy Server -->> Client: 返回响应

代码实现

创建ProxyServer类

首先,我们需要创建一个名为ProxyServer的类,这个类将负责接收客户端请求,并将其转发到目标服务器上。

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class ProxyServer {
    private static final int SERVER_PORT = 8080;
    private static final String TARGET_SERVER1_IP = "127.0.0.1";
    private static final int TARGET_SERVER1_PORT = 8001;
    private static final String TARGET_SERVER2_IP = "127.0.0.1";
    private static final int TARGET_SERVER2_PORT = 8002;

    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(SERVER_PORT);
            System.out.println("Proxy Server started on port " + SERVER_PORT);

            while (true) {
                Socket clientSocket = serverSocket.accept();
                System.out.println("Accepted connection from " + clientSocket.getInetAddress());

                InputStream clientInput = clientSocket.getInputStream();
                OutputStream clientOutput = clientSocket.getOutputStream();

                // 创建两个线程分别将请求转发到目标服务器上
                Thread targetThread1 = new Thread(() -> forwardRequest(clientInput, clientOutput, TARGET_SERVER1_IP, TARGET_SERVER1_PORT));
                Thread targetThread2 = new Thread(() -> forwardRequest(clientInput, clientOutput, TARGET_SERVER2_IP, TARGET_SERVER2_PORT));

                targetThread1.start();
                targetThread2.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void forwardRequest(InputStream clientInput, OutputStream clientOutput, String targetIP, int targetPort) {
        try {
            Socket targetSocket = new Socket(targetIP, targetPort);

            InputStream targetInput = targetSocket.getInputStream();
            OutputStream targetOutput = targetSocket.getOutputStream();

            // 将客户端请求转发到目标服务器
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = clientInput.read(buffer)) != -1) {
                targetOutput.write(buffer, 0, bytesRead);
                targetOutput.flush();
            }

            // 将目标服务器的响应转发给客户端
            while ((bytesRead = targetInput.read(buffer)) != -1) {
                clientOutput.write(buffer, 0, bytesRead);
                clientOutput.flush();
            }

            targetSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

创建TargetServer类

接下来,我们需要创建一个名为TargetServer的类,这个类将模拟目标服务器,接收转发过来的请求并返回响应。

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TargetServer {
    private static final int SERVER_PORT = 8001;

    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(SERVER_PORT);
            System.out.println("Target Server started on port " + SERVER_PORT);

            while (true) {
                Socket clientSocket = serverSocket.accept();
                System.out.println("Accepted connection from " + clientSocket.getInetAddress());

                InputStream clientInput = clientSocket.getInputStream();
                OutputStream clientOutput = clientSocket.getOutputStream();

                // 处理客户端请求并返回响应
                byte[] buffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = clientInput.read(buffer)) != -1) {
                    // 处理请求...
                    String request = new String(buffer, 0, bytesRead);
                    System.out.println("Received request: " + request);

                    // 返回响应...
                    String response = "Hello from Target Server!";
                    clientOutput.write(response.getBytes());
                    clientOutput.flush();
                }

                clientSocket.close();
            }
        } catch (IOException e) {