Bản thiết kế · 1.342 từ · 6 phút đọc

Chuyển mạch gói: Cách mạng lưới truyền tải mọi thứ

Chuyển mạch kênh lãng phí băng thông cho sự im lặng. Chuyển mạch gói cắt thông điệp thành những mảnh độc lập và để mạng lưới quên đi cuộc trò chuyện. Chính sự thay đổi đó là lý do internet tồn tại.

#TL;DR

Trước năm 1965, các mạng truyền dữ liệu theo cách hệ thống điện thoại truyền giọng nói: dành riêng một kênh từ đầu đến cuối, giữ nó mở trong suốt cuộc gọi, rồi ngắt khi xong. Paul Baran và Donald Davies độc lập đề xuất điều ngược lại — cắt mỗi thông điệp thành các mảnh nhỏ tự mô tả, gửi từng mảnh một cách độc lập, và ghép lại tại đích. Mạng trở nên không trạng thái và có thể thay thế. Các điểm đầu cuối làm toàn bộ công việc thông minh. Năm mươi năm sau, mọi byte bạn từng gửi vẫn di chuyển theo cách này.

#Chuyển mạch kênh: Mô hình điện thoại

Trong một mạng chuyển mạch kênh, việc đặt một cuộc gọi phân bổ một đường vật lý. Mỗi switch giữa bạn và bên kia dành riêng một phần dung lượng cho cuộc trò chuyện, và dung lượng đó vẫn được giữ riêng ngay cả khi không ai nói.

Với giọng nói analog, nó hoạt động. Hai con người sử dụng đường điện thoại khá hiệu quả. Với máy tính, đó là một thảm họa:

  • Một terminal gửi lệnh sử dụng đường trong vài mili giây, rồi ngồi không trong vài giây hoặc vài phút chờ phản hồi.
  • Việc thiết lập mất thời gian thực sự. Quay số và đàm phán một mạch liên lục địa vào những năm 1960 có thể mất hàng chục giây trước khi byte đầu tiên chảy.
  • Một switch hỏng làm rớt cuộc gọi. Phiên của bạn mất. Bắt đầu lại.
  • Mạng mở rộng theo số kết nối đồng thời, không phải lượng dữ liệu thực sự di chuyển. Tính phí đỉnh, nhàn rỗi hầu hết thời gian.

Đến năm 1960, lưu lượng máy tính rõ ràng mang tính bùng nổ. Chuyển mạch kênh đang tối ưu hóa cho điều sai.

#Tuệ giác của Baran: Khả năng tồn tại

Paul Baran làm việc tại RAND Corporation đầu những năm 1960 với một vấn đề mà Không quân Mỹ quan tâm cấp bách: làm sao giữ cho một mạng chỉ huy hoạt động sau khi một cuộc tấn công hạt nhân phá hủy hầu hết các nút của nó?

Câu trả lời của Baran, được xuất bản dưới dạng một loạt bản ghi nhớ RAND từ 1960 đến 1964, có ba phần:

  1. Một lưới dư thừa — đủ các đường thay thế để mất bất kỳ một nút nào, hoặc thậm chí nhiều nút, không phân mảnh mạng.
  2. Định tuyến phân tán — không có bộ điều khiển trung tâm. Mỗi nút quyết định cục bộ nơi chuyển tiếp từng thông điệp, dựa trên góc nhìn hiện tại của nó về những hàng xóm nào còn sống.
  3. Khối thông điệp — cắt mỗi thông điệp thành các mảnh nhỏ, đồng đều. Mỗi mảnh mang tiêu đề riêng với nguồn, đích, và số thứ tự. Các mảnh có thể đi các tuyến khác nhau. Đích ghép chúng lại.

Ông gọi đó là chuyển mạch khối thông điệp thích ứng phân tán. AT&T, công ty vận hành mạng điện thoại Mỹ, nói với ông nó sẽ không hoạt động. Họ đã sai, nhưng họ không quan tâm.

#Tuệ giác của Davies: Hiệu quả

Donald Davies, tại National Physical Laboratory của Anh, đến cùng một kỹ thuật vào năm 1965 từ một xuất phát điểm hoàn toàn khác. Ông không nghĩ về khả năng sống sót hạt nhân. Ông nghĩ về các máy tính chia sẻ thời gian và sự lãng phí khi giữ một mạch mở qua đại dương cho một phiên tương tác.

Phiên bản của Davies nhấn mạnh ghép kênh thống kê: nếu bạn cắt mỗi thông điệp thành các mảnh nhỏ và đan xen chúng trên các liên kết chia sẻ, bạn có thể gói được nhiều cuộc trò chuyện hơn vào cùng băng thông. Không ai giữ đường dây độc quyền. Mọi người đều có phần tỷ lệ với những gì họ thực sự đang gửi.

Davies cũng đặt cho nó cái tên đã được giữ lại. Ông bác bỏ “khối thông điệp” của Baran là cồng kềnh và chọn một từ ngắn hơn: packet (gói).

Khi ARPA bắt đầu thiết kế ARPANET vào năm 1967, Larry Roberts đã đọc cả Baran lẫn Davies và xây dựng kiến trúc xoay quanh ý tưởng chung của họ.

