2010-02-18 31 views
37

Tôi có một ứng dụng java trên linux mở ổ cắm UDP và chờ tin nhắn. Sau một vài giờ dưới tải nặng, có một gói tin bị mất, tức là các gói được nhận bởi hạt nhân nhưng không phải bởi ứng dụng của tôi (chúng ta thấy các gói bị mất trong sniffer, chúng ta thấy các gói UDP bị mất trong netstat, chúng tôi don ' t xem các gói đó trong nhật ký ứng dụng của chúng tôi).Làm thế nào để giám sát bộ nhớ đệm UDP Linux có sẵn?

Chúng tôi đã thử mở rộng bộ đệm ổ cắm nhưng điều này đã không giúp - chúng tôi bắt đầu mất gói sau đó trước đó, nhưng đó là nó.

Để gỡ lỗi, tôi muốn biết bộ đệm udp OS đầy đủ ở bất kỳ thời điểm nào. Googled, nhưng không tìm thấy gì cả. Bạn có thể giúp tôi được không?

P.S. Các bạn, tôi biết rằng UDP không đáng tin cậy. Tuy nhiên - máy tính của tôi nhận được tất cả các tin nhắn UDP, trong khi ứng dụng của tôi không thể tiêu thụ một số trong số chúng. Tôi muốn tối ưu hóa ứng dụng của mình đến mức tối đa, đó là lý do cho câu hỏi. Cảm ơn.

Trả lời

27

Linux cung cấp các tệp /proc/net/udp/proc/net/udp6, liệt kê tất cả các ổ cắm UDP mở (tương ứng với IPv4 và IPv6). Trong cả hai cột, các cột tx_queuerx_queue hiển thị hàng đợi đi và hàng đợi đến theo byte.

Nếu mọi thứ hoạt động như mong đợi, bạn sẽ không thấy bất kỳ giá trị nào khác 0 trong hai cột này: ngay khi ứng dụng của bạn tạo gói dữ liệu được gửi qua mạng và ngay sau đó các gói đó đến từ mạng của bạn ứng dụng sẽ thức dậy và nhận chúng (cuộc gọi recv ngay lập tức trả về). Bạn có thể thấy số rx_queue tăng lên nếu ứng dụng của bạn mở ổ cắm nhưng không gọi recv để nhận dữ liệu hoặc nếu dữ liệu đó không xử lý dữ liệu đủ nhanh.

+2

Cảm ơn rx_queue, phần còn lại - xem cập nhật) –

+1

@Juliano Ai nói rằng anh ấy có thể chọn giao thức để sử dụng? Có thể anh ấy đang triển khai giao thức dựa trên udp để phục vụ khách hàng hiện tại. – steffen

+2

Poster muốn biết về việc giám sát số liệu thống kê UDP, không cho ý kiến ​​về giao thức sử dụng. Bằng cách xác định vị trí đầu tiên xảy ra mất lớp, người ta có thể làm việc trên một bản sửa lỗi. – RickS

-1

Quá trình này rất đơn giản:

  1. Nếu muốn, tạm dừng quá trình ứng dụng.

  2. Mở ổ cắm UDP. Bạn có thể snag nó từ quá trình chạy bằng cách sử dụng /proc/<PID>/fd nếu cần thiết. Hoặc bạn có thể thêm mã này vào chính ứng dụng và gửi nó một tín hiệu - tất nhiên nó sẽ có ổ cắm mở.

  3. Gọi recvmsg trong vòng lặp nhanh càng nhanh càng tốt.

  4. Đếm số lượng gói/byte bạn nhận được.

Điều này sẽ loại bỏ bất kỳ gói dữ liệu nào hiện được lưu vào bộ đệm, nhưng nếu ứng dụng đó bị hỏng, ứng dụng của bạn đã bị hỏng.

+0

Tôi sắp sửa đánh giá câu trả lời này, nhưng trên suy nghĩ thứ hai nó rất vui nhộn. Tôi chỉ hy vọng không ai cố gắng thực hiện điều này :) – Navin

4

