Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Web Development
Code

Tóm tắt về HTTP: Các kết nối HTTP

by
Difficulty:IntermediateLength:LongLanguages:
This post is part of a series called HTTP Succinctly.
HTTP Succinctly: HTTP Messages
HTTP Succinctly: HTTP Web Architecture

Vietnamese (Tiếng Việt) translation by Thai An (you can also view the original English article)

Trong bài viết trước chúng ta đã xem xét các thông điệp HTTP và các ví dụ của các câu lệnh và mã lệnh được chuyển từ máy khách đến máy chủ và ngược lại trong một tiến trình xử lý HTTP. Nhưng thông tin trong những thông điệp đó di chuyển qua mạng kết nối như thế nào? Khi nào thì các kết nối mạng được mở? Khi nào các kết nối kết thúc? Có vài câu hỏi sẽ được bài viết này trả lời trong lúc chúng ta xem xét HTTP từ một góc độ chi tiết. Nhưng trước tiên, chúng ta sẽ cần hiểu một vài khái niệm bên dưới HTTP.

Tìm hiểu nhanh về networking

Để hiểu được các kết nối HTTP chúng ta phải biết chút ít về hoạt động của các layer (các tầng của giao thức mạng) bên dưới HTTP. Các giao tiếp kết nối mang giống như các ứng dụng khác gồm có nhiều layer. Mỗi layer trong stack giao tiếp đảm trách một số lượng giới hạn các nhiệm vụ cụ thể.

Ví dụ, HTTP là điều mà chúng ta gọi là một tầng giao thức ứng dụng bởi vì nó cho phép 2 ứng dụng giao tiếp thông qua một mạng kết nối. Phổ biến nhất là một các ứng dụng là trình duyệt web, và ứng dụng còn lại là một máy chủ web như IIS hoặc Apache. Chúng ta đã hiểu các thông điệp HTTP cho phép trình duyệt yêu cầu các tài nguyên từ máy chủ như thế nào. Nhưng các đặc tả HTTP không đề cập gì đến cách những thông điệp thực sự đi qua mạng kết nối và tiếp cận máy chủ ra sao - đó là việc của những giao thức ở tầng bên dưới. Một thông điệp từ một trình duyệt phải băng qua một loạt các layer, và khi tiến đến máy chủ web nó sẽ đi qua một loạt các layer để đi đến phần xử lý của dịch vụ web.

Figure 4: Protocol layers
Các layer của giao thức

Layer nằm dưới HTTP là giao thức transport layer protocol. Hầu hết lượng truy cập HTTP chuyển tiếp qua TCP (viết tắt của Transmission Control Protocol), mặc dù HTTP không bắt buộc điều này. Khi người dùng gõ một URL vào trình duyệt, trước tiên trình duyệt trích xuất tên host của URL (mã số port nếu có), và mở một TCP socket bằng cách xác định địa chỉ máy chủ (bắt nguồn từ tên host) và port (mặc định là 80).

Một khi ứng dụng có một socket đang mở, thì nó có thể bắt đầu ghi dữ liệu vào socket. Điều duy nhất trình duyệt cần quan tâm là ghi một thông điệp yêu cầu HTTP có định dạng đúng vào socket. Tầng TCP nhận dữ liệu và bảo đảm rằng thông điệp gửi đến máy chủ không bị mất đi hoặc trùng lặp. TCP sẽ tự động gửi lại bất kỳ thông tin nào bị mất trong lúc chuyên đi, và đây là lý do tại sao TCP được gọi là một giao thức đáng tin cậy. Ngoài việc phát hiện lỗi, TCP cũng cung cấp điều khiển luồng. Thuật toán điều khiển luống trong TCP bảo đảm bên gửi không chuyển dữ liệu đi quá nhanh cho bên nhận xử lý. Việc kiểm soát luồng rất quan trọng trong thế giới có thiết bị và mạng kết nối đa dạng.

