Nguyên nhân kết nối của khách hàng thất bại

Khi kết nối thất bại, khách hàng thường gặp hai lỗi, connection refuseconnection timeout.

connection refuse (Kết nối bị từ chối)

Nguyên nhân thường là:

  1. Cổng kết nối của khách hàng bị sai.
  2. Tên miền hoặc địa chỉ IP mà khách hàng kết nối sai.
  3. Nếu khách hàng sử dụng tên miền để kết nối, có thể tên miền đó trỏ đến địa chỉ IP của máy chủ sai.
  4. Máy chủ sử dụng CDN hoặc các proxy tăng tốc khác, dẫn đến IP thực tế kết nối không khớp với IP dự kiến.
  5. Máy chủ chưa được khởi động hoặc cổng không được lắng nghe.
  6. Sử dụng phần mềm proxy mạng.
  7. IP lắng nghe của máy chủ và địa chỉ truy cập không cùng một dải địa chỉ. Ví dụ, nếu máy chủ lắng nghe 127.0.0.1, thì khách hàng chỉ có thể kết nối qua 127.0.0.1, không thể kết nối qua địa chỉ IP mạng nội bộ hoặc IP mạng ngoài. Đề nghị thiết lập địa chỉ lắng nghe là 0.0.0.0, để có thể kết nối từ máy nội bộ, mạng nội bộ và mạng ngoài.

connection timeout (Kết nối vượt thời gian)

Nguyên nhân thường là:

  1. Tường lửa của máy chủ chặn kết nối, có thể tạm thời tắt tường lửa để thử.
  2. Nếu sử dụng máy chủ đám mây, nhóm bảo mật cũng có thể chặn việc thiết lập kết nối, cần vào bảng quản lý để mở cổng tương ứng.
  3. Nếu sử dụng bảng điều khiển như Baota, cần mở cổng tương ứng trong Baota.
  4. Máy chủ không tồn tại hoặc chưa được khởi động.
  5. Nếu khách hàng sử dụng tên miền để kết nối, có thể tên miền đó trỏ đến địa chỉ IP của máy chủ sai.
  6. IP mà khách hàng truy cập là IP nội bộ của máy chủ và khách hàng cùng máy chủ không nằm trong cùng một mạng LAN.

cannot assign requested address (Không thể phân bổ địa chỉ yêu cầu)

Khi là khách hàng, mỗi khi khởi tạo một kết nối sẽ cần chiếm dụng một cổng tạm thời trên máy cục bộ, một máy chủ mặc định có thể sử dụng khoảng 20.000 – 30.000 cổng tạm thời. Nếu số lượng kết nối đến máy chủ cụ thể vượt quá giá trị này thì sẽ không thể phân bổ cổng có sẵn, và sẽ phát sinh lỗi này.
Có thể tăng số lượng cổng tạm thời trên máy cục bộ bằng cách thay đổi tham số hạt nhân trong /etc/sysctl.conf trong trường hợp net.ipv4.ip_local_port_range, ví dụ, thiết lập thành 10000 65535 (thiết lập khoảng cổng cục bộ từ 10000 đến 65535, tức là tăng số lượng cổng cục bộ lên 55535 cái), chạy sysctl -p để có hiệu lực.
Ngoài ra, khi kết nối bị ngắt, kết nối sẽ chuyển sang trạng thái TIME_WAIT, vẫn sẽ chiếm dụng cổng cục bộ tương ứng trong một khoảng thời gian, tức là trong thời gian ngắn mà khởi tạo quá nhiều (vượt quá 20.000 – 30.000) kết nối ngắn cũng sẽ báo lỗi Cannot assign requested address, nếu là trường hợp này có thể sử dụng thiết lập hạt nhân để nhanh chóng thu hồi TIME_WAIT, tham khảo Tối ưu hóa hạt nhân.

Lưu ý
Giới hạn số lượng cổng cục bộ chỉ áp dụng cho khách hàng, máy chủ không bị giới hạn cổng cục bộ, miễn là đủ tài nguyên, số lượng kết nối của máy chủ có thể được coi là không giới hạn.

Các lỗi khác

Nếu lỗi phát sinh không phải là connection refuseconnection timeout thì thường là các nguyên nhân sau:

1. Giao thức giao tiếp mà khách hàng sử dụng không nhất quán với máy chủ.
Ví dụ, nếu máy chủ sử dụng giao thức http, khách hàng sử dụng giao thức websocket để truy cập sẽ không thể kết nối. Nếu khách hàng kết nối bằng giao thức websocket, máy chủ cũng phải là giao thức websocket. Nếu máy chủ là dịch vụ giao thức http, thì khách hàng phải sử dụng giao thức http để truy cập.

Nguyên lý ở đây tương tự như nếu bạn muốn giao tiếp với người Anh, bạn cần sử dụng tiếng Anh. Nếu bạn muốn giao tiếp với người Nhật, bạn cần sử dụng tiếng Nhật. Ở đây ngôn ngữ giống như giao thức giao tiếp, cả hai bên (khách hàng và máy chủ) phải sử dụng cùng một ngôn ngữ để giao tiếp, nếu không sẽ không thể kết nối.

Các lỗi phổ biến do giao thức giao tiếp không nhất quán bao gồm:

WebSocket connection to 'ws://xxx.com:xx/' failed: Error during WebSocket handshake: Unexpected response code: xxx

WebSocket connection to 'ws://xxx.com:xx/' failed: Error during WebSocket handshake: net::ERR_INVALID_HTTP_RESPONSE

Cách giải quyết:
Từ hai lỗi trên có thể thấy, khách hàng sử dụng kết nối ws là giao thức websocket. Máy chủ cũng cần phải là giao thức websocket thì mới được, mã phần lắng nghe của máy chủ cần chỉ định giao thức websocket để có thể giao tiếp, ví dụ như sau:

Nếu là gatewayWorker, mã phần lắng nghe sẽ giống như:

// giao thức websocket, như vậy khách hàng mới có thể kết nối ws://... . xxxx là cổng không cần thay đổi
$gateway = new Gateway('websocket://0.0.0.0:xxxx');

Nếu là Workerman thì sẽ là:

// giao thức websocket, như vậy khách hàng mới có thể kết nối ws://... . xxxx là cổng không cần thay đổi
$worker = new Worker('websocket://0.0.0.0:xxxx');