2011-10-03 32 views
17

Tôi có một chương trình bao gồm máy chủ chính và máy chủ phụ được phân phối. Các máy chủ nô lệ gửi cập nhật trạng thái cho máy chủ, và nếu máy chủ không nghe từ một nô lệ cụ thể trong một khoảng thời gian cố định, nó đánh dấu nô lệ là xuống. Điều này đang xảy ra nhất quán.Không thể gán địa chỉ được yêu cầu - nguyên nhân có thể xảy ra?

Từ kiểm tra nhật ký, tôi thấy rằng nô lệ chỉ có thể gửi cập nhật trạng thái cho máy chủ, và sau đó không bao giờ có thể gửi cập nhật khác, luôn thất bại trong cuộc gọi để kết nối() "Không thể gán địa chỉ được yêu cầu (99)

Rất kỳ quặc, nô lệ có thể gửi một số cập nhật khác cho máy chủ và tất cả các kết nối đang diễn ra trên cùng một cổng. Có vẻ như nguyên nhân phổ biến nhất của lỗi này là kết nối để mở, nhưng tôi gặp khó khăn khi tìm thấy bất kỳ nội dung nào còn mở, có các giải thích khác có thể không?

Để làm rõ, đây là cách tôi đang kết nối:

struct sockaddr *sa; // parameter 
size_t   sa_size; //parameter 
int    i = 1; 
int    stream; 

stream = socket(AF_INET,SOCK_STREAM,0); 
setsockopt(stream,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(i)); 
bindresvport(stream,NULL); 
connect(stream,sa,sa_size); 

Mã này nằm trong chức năng để có được kết nối với máy chủ khác và lỗi trên bất kỳ cuộc gọi nào trong số 4 cuộc gọi đó khiến chức năng bị lỗi.

+0

Tôi đã xác minh rằng địa chỉ cổng và địa chỉ IP đều chính xác. – dbeer

Trả lời

9

Có thể SO_REUSEADDR trợ giúp ở đây? http://www.unixguide.net/network/socketfaq/4.5.shtml

+0

SO_REUSEADDR được đặt cho tất cả các kết nối. – dbeer

+1

đây là một ví dụ tương tự: http://stackoverflow.com/questions/3886506/why-would-connect-give-eaddrnotavail – dmh2000

+0

@ dmh2000 - Tôi đã xem ví dụ đó trước khi đăng và chưa thành công khi cố gắng xem xét các yếu tố đó. Tôi tự hỏi nếu tôi chỉ cần tiếp tục tìm kiếm hoặc nếu có điều gì đó tôi không tính đến. – dbeer

3

Đây chỉ là ảnh trong bóng tối: khi bạn gọi kết nối mà không cần ràng buộc trước, hệ thống sẽ phân bổ cổng cục bộ của bạn và nếu bạn có nhiều chủ đề kết nối và ngắt kết nối, nó có thể cố gắng phân bổ cổng sử dụng. tập tin nguồn kernel inet_connection_sock.c gợi ý ở điều kiện này. giống như thử nghiệm, hãy thử thực hiện liên kết với cổng cục bộ trước, đảm bảo mỗi liên kết/kết nối sử dụng số cổng cục bộ khác nhau.

+0

Tôi sẽ thử điều này và xem liệu nó có giúp ích – dbeer

+0

Xin lỗi, tôi không xem mã của tôi khi tôi đăng nó.Tôi gọi một ràng buộc trước khi kết nối. Tôi sẽ cập nhật câu hỏi của mình để thể hiện tốt hơn những gì tôi đang làm. – dbeer

5

Nó chỉ ra rằng vấn đề thực sự là địa chỉ đã được bận rộn - sự bận rộn đã được gây ra bởi một số vấn đề khác trong cách chúng tôi đang xử lý thông tin liên lạc mạng. Đầu vào của bạn đã giúp tôi tìm ra điều này. Cảm ơn bạn.

CHỈNH SỬA: cụ thể, các vấn đề trong xử lý thông tin liên lạc mạng của chúng tôi là các cập nhật trạng thái này sẽ liên tục được gửi lại nếu lần đầu tiên không thành công. Nó chỉ là một vấn đề thời gian cho đến khi chúng tôi có tất cả nô lệ phân tán cố gắng gửi cập nhật trạng thái của nó cùng một lúc, đó là quá bão hòa mạng của chúng tôi.

+0

Tôi rất thích việc xây dựng “bận” trong trường hợp nó là nguyên nhân của cùng một lỗi ở đây trong mã của riêng tôi - ý bạn là “máy chủ chấp nhận các kết nối có quá nhiều hàng đợi đang chờ chấp nhận() cho một kết nối khác để được phép vào hàng đợi? ”Hoặc một trường hợp khác? Cảm ơn! –

+2

@BrandonRhodes vấn đề của chúng tôi là chúng tôi đã có một số thử lại xảy ra mà không có một thuật toán backoff thích hợp, vì vậy chúng tôi đã có hàng trăm hoặc nhiều nỗ lực kết nối vào cùng một socket mỗi giây. Sự tranh cãi này đã gây ra thất bại của chúng tôi. Thực hiện một thuật toán backoff thích hợp là rất quan trọng để giải quyết vấn đề này. – dbeer

+0

Cảm ơn bạn đã cung cấp thêm thông tin! Vui vì bạn đã sửa nó. –

1
sysctl -w net.ipv4.tcp_timestamps=1 
sysctl -w net.ipv4.tcp_tw_recycle=1 
+3

làm thế nào để bạn hoàn tác những 2? – ado

+6

Không giải thích câu trả lời này không có bất kỳ giá trị nào. –

Các vấn đề liên quan