Ngắn gọn mà nói TCP cung cấp những dịch vụ chủ yếu để truyền tải thành công các thông điệp HTTP, nhưng nó thực hiện điều đó minh bạch vì vậy đa số các ứng dụng không phải lo lắng về TCP. Như hình minh hoạ trước đó, TCP chỉ là layer đầu tiên bên dưới HTTP. Sau TCP tại transport layer (tầng giao vận) xuất hiện IP gọi là giao thức network layer (tầng mạng kết nối).

IP là cách gọi vắn tắt của Internet Protocol (giao thức mạng). Trong khi TCP đảm trách việc phát hiện lỗi, kiểm soát luồng, và độ tin cậy tổng thể, thì IP có nhiệm vụ nhận các thông tin và truyền đi thông qua các switch (thiết bị chuyển mạch), router (thiết bị định tuyến), gateway (thiết bị chuyển đổi tín hiệu), repeater (thiết bị mở rộng sóng) và những thiết bị khác có vai trò truyền tải thông tin giữa các mạng lưới và khắp thế giới. IP nỗ lực truyền dữ liệu đến mục tiêu (nhưng không bảo đảm việc truyền tải - đó là việc của TCP). IP yêu cầu máy tính có một địa chỉ (một địa chỉ IP thật sự, ví dụ như 208.192.32.40). IP cũng đảm nhận việc phân chia thành những packet (dữ liệu nhỏ hơn) thường được gọi là datagram, và đôi khi phân mảnh và tái hợp những packet để chúng được tối ưu cho một phân khúc mạng riêng biệt.

Đến giờ mọi thứ chúng ta đề cập qua đều xảy ra bên trong một máy tính, nhưng sau cùng những IP packet này phải được truyền qua một dây mạng, một cáp quang, một mạng không dây hoặc kết nối vệ tinh. Đây là nhiệm vụ của data link layer (tầng liên kết dữ liệu). Chọn lựa phổ biến của công nghệ ở giai đoạn này là Ethernet. Ở cấp độ này, các gói dữ liệu trở thành các frame, những giao thức ở cấp độ thấp như Ethernet tập trung vào 1s, 0s và các tín hiệu điện tử.

Sau cùng các tín hiệu tiến đến máy chủ và truyền qua card mạng đến phần xử lý được định sẵn. Data link layer phân phối các gói dữ liệu đến tầng IP, tầng này truyền dữ liệu đến TCP, sau đó dữ liệu được tổng hợp thành thông điệp HTTP nguyên bản được máy khách gửi đến và thông tin này được máy chủ web xử lý. Đây là một công việc được thiết kế tuyệt vời và tuân theo những tiêu chuẩn.


Yêu cầu HTTP nhanh với các socket và C#

Nếu bạn thắc mắc làm thế nào để viết một ứng dụng gửi các yêu cầu HTTP, vậy mã C# sau đây là ví dụ đơn giản để giải thích cho bạn. Code này không xử lý phần lỗi, và cố gắng viết bất kỳ hồi đáp nào từ máy chủ vào console (vì thế bạn sẽ cần yêu cầu một tài nguyên văn bản), nhưng nó hoạt động tốt với những yêu cầu cơ bản. Bạn có thể tìm thấy bản copy của ví dụ mẫu này tại https://bitbucket.org/syncfusion/http-succinctly. Tên ví dụ mẫu là sockets-sample.

Chú ý cách chương trình tìm kiếm địa chỉ máy chủ (sử dụng Dns.GetHostEntry). và xây dựng một thông điệp HTTP đúng với toán tử GET và header HOST. Phần kết nối khá dễ, bởi vì việc triển khai socket và TCP đã đảm trách phần lớn công việc. Ví dụ TCP biết cách để quản lý nhiều kết nối đến cùng một máy chủ (tất cả sẽ dùng những số port khác nhau). Vì thế hai yêu cầu chưa được giải quyết đến cùng một máy chủ sẽ không bị nhầm lẫn và nhận nhầm dữ liệu của nhau.


