首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 在 Client/Server 架構中的演進:從 C/S 到 B/S 再到微服務的網絡編程實踐

     編輯:Java 相關知識

架構演進脈絡

Java 誕生於網絡時代,其網絡能力始終伴隨著架構模式的變遷:

階段架構模式Java 角色核心技術棧
1.0 時代 (90s 末) C/S (Client/Server) 胖客戶端 Applet/Swing 客戶端 + Socket 直連數據庫/應用服務器 java.net.Socket, RMI, JDBC, Swing/AWT
J2EE 時代 (00s 初) B/S (Browser/Server) 三層架構 Servlet/JSP 生成 HTML,EJB 承載業務邏輯,瀏覽器瘦客戶端 Servlet API, EJB, JSP, JMS, JNDI
Spring 時代 (00s 中-10s) 輕量級容器 + SOA POJO 開發,依賴注入,AOP,聲明式事務,集成各類中間件 Spring MVC, Hibernate/MyBatis, Dubbo, ZooKeeper
雲原生時代 (10s 末-今) 微服務 / Serverless / Service Mesh 容器化部署,配置中心,網關路由,熔斷限流,可觀測性,gRPC/REST 通信 Spring Boot/Cloud, Kubernetes, Istio, gRPC, Netty, GraalVM

一、Java 網絡類庫的核心支撐

無論架構如何變遷,java.net 及其擴展包始終提供基礎原語:

  • 寻址與連接: InetAddress, InetSocketAddress, URL, URI (JDK 20+ 更完善)
  • 傳輸通道: Socket (TCP), ServerSocket, DatagramSocket (UDP), SocketChannel (NIO)
  • 協議處理器 SPI: URLStreamHandlerFactory, ContentHandlerFactory 實現協議擴展 (如 jar:, jrt:)
  • 安全通信: SSLSocket, SSLServerSocket, SSLContext, KeyManager/TrustManager (JSSE)

二、經典 Socket 通信模式:請求-響應

原文給出的「文本反轉服務器」展示了基礎交互模型。現代化改造要點:

1. 協議幀定義 (解決粘包/拆包)

// 長度前綴 + JSON 體 (4 字節大端長度 + UTF-8 JSON)
public class FrameCodec {
    public static void write(OutputStream out, String json) throws IOException {
        byte[] body = json.getBytes(StandardCharsets.UTF_8);
        ByteBuffer buf = ByteBuffer.allocate(4 + body.length);
        buf.putInt(body.length).put(body);
        out.write(buf.array());
        out.flush();
    }
    public static String read(InputStream in) throws IOException {
        byte[] lenBytes = new byte[4];
        readFully(in, lenBytes);
        int len = ByteBuffer.wrap(lenBytes).getInt();
        if (len > 1024*1024) throw new IOException("Frame too large");
        byte[] body = new byte[len];
        readFully(in, body);
        return new String(body, StandardCharsets.UTF_8);
    }
    private static void readFully(InputStream in, byte[] buf) throws IOException {
        int off = 0;
        while (off < buf.length) {
            int r = in.read(buf, off, buf.length - off);
            if (r == -1) throw new EOFException();
            off += r;
        }
    }
}

2. 服務端:線程池 + 連接生命周期管理

public class ModernServer {
    private final ExecutorService workerPool = new ThreadPoolExecutor(
        4, 200, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(10000),
        new ThreadFactoryBuilder().setNameFormat("socket-worker-%d").build(),
        new ThreadPoolExecutor.AbortPolicy() // 拒絕策略:拋異常觸發熔斷
    );
    private final ServerSocket serverSocket;

    public ModernServer(int port) throws IOException {
        this.serverSocket = new ServerSocket(port);
        this.serverSocket.setReuseAddress(true);
        this.serverSocket.setSoTimeout(1000); // accept 超時,定期檢查關閉標誌
    }

    public void start() {
        new Thread(this::acceptLoop, "acceptor").start();
    }

    private void acceptLoop() {
        while (!Thread.currentThread().isInterrupted()) {
            try {
                Socket client = serverSocket.accept();
                client.setSoTimeout(30000); // 讀超時
                client.setTcpNoDelay(true);
                workerPool.submit(() -> handleClient(client));
            } catch (SocketTimeoutException ignored) { /* 定期檢查中斷 */ }
            catch (IOException e) { if (!serverSocket.isClosed()) log.error("Accept error", e); }
        }
    }

    private void handleClient(Socket socket) {
        try (socket;
             InputStream in = socket.getInputStream();
             OutputStream out = socket.getOutputStream()) {
            while (true) {
                String req = FrameCodec.read(in);
                String resp = processRequest(req); // 業務邏輯
                FrameCodec.write(out, resp);
            }
        } catch (IOException e) {
            log.debug("Client disconnected: {}", e.getMessage());
        }
    }