#Giải phẫu của một gói

Mẹo làm cho mọi thứ khác hoạt động là mỗi gói đều tự mô tả. Bạn có thể giao một gói cho một router chưa từng thấy bất cứ thứ gì khác từ cuộc trò chuyện của bạn, và nó sẽ biết chính xác phải làm gì với gói đó.

Nôm na, mỗi gói có hai phần:

┌───────────────────────────────────────────┐
│  Header (Tiêu đề)                         │
│  ──────                                   │
│  địa chỉ nguồn                            │
│  địa chỉ đích                             │
│  số thứ tự                                │
│  độ dài                                   │
│  checksum                                 │
│  (cờ, phiên bản, TTL, ...)                │
├───────────────────────────────────────────┤
│  Payload (Tải trọng)                      │
│  ───────                                  │
│  lên đến ~1500 byte bất cứ thứ gì bạn muốn│
└───────────────────────────────────────────┘

Tiêu đề là thứ mạng đọc. Tải trọng là thứ mạng bỏ qua. Sự tách biệt đó là toàn bộ mẹo. Một router nhìn vào một gói không quan tâm tải trọng là email, một khung video, một truy vấn cơ sở dữ liệu, hay một thứ sẽ không được phát minh trong ba mươi năm nữa. Nó nhìn địa chỉ đích và chuyển tiếp.

#Gói đến không đúng thứ tự, gói bị mất

Bởi vì mỗi gói đi độc lập, một số điều có thể xảy ra mà không bao giờ xảy ra trong một cuộc gọi chuyển mạch kênh:

  • Đến không đúng thứ tự. Gói 3 đi một đường ngắn hơn và đến đích trước gói 2.
  • Trùng lặp. Một router phát lại một gói mà nó nghĩ đã bị mất; bản gốc vẫn xuất hiện.
  • Mất. Hàng đợi của một router tràn; một gói bị rớt mà không có lời xin lỗi.

Mạng không cố gắng sửa bất kỳ điều nào trong số này. Các điểm đầu cuối làm.

import random

def packetize(message, size=8):
    return [
        {"seq": i, "total": -(-len(message) // size), "data": message[i*size:(i+1)*size]}
        for i in range(-(-len(message) // size))
    ]

def simulate_network(packets, drop_rate=0.1):
    delivered = [p for p in packets if random.random() > drop_rate]
    random.shuffle(delivered)  # tuyến khác nhau, độ trễ khác nhau
    return delivered

def reassemble(packets):
    seen = {p["seq"]: p for p in packets}  # loại trùng theo số thứ tự
    if len(seen) < packets[0]["total"]:
        return None  # một thứ đã mất; yêu cầu phát lại
    return "".join(seen[i]["data"] for i in range(packets[0]["total"]))

msg = "Packet switching makes the network dumb and the endpoints smart."
received = simulate_network(packetize(msg))
print(reassemble(received))

Đây là nguyên tắc đầu cuối đến đầu cuối thu nhỏ: độ tin cậy không phải là thuộc tính của mạng, nó là thuộc tính của những gì các điểm đầu cuối làm với những gì mạng cho chúng. TCP, trong TCP/IP, là phiên bản thư viện của mẫu này.

#Vì sao trừu tượng này không chịu chết

Mọi cuộc cách mạng mạng lớn kể từ 1969 đã thay thế một thứ gì đó — tầng liên kết, giao thức truyền, thuật toán định tuyến, lược đồ địa chỉ — mà không thay thế chuyển mạch gói. Lý do là chuyển mạch gói là một hợp đồng, không phải một công nghệ:

  • Mạng không hiểu tải trọng. Nó không bao giờ phải được nâng cấp khi các ứng dụng thay đổi. Streaming YouTube, SSH và BitTorrent đều chạy trên cùng các router IP.
  • Các điểm đầu cuối không biết topology. Cáp quang thay thế đồng, 5G thay thế LTE, liên kết vệ tinh tham gia — gói không quan tâm. Ứng dụng không quan tâm.
  • Trạng thái sống ở rìa. Một router không giữ trạng thái cuộc trò chuyện. Mất một router, một đường khác hấp thụ lưu lượng, không phiên nào bị rớt. Đây là thuộc tính sống sót của Baran, và đó là lý do internet chưa bao giờ có một switch trung tâm có thể bị tắt.

Chuyển mạch kênh vẫn tồn tại cho các khối lượng công việc cụ thể — mạng quang đồng bộ trong đường trục viễn thông, một số dạng MPLS, các “làn” chuyên dụng mà một trung tâm dữ liệu có thể thiết lập giữa các GPU cho các lần huấn luyện. Nhưng như một mặc định, chuyển mạch gói đã thắng ở mọi nơi đã được thử.

Bài viết ARPANET mở đầu với sơ đồ bốn nút. Sơ đồ đó chỉ thú vị nếu bạn hiểu các IMP giữa các nút đang làm gì. Chúng đang di chuyển các gói — tiêu đề chúng đọc, tải trọng chúng bỏ qua — và lựa chọn không có gì đặc biệt đó là lý do một mạng được thiết kế cho mười hai máy tính giờ chạy cho mười tỷ.