Tôi không thể tìm thấy trích dẫn trong tài liệu, nhưng kinh nghiệm của tôi cho thấy rằng cơ sở hạ tầng mạng của EC2 nói chung (sẽ bao gồm RDS và có thể là bất kỳ dịch vụ AWS nào khác chạy trên các máy ảo được cung cấp cho mỗi khách hàng, nếu không phải tất cả AWS, và chắc chắn có vẻ như không bị giới hạn nghiêm ngặt đối với "phiên bản EC2") thực hiện kiểm tra gói trạng thái và sẽ "quên" rằng kết nối TCP là hợp lệ sau một vài phút không hoạt động tuyệt đối ... gây ra hành vi mà bạn mô tả.
Các máy ở cả hai đầu của kết nối có thể tin rằng kết nối vẫn ở đó, nhưng mạng sẽ không cho phép lưu lượng truyền giữa chúng, bởi vì các phiên TCP trong môi trường SPI không được phát hiện, chúng được tạo và chỉ có thể được tạo khi mạng thấy kết nối ngay từ đầu ( SYN, SYN / ACK, ACK ). Ban đầu tôi gặp sự cố này với máy chủ MySQL trong EC2 (không phải RDS) nhưng sẽ rất ngạc nhiên nếu nguyên nhân cơ bản không giống nhau.
Có hai cách tiếp cận để giải quyết vấn đề này.
Nếu máy PHP của bạn là Linux, hãy định cấu hình hạt nhân để giữ cho các kết nối tồn tại ở lớp 4. Thay đổi này sẽ không hiển thị với bạn theo nghĩa là các keepalives này sẽ không thay đổi giá trị trong Time
trong SHOW PROCESSLIST
cho các kết nối trong Sleep
bởi vì nó sẽ không đặt lại lượng thời gian kết nối không hoạt động ở lớp 7 ... nhưng nó sẽ tránh hết thời gian chờ từ cơ sở hạ tầng AWS nếu các thư viện quản lý kết nối MySQL đang đặt các tùy chọn socket chính xác để tận dụng lợi thế của nó.
http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/usingkeepalive .html giải thích cách thiết lập tính năng này hoạt động và cách làm cho nó hoạt động liên tục khi khởi động lại.
Nếu không, tùy chọn khác là buộc MySQL đóng kết nối sớm hơn thời gian chờ của mạng để máy PHP sẽ ngay lập tức nhận ra rằng nó đang cố gắng nói chuyện trên một ổ cắm đóng. Nghe có vẻ phản trực quan khi rút ngắn thời gian chờ thay vì kéo dài thời gian chờ, nhưng việc rút ngắn thời gian chờ sẽ khiến kiểm tra ping của bạn không thành công rất nhanh nếu một phiên không hoạt động quá lâu, điều này cũng (về cơ bản) "giải quyết" vấn đề, giả sử sự tỉnh táo trong thư viện máy khách PHP. Một khi ứng dụng của bạn bận rộn hơn, các kết nối có lẽ sẽ hiếm khi không hoạt động đủ lâu để đạt đến thời gian chờ.
MySQL Server có hai cài đặt thời gian chờ nhàn rỗi khác nhau: wait_timeout
(đối với các phiên không tương tác, tức là các kết nối từ mã, như PHP) và interactive_timeout
(từ trình duyệt truy vấn và máy khách dòng lệnh) nhưng máy chủ chỉ biết sự khác biệt vì thư viện máy khách phải thông báo cho máy chủ mà nó đang thiết lập loại kết nối nào. Giả sử thư viện khách hàng của bạn sử dụng thiết lập chính xác, thì wait_timeout
là một trong những bạn đang tìm kiếm. Đặt giá trị này thành giá trị dưới 900 sẽ giải quyết được sự cố nếu không thay đổi cài đặt lưu giữ TCP trong nhân Linux. Tuy nhiên, lưu ý rằng sau khi thực hiện thay đổi, chỉ các kết nối trong tương lai mới bị ảnh hưởng - các kết nối đã được thiết lập khi thực hiện thay đổi sẽ vẫn chạy với giá trị hiện tại, giá trị này được mặc định là 8 giờ (28800 giây). Chúng có thể định cấu hình trong Nhóm tham số RDS cho trường hợp của bạn.
Có gợi ý về hành vi tương tự trong tài liệu AWS tại đây , cùng với cài đặt đăng ký Windows cần được điều chỉnh để thay đổi lưu giữ TCP nếu bạn đang chạy máy chủ PHP trên Windows, thay vì Linux, như tôi đã giả định ở trên ... mặc dù bài viết nói riêng về Redshift và các kết nối bên ngoài EC2 dường như vẫn xác thực vấn đề cơ bản như đã thảo luận ở trên.