Kết nối mạng và Wireshark

Nếu bạn muốn nhận diện TCP và IP, bạn có thể cài đặt phần mềm miễn phí Wireshark (hỗ trợ OSX và Windows tại wireshark.org). Wireshart là một chương trình phân tích mạng có thể hiển thị chi tiết thông tin đang truyền tải qua các interface mạng kết nối của bạn. Với Wireshark bạn có thể theo dõi các giao tiếp (handshakes) của TCP, đó là các thông điệp TCP cần có để thiết lập kết nối giữa máy chủ và máy khách trước khi một thông điệp HTTP thực sự bắt đầu được gửi đi. Bạn cũng có thể xem các header của TCP và IP (20 bytes cho mỗi header) cho từng thông điệp. Hình minh hoạ dưới đây trình bày hai bước sau cùng của giao tiếp, theo sau là một yêu cầu GET và một điều hướng 304.

Figure 5: Using Wireshark
Sử dụng Wireshark

Bạn có thể dùng Wireshart để xem khi nào các kết nối HTTP được thiết lập và đóng lại. Phần quan trọng không phải là các giao tiếp và TCP hoạt động ra sao ở cấp thấp nhất, mà là HTTP hầu như dựa hoàn toàn vào TCP để quản lý tất cả phần việc quan trọng và TCP gây nên một số hao tổn tài nguyên, giống như các giao tiếp. Do đó, các đặc điểm hiệu suất của HTTP cũng dựa vào đặc điểm hiệu năng của TCP, và đây là chủ đề của phần kế tiếp.


HTTP, TCP và sự phát triển của Web

Những ngày đầu của web, đa số các tài nguyên là văn bản. Bạn có thể yêu cầu một tài liệu từ một máy chủ, tắt mạng và đọc trong 5 phút, sau đó yêu cầu một tài liệu khác. Thế giới thật đơn giản.

Với web của ngày nay, đa số trang web cần nhiều tài nguyên để render toàn diện. Mỗi trang trong một ứng dụng có một hoặc nhiều hình ảnh, các file JavaScript, và các file CSS. Không lạ khi một yêu cầu đầu tiên của trang chủ làm phát sinh thêm 30 hoặc 50 yêu cầu để lấy tất cả tài nguyên cần có của trang.

Trước đây thật đơn giản để trình duyệt thiết lập một kết nối với máy chủ, gửi một yêu cầu, nhận hồi đáp và đóng kết nối lại. Nếu các trình duyệt web ngày này mở một kết nối mỗi lần, và đợi từng tài nguyên được tải về đầy đủ trước khi thực hiện lần tải tiếp theo, thì web sẽ rất chậm. Internet sẽ cực kỳ chậm. Các tín hiệu phải truyền đi qua quãng đường dài và nhiều thiết bị phần cứng khác nhau. Cũng sẽ hao tổn tài nguyên khi thiết lập kết nối TCP. Như ta thấy trong ảnh chụp của Wireshark, có 3 bước giao tiếp cần hoàn tất trước khi một giao dịch HTTP có thể tiến hành.

SỰ phát triển từ những tài liệu đơn giản đến các trang web phức tạp đã đòi hỏi một số sáng kiến trong thực hành của HTTP.


Các kết nối song song

Đa số người dùng (tức là trình duyệt) sẽ không gửi từng yêu cầu đơn lẻ. Thay vào đó, họ mở nhiều kết nối song song đến máy chủ. Ví dụ, khi tải về HTML của trang web, trình duyệt có thể thấy 2 thẻ <img> trong trang, nên trình duyệt sẽ mở 2 kết nối song song để đồng thời tải về cả 2 hình ảnh đó. Số kết nối song song tuỳ thuộc vào người dùng và cấu hình của người dùng.

Trong một thời gian dài chúng ta xem 2 là con số kết nối song song tối đa một trình duyệt có thể tạo ra. 2 là số lượng kết nối tối đa vì trong nhiều năm, đa số trình duyệt Internet Explorer (IE) chỉ cho phép đồng thời 2 kết nối đến một host. IE chỉ tuân thủ các quy tắc được đặt ra trong đặc tả HTTP 1.1:

Một máy khách KHÔNG NÊN duy trì hơn 2 kết nối với máy chủ bất kỳ hoặc proxy.

Để gia tăng số lượng kết nối song song, nhiều website áp dụng một số mánh khoé. Ví dụ, giới hạn trong 2 kết nối cho mỗi host, nghĩa là một trình duyệt như IE 6 sẽ thoải mái thực hiện 2 kết nối song song đến www.odetocode.com, 2 kết nối song song đến images.odetocode.com. Bằng cách lưu hình ảnh trên một máy chủ khác, các website có thể tăng lượng tải song song và làm trang của họ nạp nhanh hơn (thậm chí nếu DNS record được thiết lập để trỏ đến 4 yêu cầu của cùng một máy chủ, bởi vì giới hạn 2 kết nối áp dụng cho mỗi host, không phải cho địa chỉ IP).

Ngày nay mọi thứ đã khác. Đa số người dùng sử dụng những phỏng đoán khác nhau khi quyết định có bao nhiêu kết nối song song cần thiết lập. Ví dụ, Internet Explorer 8 sẽ mở ra đồng thời 6 kết nối.

Câu hỏi thực sự là: có bao nhiêu kết nối thì gọi là quá nhiều? Các kết nối sẽ tuân thủ law of diminishing returns - quy luật hiệu suất giảm dần. Quá nhiều kết nối có thể tràn ngập và tắt nghẽn mạng, đặc biệt khi các thiết bị di động hoặc các mạng kết nối không đáng tin tham gia vào. Do đó, qua nhiều kết nối sẽ tác động đến hiệu năng. Một máy chủ cũng chỉ có thể nhận số lượng có hạn các kết nối, nên nếu 100,000 trình duyệt đồng thời tạo ra 100 kết nối cho một máy chủ, thì những điều tệ hại sẽ xảy ra. Dù vậy việc có nhiều kết nối cho mỗi người dùng vẫn tốt hơn là tuần tự tải tất cả mọi thứ.

Thât may mắn các kết nối song song không phải là cách tối ưu hiệu năng duy nhất.


Các kết nối bền vững

Những ngày ban đầu của web, một người dùng sẽ mở và đóng một kết nối sau mỗi yêu cầu được gửi đến một máy chủ. Cách triển khai này phù hợp với ý tưởng của HTTP trở thành một giao thức stateless (phi trạng thái). Khi số lượng yêu cầu của mỗi trang tăng lên, thì tài nguyên hao tốn phát sinh bởi TCP handshake (giao tiếp) và cấu trúc dữ liệu in-memory yêu cầu để thiết lập cho từng TCP socket cũng tăng lên. Để giảm hao tổn tài nguyên này và nâng cao hiệu suất, đặc tả HTTP 1.1 đề xuất máy khách và máy chủ nên triển khai kết nối bền vững, và biến loại kết nối này thành kiểu kết nối mặc định.

Một kết nối bền vừng vẫn mở sau khi một giao dịch yêu cầu-hồi đáp hoàn tất. Chế độ này mang lại cho người dùng một socket đã được mở sẵn, nó có thể tiếp tục gửi yêu cầu đến máy chủ mà không hao tốn thêm tài nguyên để mở một kết nối khác. Những kết nối bền vững cũng tránh chiến lược khởi động chậm góp phần tạo nên việc tắc nghẽn, làm cho kết nối bền vững dần dần hoạt động tốt hơn. Ngắn gọn thì những kết nối bền vững giảm thiểu việc sử dụng memory, CPU, vấn đề nghẽn mạng, giảm thời gian trễ, và nhìn chung cải thiện thời gian hồi đáp của một trang web. Nhưng trong cuộc sống mọi thứ đều có nhược điểm.

