2011-01-16 20 views
19

Tôi đang cố tải thử nghiệm một máy chủ Java bằng cách mở một số lượng lớn các kết nối socket đến máy chủ, xác thực , đóng kết nối, sau đó lặp lại. Ứng dụng của tôi chạy rất tốt cho một lúc nhưng cuối cùng tôi nhận được:"java.net.BindException: Địa chỉ đã được sử dụng" khi cố gắng tạo Ổ cắm nhanh chóng và phá hủy để kiểm tra tải

java.net.BindException: Address already in use: connect

Theo tài liệu tôi đọc, lý do cho điều này là ổ cắm kín vẫn chiếm địa chỉ địa phương được giao cho một khoảng thời gian sau khi đóng cửa() là gọi là. Đây là hệ điều hành phụ thuộc nhưng có thể vào thứ tự của phút. Tôi đã thử gọi setReuseAddress(true) trên ổ cắm với hy vọng rằng địa chỉ của nó sẽ có thể sử dụng lại ngay sau khi close() được gọi. Thật không may điều này dường như không phải là trường hợp.

Mã của tôi để tạo ổ cắm là:

Socket socket = new Socket(); 
socket.setReuseAddress(true); 
socket.connect(new InetSocketAddress(m_host, m_port)); 

Nhưng tôi vẫn nhận được lỗi này:

java.net.BindException: Address already in use: connect after awhile.

Có cách nào khác để thực hiện những gì tôi đang cố gắng để làm gì? Tôi muốn ví dụ: mở 100 ổ cắm, đóng tất cả, mở 200 ổ cắm, đóng tất cả, mở 300, vv lên đến tối đa 2000 hoặc ổ cắm.

Bất kỳ trợ giúp nào sẽ được đánh giá rất nhiều!

+1

Máy chủ hoặc ứng dụng khách có ném ngoại lệ không? Điều đó có xảy ra sau một số kết nối nhất quán không? –

+1

Bạn có thể cần thay đổi cài đặt TCP của máy, xem http://docs.alfresco.com/4.0/topic/com.alfresco.enterprise.doc/tasks/alf-win-regedit.html –

Trả lời

15

Bạn đang xả không gian của các cổng đi bằng cách mở nhiều ổ cắm ra bên ngoài trong khoảng thời gian TIME_WAIT trong hai phút. Câu hỏi đầu tiên bạn nên tự hỏi là liệu đây có phải là một thử nghiệm tải thực tế không? Là một khách hàng thực sự thực sự sẽ làm điều đó? Nếu không, bạn chỉ cần sửa đổi phương pháp thử nghiệm của mình.

BTW SO_LINGER là số giây mà ứng dụng sẽ đợi trong khi đóng() để dữ liệu bị xóa. Nó thường là số không.Các cổng sẽ treo xung quanh cho khoảng TIME_WAIT anyway nếu đây là kết thúc đã ban hành gần. Đây không phải là điều tương tự. Có thể lạm dụng tùy chọn SO_LINGER để khắc phục sự cố. Tuy nhiên điều đó cũng sẽ gây ra hành vi đặc biệt ở đồng đẳng và một lần nữa đây không phải là mục đích của một thử nghiệm.

+0

Bạn chính xác trong đó không có khách hàng thực sự nào sẽ mở nhiều kết nối. Trong ứng dụng của tôi, các máy khách thực sự sẽ chỉ mở 1 kết nối TCP tới máy chủ. Những gì tôi đang cố gắng làm là mô phỏng khách hàng thực và tôi muốn có nhiều khách hàng mô phỏng chạy trên cùng một máy càng tốt. – bradforj287

+0

Phản hồi của bạn cũng giúp tôi! :-) Một cái gì đó tôi muốn thêm lên ở đây là nếu bạn sử dụng phương pháp setSoLinger(), nó gây ra vấn đề cho các đồng nghiệp đã kết nối và đôi khi họ bị ngắt kết nối quá! Không thực sự biết những gì gây ra hành vi này nhưng nó đã cho tôi một 45 phút tốt để tìm ra! – M2X

+0

@ M2X SO_LINGER tắt là mặc định, khiến 'close()' hoạt động như tất cả chúng ta bây giờ và yêu thích. Nếu bạn đặt nó 'on' và * với thời gian chờ bằng không, * nó gây ra 'close()' và 'shutdown()' để đặt lại một thay vì đóng một cách thích hợp. Tôi thậm chí không muốn đề cập đến điều này bởi vì nó là một hành vi không mong muốn như vậy. Nếu có bất kỳ lý do hợp lệ nào để gây rối với SO_LINGER trong một ứng dụng TCP/IP bình thường thì tôi vẫn chưa gặp chúng ... trong gần ba mươi năm. – EJP

-1

Tôi nghĩ rằng bạn nên lập kế hoạch trên cổng bạn muốn sử dụng để kết nối để sử dụng. Bằng cách đó, tôi có nghĩa là hãy thử để kết nối bằng cổng đã cho. Nếu kết nối không thành công (hoặc trong trường hợp của bạn ném một ngoại lệ), hãy thử mở kết nối bằng số cổng tiếp theo.

Hãy thử đính kèm câu hỏi connect trong số try/catch.

Dưới đây là một số mã giả truyền tải những gì tôi nghĩ sẽ làm việc:

portNumber = x //where x is the first port number you will try 
numConnections = 200 // or however many connections you want to open 
while(numConnections > 0){ 
    try{ 
     connect(host, portNumber) 
     numConnections-- 
    }catch(){} 
    portNumber++ 
} 

Mã này không bao gồm các trường hợp góc như "những gì xảy ra khi tất cả các cổng đang được sử dụng?"

+1

Điều này không làm cho bất kỳ ý nghĩa. Anh ta đang cố gắng kết nối với một dịch vụ đang nghe ở một số cổng cố định, không phải một dịch vụ có thể được tăng lên, và vấn đề của anh ta là không gian cổng cục bộ, không phải là không gian cổng từ xa. – EJP

1

Không sử dụng bind() nhưng setReuseAddress (đúng) chỉ là lạ, tôi hy vọng bạn hiểu được ý nghĩa của setReuseAddress (và điểm của). 100-2000 là không phải một số lượng lớn ổ cắm để mở, tuy nhiên máy chủ bạn đang cố gắng kết nối (vì có vẻ như cùng một cặp cổng/cổng), có thể chỉ cần thả chúng với một backlog bình thường là 50.

Chỉnh sửa: nếu bạn cần mở nhiều ổ cắm nhanh (quét cổng ermm?), Tôi muốn rất khuyên bạn nên sử dụng NIO và kết nối()/finishConnect() + Selector. Mở 1000 ổ cắm trong cùng một luồng chỉ đơn giản là chậm. Quên bạn có thể cần finishConnect() theo cách nào đó trong mã của bạn.

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