Tìm hiểu về DNS round robin
(blog.hyperknot.com)- Người vận hành OpenFreeMap đã gom nhiều VPS ở các khu vực khác nhau vào các bản ghi A record của cùng một subdomain để cấu hình DNS round robin, rồi thử nghiệm xem trình duyệt và Cloudflare thực sự chọn máy chủ nào
- Cách này có thể kỳ vọng phân tán tải và né tránh sự cố mà không cần load balancer riêng, nhưng kết quả thực tế phụ thuộc rất nhiều vào cách client sắp xếp địa chỉ và thử lại
- Khi thử nghiệm với 3 VPS tại Mỹ, châu Âu và Singapore, Chrome và Firefox có xu hướng cố định vào một máy chủ ngẫu nhiên lúc khởi động, còn Safari và curl thì hội tụ về máy chủ EU gần hơn sau các yêu cầu lặp lại
- Khi một số máy chủ bị offline, trình duyệt và curl chuyển nhanh sang máy chủ thay thế, nhưng các yêu cầu đi qua proxy Cloudflare có thể tiếp tục dùng origin đã gán theo IP client và gây ra lỗi 521
- Nếu Cloudflare không chọn đúng origin đang offline hoặc máy chủ có độ trễ thấp hơn, việc phân tán dựa trên DNS round robin có thể khiến người dùng kết nối tới máy chủ chậm bất kể vị trí thực tế của họ
Ý tưởng cơ bản của DNS round robin
- Với website chạy trên VPS thông thường, bạn chỉ cần thêm một A record tại nhà cung cấp DNS để đưa lưu lượng đến một IP cụ thể
- DNS round robin là cách chỉ định nhiều IP máy chủ cho cùng một subdomain
- Ví dụ là cấu hình nhiều A record cho
rr-direct.hyperknot.comvàrr-cf.hyperknot.com
- Ví dụ là cấu hình nhiều A record cho
- Với cấu hình này, có thể kỳ vọng chia tải sang nhiều máy chủ và tránh các máy chủ đang offline
- Trên hầu hết nhà cung cấp DNS, có thể thiết lập mà không cần load balancer riêng, nên đây là cách tiếp cận đơn giản và gần như miễn phí
- Tính năng cân bằng tải của các dịch vụ như Cloudflare có thể tốn kém đáng kể
Client có thể chọn máy chủ theo tiêu chí nào
- Các tiêu chuẩn liên quan gồm RFC 8305 Happy Eyeballs và RFC 6724
- Phần sắp xếp địa chỉ của RFC 8305 giải thích rằng nếu client có trạng thái lưu lại lịch sử thời gian khứ hồi ước tính (RTT) của từng đường đi địa chỉ, thì nên bổ sung quy tắc chọn địa chỉ đích ưu tiên địa chỉ có RTT thấp hơn
- Người thử nghiệm hiểu điều này theo cách sau
- Kiểm tra máy chủ đang online hay offline
- Sắp xếp các máy chủ online theo thời gian ping
Cấu hình thử nghiệm
- Tạo VPS ở 3 khu vực trên thế giới
- Mỹ
- Châu Âu
- Singapore
- Trên Cloudflare, cấu hình 3 A record được proxy và 3 A record không được proxy
- Mỗi máy chủ dùng nginx để cung cấp cùng một cấu trúc phản hồi
- Mọi yêu cầu đường dẫn đều được rewrite thành
color.png /servertrả về/etc/hostnamedưới dạngtext/plain
- Mọi yêu cầu đường dẫn đều được rewrite thành
color.pnglà tệp PNG 1px với màu khác nhau cho từng máy chủ- US: xanh lá
- EU: xanh dương
- SG: đỏ
- Tên host được phân biệt là
test-eu,test-us,test-sg - Vì địa điểm thử nghiệm là châu Âu, hành vi mong đợi là máy chủ EU gần nhất sẽ được chọn
- Trang thử nghiệm HTML hiển thị lưới 10x10 với các ảnh ngẫu nhiên để trực quan hóa kết quả chọn máy chủ
Hành vi của từng client khi mọi máy chủ đều online
- Chrome có xu hướng chọn một vị trí khá ngẫu nhiên trong số nhiều vị trí, rồi bám vào máy chủ đã chọn
- Sau vài giờ, nó sẽ đánh giá lại lựa chọn
- Trong thử nghiệm, có lúc nó bị cố định vào máy chủ Singapore chậm nhất suốt vài giờ
- Khi không dùng HTTP/2, đôi lúc nó chọn ngẫu nhiên giữa hai máy chủ và tạo ra mẫu lặp
- Firefox cũng hoạt động tương tự Chrome
- Chọn một vị trí ngẫu nhiên khi khởi động
- Nếu khởi động lại trình duyệt, nó có thể chọn một vị trí ngẫu nhiên khác
- Safari luôn chọn đúng máy chủ gần nhất
- Kể cả khi máy chủ tạm thời offline rồi hoạt động lại, chỉ cần tải lại vài lần là nó lại tìm về máy chủ EU
- curl cũng tự điều chỉnh về máy chủ gần hơn
- Lần chạy đầu có thể chưa vậy, nhưng nếu chạy lệnh hai lần thì luôn chuyển sang máy chủ gần nhất
- Trong ví dụ, yêu cầu đầu là
test-us, còn yêu cầu sau đổi thànhtest-eu
Hành vi khi đi qua proxy Cloudflare
- Cloudflare chọn một vị trí ngẫu nhiên dựa trên IP client rồi tiếp tục dùng cùng vị trí đó
- Hành vi quan sát được tương tự
client_ip_hash modulo server_num - Với IP ở nhà, dù thao tác thế nào Cloudflare cũng kết nối tới máy chủ Mỹ
- Kết quả
curl https://rr-cf.hyperknot.com/servertrả vềtest-us
- Kết quả
- Với hotspot di động, nó luôn kết nối tới máy chủ EU
- Khi chạy cùng lệnh curl từ nhiều VPS, mỗi VPS kết nối tới một vị trí ngẫu nhiên trên thế giới nhưng luôn dùng cùng một máy chủ
- Kết quả ví dụ là
test-sg
- Kết quả ví dụ là
Khác biệt khi một số máy chủ offline
- Đã kiểm tra hành vi sau khi dừng nginx trên máy chủ Mỹ bằng
service nginx stop - Chrome, Firefox, Safari và curl đều phát hiện máy chủ offline và chọn máy chủ khác
- Ngay cả khi tắt máy chủ trong lúc đang tải, kết nối thay thế vẫn hoạt động đủ nhanh để tự điều chỉnh trong chưa đến 1 giây
- Cloudflare không phát hiện được máy chủ offline
- Với một IP client, nó tiếp tục truy cập máy chủ đã chọn ban đầu bất kể máy chủ đó có online hay không
- Nếu máy chủ đó offline, người dùng sẽ nhận lỗi
- Kết quả curl là
error code: 521
Câu hỏi và giới hạn với Cloudflare
- Tác giả cho rằng việc Cloudflare không phát hiện origin offline rất có thể là một bug của mạng này
- Dựa trên tài liệu zero downtime failover của Cloudflare, tác giả cho rằng nó lẽ ra phải hoạt động như trình duyệt và curl
- Tối thiểu thì các máy chủ offline phải được phát hiện
- Nếu có thể chọn máy chủ có độ trễ thấp nhất như Safari thì càng tốt
- Với hành vi hiện tại, nếu có 1 máy chủ ở Mỹ và 1 máy chủ ở New Zealand, 50% người dùng Mỹ có thể nhận phản hồi từ máy chủ New Zealand
- Người dùng Safari có thể chậm hơn khi dùng Cloudflare so với không dùng Cloudflare
- Trong thảo luận trên HN, CEO và CTO của Cloudflare đã trả lời
- Tác giả cũng hỏi liệu có nền tảng serverless nào hỗ trợ HTTPS và DNS round robin mà không tốn chi phí cho 3 VPS toàn cầu để tiếp tục duy trì thử nghiệm hay không
1 bình luận
Ý kiến Hacker News
Ừm, tôi đã nhờ nhóm DNS có thẩm quyền giải thích chuyện gì đang xảy ra ở đây
Khi có câu trả lời chắc chắn, tôi sẽ báo lại trên HN. Đã vài năm rồi tôi chưa nhìn vào đoạn mã đó, và trong thời gian ấy rất nhiều người đã tiếp tục chỉnh sửa nó :-)
Phỏng đoán của tôi là nó có liên quan đến hành vi cố giữ độ ưu tiên giữa IP của client và máy chủ backend, như tác giả có nhắc trong bài blog. Câu hỏi cốt lõi là: “khi máy chủ backend bị down thì có nên phá vỡ độ ưu tiên đó không”, và nếu biết thêm tôi sẽ trả lời dưới bình luận của mình
Một trong những cách giải ban đầu cho vấn đề này là bản ghi DNS SRV. Nó giống bản ghi MX, nhưng được định hướng để áp dụng cho mọi dịch vụ chứ không chỉ email
Với MX và SRV, client có thể được chỉ định danh sách máy chủ cần thử cùng thứ tự ưu tiên, và SRV còn có tham số
weightđể cân bằng tải. Nhưng trên thực tế, SRV được quy định chỉ dùng khi tiêu chuẩn của giao thức tương ứng nêu rõ việc dùng SRV, nhằm tránh cuộc chiến chính trị về việc chặn ngang gần như mọi giao thức chuẩn và buộc mọi client phải kiểm tra SRV. Vì thế về mặt kỹ thuật, client HTTP không thể dùng SRV. Sau này khi xây dựng HTTP/2 và các tiêu chuẩn HTTP tiếp theo, họ cũng không thể quy định SRV cho giao thức HTTP mới vì những lập luận thiếu thuyết phục từ Google và các bên khác. SRV về cơ bản đã chết trong phát triển mới, và có vẻ chỉ còn được dùng trong một số tiêu chuẩn cũGiải pháp cân bằng tải mới có vẻ là bản ghi DNS HTTPS và SVCB. Theo hiểu biết của tôi, nó được chuẩn hóa bởi những người muốn đưa thêm tham số vào DNS để có thể bắt đầu bắt tay TLS 1.3 sớm hơn và giảm số vòng khứ hồi. Kiểu bản ghi SVCB giống HTTPS nhưng là dạng tổng quát hóa như SRV. HTTPS và SVCB có tham số ưu tiên như SRV và MX, nhưng không có tham số
weightcủa SRV. Tiêu chuẩn đã được công bố và có vẻ một số trình duyệt đã hỗ trợ, nhưng chưa phải tất cả đều bật nó. Cần chờ xem trong tương lai gần các trình duyệt thực sự sẽ làm gìKhông cần đến mánh CNAME flattening vốn có thể gây ra vấn đề định tuyến trong các CDN dùng GeoDNS cùng với hoặc thay cho anycast. Nếu bạn từng thấy nền tảng nào đó khuyên dùng subdomain
wwwthay vì apex domain, thì đây là lý do, và đó cũng là một trong các lý do Akamai thúc đẩy việc chuẩn hóa bản ghi HTTPS vì họ dùng GeoDNSViệc thiếu những bản ghi như vậy đặc biệt đau vì mọi người thường muốn host website ngay tại apex của domain. Dù vậy, nếu không thể dựa vào DNSSEC thì việc dùng bản ghi kiểu MX một cách an toàn có thể khá khó
Cân bằng tải bằng DNS có rất nhiều trường hợp biên cực kỳ lằng nhằng. Tôi từng xử lý tình huống client Go HTTP/2 dùng round-robin DNS và đã gặp vấn đề
Client Go HTTP/2 sẽ tiếp tục tái sử dụng máy chủ đầu tiên mà nó kết nối được và không phân giải DNS lại. Vì vậy, nếu thêm máy chủ mới vào pool thì client có thể không bao giờ phát hiện ra
Trường hợp bệnh lý đặc biệt là khi tất cả backend đều down rồi backend đầu tiên quay lại hoạt động: mọi client sẽ bị ghim vào máy chủ đó và không dịch chuyển đi đâu. Dù các máy chủ khác có hoạt động trở lại thì cũng hầu như không có client mới kết nối tới, vì tất cả đã nối với máy chủ đầu tiên rồi
grpc-gocũng gặp vấn đề tương tự. Trình phân giải DNS của gRPC chỉ phân giải lại khi kết nối tới backend bị đứt. Vì vậy các client gRPC có thể dồn về một host rồi cứ ở lì tại đó. Có đề xuất cấu hìnhMAX_CONNECTION_AGEở phía server để định kỳ ngắt client sau một khoảng thời gian, buộc client phải phân giải DNS lạiTôi ước gì có một giải pháp chuẩn tốt hơn cho service discovery. Cuối cùng có vẻ điều tốt nhất có thể làm là triển khai bộ cân bằng tải theo từng request dựa trên IP ảo và để bộ cân bằng tải tự thực hiện health check. Nhưng ngay cả vậy thì cũng chỉ là đẩy vấn đề sang hệ thống triển khai IP ảo mà thôi. Có vẻ người ta cho rằng hệ thống định tuyến tương đối tĩnh hơn backend, và đó là điểm mang lại lợi ích
Tôi tò mò trên bare metal người ta làm việc này như thế nào. Tôi biết AWS/GCP và các bên tương tự có bộ cân bằng tải nội bộ, nhưng muốn biết bí quyết để hiện thực hóa nó là gì. Nếu có bài blog hay whitepaper liên quan thì càng tốt
Bài viết nói “nếu một máy chủ offline thì sao? Giả sử ta dừng máy chủ ở Mỹ:
service nginx stop”, nhưng không nên kiểm thử theo cách đóClient sẽ thấy kết nối bị từ chối và chuyển sang IP tiếp theo. Nhưng trong thực tế, máy chủ có thể hoàn toàn không phản hồi, hoặc chấp nhận kết nối rồi im lặng
Khi đó bạn sẽ phải phụ thuộc vào timeout phía client, và round-robin DNS vốn nhằm tăng độ tin cậy bỗng trở nên kém hấp dẫn hơn nhiều
Việc dừng dịch vụ là tình huống có kế hoạch, và trong trường hợp đó có thể xử lý bằng cách cập nhật DNS trước
SIG_STOPhoặcDROPcủaip/nftableslà bài kiểm thử thực tế hơn nhiều“Như bạn thấy, mọi client đều phát hiện điều này đúng cách và chọn máy chủ thay thế” chính là phần cốt lõi lộn xộn. Độ tin cậy được quyết định ở phía client
Ví dụ,
systemd-resolvedtừng cho rằng mình hoạt động đúng về mặt kỹ thuật nhất có thể nên luôn trả về địa chỉ IP thấp nhất. Lý lẽ là DNS round robin không được định nghĩa rõ ràng, nên việc luôn trả về IP thấp nhất cũng không hẳn là sai. Sau một đợt ồn ào thì điều này đã thay đổi, nhưng theo tôi biết thì Debian 11 đã bị trói vào hành vi đó, hoặc đã như vậy trong một thời gian dàiTôi cũng thường phải xử lý nhiều ứng dụng có hành vi retry rất tệ, hoặc hoàn toàn không có retry. Chúng hoạt động kiểu như “à, có một lần connection refused, hủy hết, thoát ra và đừng bao giờ thử lại nữa”. Thế là 20~30% tổng số request bốc hơi
Nếu không còn lựa chọn nào khác thì đây là một giải pháp có thể chấp nhận được. Như bài viết nói, nếu bạn có một HTTP client chất lượng tốt như trình duyệt với vài lần retry được cấu hình sẵn, thì DNS round robin có thể tạm ổn để thay cho việc tìm một load balancer thực sự có health check các kiểu, và có thể mang lại tỷ lệ thành công 100%
Nhưng DNS round robin không phải là load balancer, và load balancer thì tốt hơn
Chỗ tôi từng làm có một máy chủ DNS nội bộ với hàng trăm triệu record và TTL 60 giây, được dùng cho một hệ thống định tuyến nội bộ tùy biến để đưa các kết nối đến từ khách hàng vào đúng tài nguyên bên trong mạng. Nó thực sự rất tuyệt. Việc thay đổi định tuyến đơn giản như một bản cập nhật DDNS, và với
NOTIFYcó thể đẩy thay đổi ra tất cả máy chủ cấp dưới, nên độ trễ trung bình để áp dụng toàn bộ dưới 60 giây. Nhờ đó rất dễ xây thêm các công cụ phức tạp hơn, và chúng tôi cũng làm được một bảng điều khiển cho phép loại khỏi phục vụ chỉ bằng một nút bấm, từ một máy chủ đơn lẻ cho tới cả một trung tâm dữ liệuHệ thống đó chắc chắn vẫn có những góc cạnh thô ráp, nhưng với kiểu hệ thống như vậy thì nó nhanh, dễ quan sát và tương đối gần như chống đạn
Failover cũng vậy. Nếu một region bị sập, bạn muốn lưu lượng được phân bổ đều sang các region khác, hay muốn nó dồn vào region lân cận gần nhất tiếp theo? Nếu hành vi đó quan trọng thì bạn phải giữ quyền kiểm soát việc quản lý lưu lượng, chứ không nên giao cho người khác
Ngày nay có nhiều giải pháp khác để chọn từ rất lâu trước khi bạn thật sự rơi vào tình huống “không còn lựa chọn nào khác” đó
Nhân câu “có thể phân phối tải sang nhiều máy chủ và tự động phát hiện máy chủ nào đang offline để chọn máy chủ còn online”, xin bắt bẻ một chút một cách thận trọng về khả năng tự động phát hiện offline bằng DNS: round robin DNS ở trạng thái cơ bản chỉ thật sự đáng dùng cho cân bằng tải
Trừ khi bạn đưa logic đủ thông minh vào client, sẽ không có gì tự động xảy ra về mặt phát hiện tình trạng khả dụng. Phần mở đầu của bài có nhắc điều này ở mức nào đó, nhưng tôi phải đọc lại vài lần mới hiểu được ý. Nói công bằng thì cũng có thể là do khả năng đọc hiểu của tôi. Sau đó đọc phần còn lại của bài thì thấy toàn bộ đều nói về cái logic thông minh đó
Nếu record máy chủ 1/N mà trình duyệt chọn không dùng được, sẽ không có cơ chế tự phục hồi hay retry tự động nào diễn ra ở cấp giao thức
Tiện thể, đừng quên “một điều thú vị liên quan”: hành vi DNS TTL của Java [1] và
.equals()[2][1] https://stackoverflow.com/questions/1256556/how-to-make-java...
[2] https://news.ycombinator.com/item?id=21765788 (5 năm trước, 168 bình luận)
Dĩ nhiên vẫn có client bỏ qua TTL, nhưng khá hiếm
Nếu máy chủ ngừng hoạt động, các địa chỉ IP đã được phân tán và lưu trong bộ nhớ đệm trên toàn thế giới vẫn còn đó, và không thể ngăn mọi người truy cập vào địa chỉ đó
https://www.cloudflare.com/learning/dns/glossary/round-robin...
Cân bằng tải cũng có chi phí, và còn có vấn đề là bộ cân bằng tải làm hỏng kết nối một cách tinh vi hoặc trắng trợn. Ở một số nhà cung cấp, đã từng có lúc độ sẵn sàng của bộ cân bằng tải còn tệ hơn cả máy chủ của chúng tôi
Nếu kiểm soát được client, thì cách gọi API DNS của nền tảng để nhận danh sách IP rồi trộn và xoay vòng hợp lý cũng là phương án hợp lý. Sẽ còn tốt hơn nếu có thể đưa sẵn vài IP được gán ổn định vào binary của client để phòng khi DNS gặp sự cố. Nhưng DNS thường không hỏng, và nó phù hợp để dùng cho các thay đổi vận hành mà không cần triển khai cấu hình mới hay binary mới mỗi khi cập nhật cụm
Nếu client là trình duyệt thì hành vi mặc định nhìn chung là ổn. Thông thường nó dùng IP theo thứ tự nên có thể thành vấn đề [1], nhưng ngoài ra hành vi retry là tốt. Nếu bị từ chối kết nối thì nó lập tức thử IP khác, còn nếu bị timeout thì ít nhất cũng thử thêm vài IP khác. Dù không lý tưởng, tôi vẫn sẽ dùng bộ cân bằng tải cho trình duyệt, và nếu có thể thì ít nhất là cho lần tải trang ban đầu. Với WebSocket các loại, có thể dùng DNS round robin cùng logic client JS thông minh ở mức nào đó. Dù vậy, vẫn có thể dùng DNS round robin cho toàn bộ website
Nếu client không phải trình duyệt và tôi cũng không kiểm soát được nó, thì chỉ còn biết cầu may
Thỉnh thoảng phải chấp nhận 100% rằng ai đó khi tạo một bộ phân giải DNS có bộ nhớ đệm đã diễn giải trường TTL theo đơn vị ngày thay vì giây. Các client nằm sau những bộ phân giải như vậy sẽ gặp vấn đề khi cập nhật DNS. Nhưng nếu bộ cân bằng tải nằm sau một tên DNS và đến lúc phải thay đổi địa chỉ đó, thì khi ấy bạn cũng sẽ gặp đúng vấn đề đó, chỉ là lúc ấy còn chưa có kinh nghiệm xử lý
[1] Một RFC nào đó đề xuất API của OS nên sắp xếp các phản hồi theo mức độ khớp tiền tố. Điều đó có lý nếu tiền tố IP có tính phân cấp và là chỉ dấu đại diện để chọn máy chủ có khoảng cách mạng gần nhất. Nhưng trong thực tế, các
/24gần nhau về mặt số học thường lại không gần nhau trên mạng. Nếu địa chỉ máy chủ phân tán khá rộng, bạn có thể thấy lưu lượng từ một số IP client dồn về các IP máy chủ gần nhau về mặt số họcTất nhiên, ai đó có thể cấu hình DNS cục bộ sai hoặc buộc phải dùng client kém chất lượng. Hoặc chấp nhận sự cố đối với những người có cấu hình hỏng, hoặc phải gán lại IP sang máy chủ khác trong cùng datacenter
Xin chào. Tôi là CTO của Cloudflare. Chúng tôi đã triển khai thay đổi cho tất cả tài khoản miễn phí của Cloudflare để chúng hoạt động giống như tài khoản trả phí
Vấn đề được nói đến ở đây đã được sửa, và Zero Downtime Failover sẽ hoạt động với mọi loại tài khoản. Bạn có thể thử lại được không?
Cảm ơn vì đã tổng hợp điều này thành bài viết. Tôi rất vui vì có thể thay đổi hành vi này cho mọi người
Tôi cũng sẽ cập nhật bài viết cho phù hợp. Cảm ơn vì đã áp dụng cho cả tài khoản miễn phí, đây là kết quả tuyệt vời
Phiên bản remix đen tối của thứ này là fast flux hosting, và đó là cách nhiều nhà cung cấp bulletproof hosting sử dụng
https://unit42.paloaltonetworks.com/fast-flux-101/
Có lẽ nên nhắc rằng Zero Downtime Failover là tính năng dành cho gói Pro trở lên
Tôi nhớ trước đây, khi tài liệu về bảo vệ origin server còn được chia theo từng cấp gói, nó cũng được ghi như vậy. Vì thế hành vi hoặc việc retry có thể trông khác nhau