Như đã đề cập, một máy chủ chỉ có thể hỗ trợ số lượng có hạn những kết nối incoming. Số lượng chính xác tuỳ vào bộ nhớ đang có, cấu hình của phần mềm máy chủ, hiệu suất của ứng dụng, và nhiều biến số khác. Thật khó để có con số chính xác nhưng nói chung nếu bạn bàn về việc hỗ trợ hàng ngàn kết nối cùng lúc, thì bạn sẽ phải bắt đầu thử nghiệm xem liệu máy chủ có hỗ trợ được không. Thực tế, nhiều máy chủ được cấu hình để giới hạn số lượng kết nối đồng thời khá xa so với con số khiến máy chủ phải ngắt kết nối. Việc cấu hình là một phương pháp bảo mật để ngăn chặn các cuộc tấn công từ chối dịch vụ (DoS). Tương tối dễ để tạo một chương trình nhằm mở hàng ngàn kết nối bền vững đến một máy chủ và làm máy chủ đó không thể phản hồi cho người dùng thực sự. Những kết nối bền vững sẽ tối ưu hiệu suất nhưng cũng dễ bị tấn công.

Suy nghĩ về những vấn đề của việc dễ bị tấn công, chúng tôi cũng tự hỏi nên duy trì mở một kết nối bền vững trong bao lâu. Trong một thế giới mở rộng không ngừng, các kết nối có thể duy trì trạng thái mở chừng nào chương trình từ phía người dùng vẫn chạy. Nhưng vì một máy chủ hỗ trợ số lượng giới hạn các kết nối, đa số máy chủ được cấu hình để ngắt kết nối bền vững nếu ở trạng thái idle (không có hoạt động) trong một khoảng thời gian (ví dụ như 5 giây với Apache). Người dùng cũng có thể đóng kết nối sau một khoảng thời gian idle. Để xem các kết nối đã bị đóng ta dùng một chương trình phân tích mạng lưới tên là Wireshark.

Ngoài việc nhanh chóng đóng các kết nối bền vững, hầu hết các phần mềm máy chủ web có thể được cấu hình để tắt các kết nối bền vững. Đây là việc phổ biến với các máy chủ chia sẻ. Máy chủ chia sẻ hy sinh hiệu suất để cho phép nhiều kết nối nhất có thể. Vì những kết nối bền vững là hình thức mặc định với HTTP 1.1, một máy chủ tuyệt không yêu cầu một Connection header trong mỗi lần phản hồi HTTP. Code dưới đây là một ví dụ.

Header Connection:close báo hiệu đến người dùng rằng kết nối sẽ không bền vững và sẽ bị đóng lại khi có thể. Người dùng không được phép gửi yêu cầu thứ 2 trên cùng một kết nối.


Các kết nối pipelined

Kết nối song song và kết nối ổn định được sử dụng rộng rãi và hỗ trợ bởi máy khách và máy chủ. Đặc tả HTTP cũng cho phép kết nối pipelined, loại này không được hỗ trợ rộng rãi ở máy chủ lẫn máy khách. Trong kết nối pipelined, một người dùng có thể gửi nhiều yêu cầu HTTP trên một kết nối trước khi nhận được phản hồi đầu tiên. Pipeline cho phép chia nhỏ các yêu cầu thành những packet và giảm thời gian chờ, nhưng không được ứng dụng rộng rãi như kết nối song song và kết nối bền vững.


Chúng ta đang ở đâu?

Trong bài viết này, chúng ta đã xem qua các kết nối HTTP và thảo luận vài việc tối ưu hoá hiệu suất có thể thực hiện qua những đặc điểm kỹ thuật của HTTP. Giờ chúng ta đào sâu vào những thông điệp HTTP và thậm chí đã kiểm tra các kết nối và hỗ trợ của TCP bên dưới giao thức, chúng ta sẽ trở lại và xem xét Internet từ một góc nhịn rộng hơn.

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.