    private String processRequest(String req) {
        // 解析 JSON, 路由到 Service Bean, 返回響應
        return "{\"result\":\"reversed: " + new StringBuilder(req).reverse() + "\"}";
    }

    public void stop() throws IOException {
        serverSocket.close();
        workerPool.shutdown();
        workerPool.awaitTermination(30, TimeUnit.SECONDS);
    }
}

3. 客戶端:連接池 + 重試 + 熔斷

public class PooledClient {
    private final BlockingQueue pool = new LinkedBlockingQueue<>();
    private final String host; private final int port;
    private final int maxSize = 50;

    public PooledClient(String host, int port) { this.host = host; this.port = port; }

    private Socket createSocket() throws IOException {
        Socket s = new Socket();
        s.connect(new InetSocketAddress(host, port), 3000);
        s.setSoTimeout(5000);
        s.setTcpNoDelay(true);
        return s;
    }

    public String sendRequest(String request) {
        Socket socket = null;
        try {
            socket = pool.poll(100, TimeUnit.MILLISECONDS);
            if (socket == null || socket.isClosed() || !socket.isConnected()) {
                socket = createSocket();
            }
            FrameCodec.write(socket.getOutputStream(), request);
            return FrameCodec.read(socket.getInputStream());
        } catch (Exception e) {
            closeQuietly(socket);
            socket = null;
            throw new RuntimeException("Request failed", e);
        } finally {
            if (socket != null && !socket.isClosed() && pool.size() < maxSize) {
                pool.offer(socket); // 歸還池
            } else {
                closeQuietly(socket);
            }
        }
    }
}

三、從 Socket 到微服務通信的範式轉移

維度手寫 Socket 時代微服務框架時代
協議定義 隱性、文檔、口頭傳承 顯性 IDL (Protobuf/Avro/Thrift/OpenAPI),代碼生成,契約測試
服務發現 硬編碼 IP:Port / 配置文件 註冊中心 (Nacos/Eureka/Consul) + 客戶端負載均衡
通信韌性 手寫重試/超時/連接池 框架內建 (Resilience4j/Sentinel/Envoy):熔斷、限流、重試、超時、隔離
可觀測性 日誌打印、抓包分析 分布式追蹤 (SkyWalking/Zipkin/Jaeger)、指標 (Prometheus)、日誌聚合 (ELK/Loki)
安全 自定義握手/加密 mTLS (Service Mesh/OAuth2/JWT),零信任網絡
部署單元 Fat JAR / WAR Container Image / JLink Runtime / GraalVM Native Image

四、實戰選型指南

  1. 內部高性能 RPC (微服務核心鏈路): **gRPC + Protobuf** (HTTP/2 多路復用、流控、多語言、代碼生成)。Java 實現:grpc-java (Netty 底層)。
  2. 對外開放 API / 異構系統集成: **REST + JSON (OpenAPI 3.0)**。客戶端:Spring RestClient / OpenFeign / Java 11 HttpClient。網關:Spring Cloud Gateway / Kong / Envoy。
  3. 異步事件驅動 / 解耦: **Message Queue (Kafka/RocketMQ/Pulsar/RabbitMQ)**。Java 客戶端配合 Spring Cloud Stream / @RabbitListener。
  4. 極致低延遲 / 金融交易 / 游戲: **自定義 TCP/UDP 協議 + Netty** (或 Aeron/SBE 用戶態網絡)。繞過內核協議棧 (DPDK/XDP) 為極少數頂級場景。
  5. Legacy 系統對接 (無法改造): 封裝 Socket/HttpClient 為 **Anti-Corruption Layer (防腐層)**,隔離協議差異,內部暴露領域模型接口。

五、總結

Java 的網絡編程能力從 Socket 原語出發,經歷了 RMI、Hessian、Dubbo、gRPC、Service Mesh 的層層封裝與抽象。今日架構師面臨的不是「如何寫 Socket」,而是**在何處劃定邊界、選擇何種協議、如何治理通信韌性**。理解 Socket 的三次握手、滑動窗口、Nagle 算法、TIME_WAIT、NIO 事件循環,是為了在框架洩漏抽象時能精準診斷;拥抱高層框架,是為了將有限認知帶寬投入到業務創新與系統穩定性建設中。**網絡是分布式系統的血管,協議是血液,框架是心臟——守護好它們的健康運行,才是 Java 工程師在 Client/Server 演進長河中的核心使命。**

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved