分散式系列二: 分散式系統的通訊
通訊是分散式架構的一個基本問題, 通訊是基於通訊協議, 通過網路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);
}
}
}