1. 程式人生 > >分散式系列二: 分散式系統的通訊

分散式系列二: 分散式系統的通訊

通訊是分散式架構的一個基本問題, 通訊是基於通訊協議, 通過網路IO來實現的, 基本的通訊協議有TCP,HTTP,UDP等, Java的IO分為BIO,NIO,AIO等, java領域有很多支援通訊的技術, 如RMI,MINA,JMS等.

網路協議

  • TCP/IP:

    五層模型: 基於OSI七層模型. 包含: 應用層,傳輸層(TCP/IP協議),網路層(ICMP,IGMP),鏈路層,物理層. OSI還包含表現層,會話層.

    三次握手:

    Dos攻擊就是在第三步發生, 傳送大量連線請求, 使網路處在半連線狀態. server端的連線未完成, 導致阻塞.

    四次揮手:

    TCP協議是全雙工的, 全雙工是雙方可以相互發起通訊, 資料可以往兩個方向傳輸; 半雙工是某個階段只能一方傳輸; 單工是隻能一方往另一方傳輸資料.

  • UDP/IP:

阻塞的概念

瞭解阻塞, 就首先需要了解TCP傳輸協議的快取區概念.

應用層傳送資料的時候, 首先資料會暫存到傳輸層的快取區.

資料傳輸的時候有個滑動視窗的概念, 視窗的大小可以控制, 這樣可以保證接收方快取區不夠大導致快取溢位. 視窗的資料全部發送且接收方確認收到後才可以向前繼續滑動.

傳送方和接收方均有快取區, 當快取區滿(或空, 分別對應寫和讀)的時候就會發生阻塞, 必須等快取區有足夠空間容納更多資料的時候才能繼續傳送或接收.

阻塞分為BIO(同步阻塞),NIO(同步非阻塞, 同路複用技術,netty等使用這種方式),AIO(非同步非阻塞, java7開始)

阻塞和非阻塞, 同步和非同步分開理解比較好.阻塞和非阻塞是針對呼叫者, 阻塞是緩衝區讀寫沒有資料的時候執行緒等待, 非阻塞是緩衝區讀寫沒有資料時立即返回, 執行緒去做其他的事情; 同步和非同步是針對被呼叫者, 被呼叫者處理時不返回時, 呼叫者需要等待結果是同步, 被呼叫者立即返回,同時做處理時非同步.

Java 網路通訊

TCP Socket通訊

// 服務端
public class SocketServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = null;

        try{
            serverSocket = new ServerSocket(8888);
            Socket socket= serverSocket.accept();
            // 緩衝區讀取
            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            System.out.println(reader.readLine());
            reader.close();
            socket.close();
        }catch (Exception e){

        }finally {
            if(serverSocket!=null){
                serverSocket.close();
            }
        }
    }
}

//客戶端
public class SocketClient {
    public static void main(String[] args) throws IOException {

        try{
            Socket socket = new Socket("localhost",8888);
            PrintWriter writer = new PrintWriter(socket.getOutputStream(),true);
            writer.println("this is a message from client");
            writer.close();
            socket.close();
        }catch (Exception e){

        }finally {

        }
    }
}

Multicast 多播, 使用UDP協議

// 服務端
public class MulticastServer {
    public static void main(String[] args) throws IOException, InterruptedException {
        // 多播必須是224網段
        InetAddress group = InetAddress.getByName("224.7.8.9");
        MulticastSocket socket = new MulticastSocket();
        for (int i = 0; i < 10; i++) {
            String data = "multcast"+i;
            byte[] bytes = data.getBytes();
            socket.send(new DatagramPacket(bytes,bytes.length,group,8888));
            TimeUnit.SECONDS.sleep(2);
        }
    }
}

// 客戶端
public class MulticastClient {
    public static void main(String[] args) throws IOException, InterruptedException {
        // 多播必須是224網段
        InetAddress group = InetAddress.getByName("224.7.8.9");
        MulticastSocket socket = new MulticastSocket(8888);
        socket.joinGroup(group);
        byte[] buf = new byte[32];
        while (true){
            DatagramPacket packet = new DatagramPacket(buf,buf.length);
            socket.receive(packet);
            String reveived = new String(packet.getData());
            System.out.println("received:"+reveived);
        }
    }
}