rx_queue sẽ cho bạn biết độ dài hàng đợi tại bất kỳ thời điểm cụ thể nào, nhưng nó sẽ không cho bạn biết mức độ đầy hàng đợi, tức là điểm cao nhất. Không có cách nào liên tục theo dõi giá trị này, và không có cách nào để có được nó theo chương trình (xem How do I get amount of queued data for UDP socket?).

Cách duy nhất tôi có thể tưởng tượng theo dõi độ dài hàng đợi là di chuyển hàng đợi vào chương trình của riêng bạn. Nói cách khác, bắt đầu hai luồng - một là đọc socket nhanh như nó có thể và đổ các datagram vào hàng đợi của bạn; và chương trình còn lại là chương trình của bạn kéo từ hàng đợi này và xử lý các gói. Điều này tất nhiên giả định rằng bạn có thể đảm bảo mỗi thread là trên một CPU riêng biệt. Bây giờ bạn có thể theo dõi độ dài của hàng đợi của riêng bạn và theo dõi dấu nước cao.

46

UDP là giao thức hoàn toàn khả thi. Đó là trường hợp cũ của công cụ thích hợp cho đúng công việc!

Nếu bạn có một chương trình chờ UDP datagram, và sau đó đi để xử lý chúng trước khi trở về để chờ khác, sau đó thời gian xử lý trôi qua của bạn cần phải luôn luôn nhanh hơn tỷ lệ đến trường hợp xấu nhất của datagrams. Nếu không, thì hàng đợi nhận của cổng UDP sẽ bắt đầu lấp đầy.

Điều này có thể được dung thứ cho các vụ nổ ngắn. Hàng đợi thực hiện chính xác những gì nó được cho là làm - xếp hàng các gói dữ liệu cho đến khi bạn sẵn sàng. Nhưng nếu tỷ lệ đến trung bình thường xuyên gây ra một tồn đọng trong hàng đợi, đó là thời gian để thiết kế lại chương trình của bạn. Có hai lựa chọn chính ở đây: giảm thời gian xử lý trôi qua thông qua các kỹ thuật lập trình xảo quyệt và/hoặc đa luồng chương trình của bạn. Cân bằng tải trên nhiều phiên bản của chương trình của bạn cũng có thể được sử dụng.

Như đã đề cập, trên Linux, bạn có thể kiểm tra hệ thống tệp proc để nhận trạng thái về UDP. Ví dụ, nếu tôi cat nút /proc/net/udp, tôi nhận được một cái gì đó như thế này:

$ cat /proc/net/udp 
    sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode ref pointer drops    
    40: 00000000:0202 00000000:0000 07 00000000:00000000 00:00000000 00000000  0  0 3466 2 ffff88013abc8340 0   
    67: 00000000:231D 00000000:0000 07 00000000:0001E4C8 00:00000000 00000000 1006  0 16940862 2 ffff88013abc9040 2237  
122: 00000000:30D4 00000000:0000 07 00000000:00000000 00:00000000 00000000 1006  0 912865 2 ffff88013abc8d00 0   

Từ đó, tôi có thể thấy rằng một ổ cắm thuộc sở hữu của người sử dụng id 1006, đang lắng nghe trên cổng 0x231D (8989) và rằng nhận hàng đợi ở khoảng 128KB. Vì 128KB là kích thước tối đa trên hệ thống của tôi, điều này cho tôi biết chương trình của tôi là yếu kém trong việc theo kịp với các datagram đến. Đã có 2237 giọt cho đến nay, có nghĩa là lớp UDP không thể đặt thêm bất kỳ gói dữ liệu nào vào hàng đợi socket và phải thả chúng.

Bạn có thể xem hành vi của chương trình theo thời gian, ví dụ: sử dụng:

watch -d 'cat /proc/net/udp|grep 00000000:231D' 

Cũng lưu ý rằng lệnh netstat ta về những điều tương tự: netstat -c --udp -an

Giải pháp của tôi cho chương trình weenie của tôi, sẽ là multi-thread.

Chúc mừng!

+0

làm thế nào để bạn biết kích thước hàng đợi tối đa udp của hệ thống của bạn là 128KB? – Chinaxing

+2

@Chinaxing 'cat/proc/sys/net/core/rmem_max' – wakjah

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