Steven
Steven6 phút đọc

Khi tường lửa chặn WebSocket, phiên âm thời gian thực sẽ ra sao

Mạng doanh nghiệp thích cho HTTPS đi qua nhưng âm thầm giết chết bước nâng cấp WebSocket. Điều đó lặng lẽ làm hỏng phiên âm thời gian thực. GeekBye v2.0.8 tự động fall back sang một transport thuần HTTPS — và trong lúc làm ra nó, chúng tôi đào được một con bug có thể khiến cả tính năng trở nên vô dụng.

Phiên âm
Mạng
Kỹ thuật
GeekBye Releases
Khi tường lửa chặn WebSocket, phiên âm thời gian thực sẽ ra sao

Có một cách thất bại rất riêng và phát điên mà phiên âm thời gian thực gặp phải trên mạng doanh nghiệp. Wi-Fi của bạn vẫn ổn. HTTPS vẫn chạy — bạn mở được bất kỳ website nào. Vậy mà phiên âm trực tiếp thì cứ… không chịu khởi động, và chẳng có gì cho bạn biết vì sao.

Thủ phạm là một loại proxy doanh nghiệp cho lưu lượng HTTPS thông thường đi qua nhưng chặn bước nâng cấp WebSocket — cái bắt tay biến một kết nối HTTPS thành kênh hai chiều, bền vững mà phiên âm thời gian thực cần. Với proxy, một WebSocket trông như một đường hầm không được giám sát chui ra khỏi mạng, nên nó giết đi. Với bạn, phiên âm chỉ lặng lẽ hỏng.

GeekBye v2.0.8 đã thêm một fallback tự động cho đúng tình huống này — và việc xây nó lôi ra một con bug có thể khiến cả tính năng chẳng làm gì cả.

Vì sao là fallback, chứ không chỉ là thử lại

Mạng chập chờn thì chúng tôi đã xử lý. Nếu kết nối của bạn rớt giữa phiên, GeekBye kết nối lại có backoff và đệm âm thanh của bạn để không mất gì — đó là một tính năng riêng, được nói trong vì sao AI notetaker của bạn dừng khi Wi-Fi tệ.

Nhưng một WebSocket bị chặn không phải là một kết nối chập chờn. Thử lại cùng một WebSocket trước một proxy từ chối WebSocket thì lần nào cũng thất bại y như nhau, mãi mãi. Cách sửa duy nhất là một transport khác — một cái trông giống thứ HTTPS trơn mà proxy vốn đã cho phép.

Vậy nên v2.0.8 fall back sang một transport thuần HTTPS trên cùng một endpoint đã xác thực:

  • Chiều xuống (các đoạn phiên âm trả về cho bạn): server-sent events — một phản hồi HTTPS sống lâu mà proxy thấy như một lượt tải xuống dạng luồng bình thường.
  • Chiều lên (âm thanh của bạn gửi ra): các yêu cầu POST theo lô, mỗi cái mang một khối âm thanh kèm một số thứ tự để máy chủ ráp lại đúng thứ tự ngay cả khi mạng đảo lộn chúng.

Không có socket bền vững, không có gì trông như đường hầm — chỉ là các yêu cầu và phản hồi HTTPS. Nếu một proxy cho phép bạn dùng website, thì nó cho phép cái này.

Con bug suýt phát hành một tính năng đã chết

Đây mới là phần đáng đọc. Fallback lẽ ra phải kích hoạt khi kết nối WebSocket dùng cạn số lần thử với một chữ ký transport-bị-chặn — mọi lần thử đều thất bại ở bước nâng cấp, không có vấn đề xác thực hay hạn ngạch, ít nhất một lần bị từ chối theo kiểu proxy. Một proxy chặn WebSocket thường trả lời bước nâng cấp bằng một HTTP 403 Forbidden hoặc 407.

Vấn đề: mã kết nối của chúng tôi vốn đã có một quy tắc rằng một 403 nghĩa là lỗi xác thực nghiêm trọng — dừng lại, đưa nó ra cho người dùng, đừng thử lại. Điều này đúng ở gần như mọi nơi. Nhưng nó có nghĩa là cái 403 từ một proxy chặn — đúng cái tín hiệu lẽ ra phải kích hoạt fallback — lại bị ném ra như một lỗi nghiêm trọng trước khi logic fallback kịp chạy. Chỉ một cú rớt kết nối trần trụi (một lần đóng 1006) mới lọt xuống tới fallback. Thế nên tính năng lẽ ra sẽ chạy được cho trường hợp hiếm và âm thầm thất bại với mục tiêu chính thật sự của nó: cái proxy doanh nghiệp.

Chúng tôi bắt được nó khi đang gia cố bản phát hành, chứ không phải trong production. Cách sửa: một 403/407 ở chặng nâng cấp WebSocket giờ được coi là có thể phục hồi để vòng lặp kết nối dùng cạn rồi rơi vào fallback — trong khi một thất bại xác thực thật sự (vốn đến theo cách khác, sau khi nâng cấp đã thành công) vẫn thất bại nhanh, y hệt như trước. Một bài test hồi quy giờ ghim chặt sự phân biệt này: một 403 của proxy chặn phải fall back; một 403 xác thực thật thì không được.

Phần gia cố còn lại đi theo cùng một lối đa nghi: một timeout trên mọi POST chiều lên để một proxy nhận yêu cầu nhưng không bao giờ trả lời không thể làm nghẽn luồng âm thanh, và một bảo đảm rằng một vấn đề đăng nhập thật sự không bao giờ bị bộ máy fallback âm thầm che mất.

Chúng tôi đã kiểm thử với một proxy thù địch thật

Một tính năng mà toàn bộ mục đích tồn tại là sống sót qua các mạng thù địch thì không thể chỉ kiểm chứng bằng unit test — unit test không có proxy. Trước khi bật, chúng tôi cho chính ứng dụng thật chạy qua một reverse proxy cục bộ được cấu hình để làm đúng cái các proxy doanh nghiệp làm: chuyển tiếp HTTPS, từ chối nâng cấp WebSocket bằng một 403.

Dấu vết trong log chính là biên nhận: bốn lần thử WebSocket bị chặn, chữ ký dùng-cạn được nhận ra, cú chuyển tự động sang transport HTTPS, rồi một phiên phiên âm 96 giây khỏe mạnh trên thuần HTTPS — 66 đoạn phiên âm, không rớt cái nào. Chuyển đổi dự phòng chạy được là vì chúng tôi đã tận mắt xem nó chuyển đổi.

Ba bài học mang đi được

  1. "Nó chạy được trên Wi-Fi chập chờn" và "nó chạy được sau một proxy thù địch" là hai đảm bảo khác nhau. Một cái cần kết nối lại; cái kia cần một transport khác. Gộp chúng lại là bỏ mặc cả một nhóm người dùng doanh nghiệp hỏng trong lặng lẽ.
  2. Cách phân loại lỗi của bạn có thể giấu chính tính năng của bạn khỏi chính nó. Một quy tắc đúng 99% thời gian (403 = xác thực nghiêm trọng) lại sai đúng cái 1% mà tính năng này tồn tại để phục vụ. Khi bạn thêm một fallback, hãy soát xem điều kiện kích hoạt có thể chạm tới được fallback hay không.
  3. Hãy kiểm thử kẻ thù, không chỉ đường đi suôn sẻ. Bài kiểm thử trung thực duy nhất cho "sống sót qua một proxy chặn WebSocket" là một proxy chặn WebSocket. Chúng tôi đã dựng ra một cái.

GeekBye v2.0.8 phát hành fallback HTTPS này, có cờ kiểm soát và đã được kiểm chứng. Về công việc độ tin cậy nằm cạnh nó, xem vì sao AI notetaker của bạn dừng khi Wi-Fi tệ, và về các bản phát hành lân cận trong series này, xem vì sao AI notetaker của bạn dừng ghi âm giữa cuộc họp (v2.0.9) và vì sao AI phiên âm nghe nhầm thuật ngữ kỹ thuật (v2.0.11).

Bài Viết Liên Quan

Ngày ứng dụng của chúng tôi tự DDoS chính mình
Steven
Steven7 phút đọc

Ngày ứng dụng của chúng tôi tự DDoS chính mình

Một đống bản tải lên còn tồn đọng, được xả ra cùng một lúc lúc khởi động, đã biến mỗi client GeekBye thành một đợt tấn công từ chối dịch vụ nhỏ nhắm vào chính máy chủ của chúng tôi. Cách sửa — và cái thang connection-liveness mà nó buộc chúng tôi phải dựng — là một trong những thứ hữu ích nhất mà v2 đã dạy chúng tôi.

Độ tin cậy
Mạng
Kỹ thuật
Vì sao AI phiên âm nghe nhầm thuật ngữ kỹ thuật (và chúng tôi đã sửa như thế nào)
Steven
Steven9 phút đọc

Vì sao AI phiên âm nghe nhầm thuật ngữ kỹ thuật (và chúng tôi đã sửa như thế nào)

Một phiên ghi âm trực tiếp đã nghe "what is the pointer in C++" thành "what is the point in life". Đây là hành trình điều tra từ bản phiên âm đó đến GeekBye v2.0.11 — keyterm biasing, một race condition làm rớt kết nối, và cái ngày mà chính bản sửa lỗi của chúng tôi phản tác dụng.

Phiên âm
Độ tin cậy
Kỹ thuật
Vì sao ghi màn hình lại quay nhầm màn hình (và cách chúng tôi sửa)
Steven
Steven6 phút đọc

Vì sao ghi màn hình lại quay nhầm màn hình (và cách chúng tôi sửa)

Trên thiết lập hai màn hình, GeekBye luôn ghi và chụp màn hình chính bất kể bạn đang làm việc trên màn hình nào. Bản sửa chỉ là một hàm nhỏ — nhưng phiên bản đầu tiên của nó sai, và code review đã bắt được lý do.

Ghi màn hình
Đa màn hình
Kỹ thuật