2016-11-14 20 views
9

Tôi có một vài vấn đề với việc sử dụng WebSockets:Xuân WebSockets ống bị hỏng & khách hàng không nhận được tin nhắn

  • java.io.IOException: Broken Pipe
  • Khách hàng không nhận tin nhắn
    TL; DR

Những điều chính tôi muốn biết:

  • Vui lòng liệt kê tất cả các tình huống có thể xảy ra tại sao phía khách hàng đóng kết nối (ngoài việc làm mới hoặc đóng tab).
  • Có thể xảy ra ngoại lệ ống bị hỏng, ngoài máy chủ gửi tin nhắn cho khách hàng qua kết nối bị hỏng không? Nếu có, thì làm thế nào?
  • Kịch bản có thể xảy ra tại sao máy chủ không gửi thư, mặc dù máy chủ gửi nhịp tim? (Khi điều này xảy ra, tôi cần phải khởi động lại ứng dụng cho nó hoạt động trở lại Đây là một giải pháp khủng khiếp, bởi vì nó đã là trong sản xuất..)


tôi có một dự án có sử dụng SpringMVC websockets; SockJS phía máy khách và org.springframework.web.socket.handler.TextWebSocketHandler phía máy chủ.

A JSON được tạo phía máy chủ và gửi cho khách hàng. Đôi khi, tôi nhận được java.io.IOException: Broken Pipe. Tôi googled/StackOverflowed rất nhiều và tìm thấy quá nhiều điều tôi không hiểu, nhưng lý do có lẽ là kết nối được đóng phía khách hàng và máy chủ vẫn gửi một tin nhắn (ví dụ, một nhịp tim). Âm thanh này có ổn không? Các nguyên nhân khác cho ngoại lệ này phát sinh là gì? Những lý do để phía khách hàng đóng kết nối (ngoài việc làm mới hoặc đóng tab) là gì?

Ngoài ra, đôi khi phía máy khách không nhận được bất kỳ thư nào từ máy chủ, mặc dù máy chủ nên gửi chúng. Tôi đăng nhập trước và sau khi gửi tin nhắn, và cả hai câu lệnh tường trình được in. Có ai có một ý tưởng tại sao điều này có thể xảy ra? Tôi không có lỗi trong nhật ký bảng điều khiển của Chrome. Làm mới trang không hoạt động, tôi cần phải khởi động lại dự án mùa xuân ...

Nếu bạn cần thêm thông tin, vui lòng để lại nhận xét.


Khách hàng bên

function connect() { 
    var socket = new SockJS('/ws/foo'); 

    socket.onopen = function() { 
     socket.send(fooId); // ask server for Foo with id fooId. 
    }; 

    socket.onmessage = function (e) { 
     var foo = JSON.parse(e.data); 
     // Do something with foo. 
    }; 
} 

Server side
Dịch vụ

@Service 
public class FooService implements InitializingBean { 
    public void updateFoo(...) { 
     // Update some fields of Foo. 
     ... 
     // Send foo to clients. 
     FooUpdatesHandler.sendFooToSubscribers(foo); 
    } 
} 

WebSocketHandler

public class FooUpdatesHandler extends ConcurrentTextWebSocketHandler { 
// ConcurrentTextWebSocketHandler taken from https://github.com/RWTH-i5-IDSG/BikeMan (Apache License version 2.0) 

    private static final Logger logger = LoggerFactory.getLogger(FooUpdatesHandler.class); 
    private static final ConcurrentHashMap<String, ConcurrentHashMap<String, WebSocketSession>> fooSubscriptions = 
      new ConcurrentHashMap<>(); 

    public static void sendFooToSubscribers(Foo foo) { 
     Map<String, WebSocketSession> sessionMap = fooSubscriptions.get(foo.getId()); 

     if (sessionMap != null) { 
      String fooJson = null; 
      try { 
       fooJson = new ObjectMapper().writeValueAsString(foo); 
      } catch (JsonProcessingException ignored) { 
       return; 
      } 

      for (WebSocketSession subscription : sessionMap.values()) { 
       try { 
        logger.info("[fooId={} sessionId={}] Sending foo...", foo.getId(), subscription.getId()); 
        subscription.sendMessage(new TextMessage(fooJson)); 
        logger.info("[fooId={} sessionId={}] Foo send.", foo.getId(), subscription.getId()); 
       } catch (IOException e) { 
        logger.error("Socket sendFooToSubscribers [fooId={}], exception: ", foo.getId(), e); 
       } 
      } 
     } 
    } 
} 

Trả lời

1

Chỉ cần một đoán: Kiểm tra thiết bị mạng của bạn. Có thể có tường lửa bị định cấu hình sai kết thúc các kết nối này; hoặc thậm chí tệ hơn, thiết bị mạng bị hỏng khiến các kết nối bị chấm dứt. Nếu máy chủ của bạn có nhiều NIC (có khả năng là trường hợp), cũng có thể có một số cấu hình sai khi sử dụng các NIC này hoặc kết nối với máy chủ qua các NIC khác nhau.

+0

Điều kỳ lạ là, thông thường mọi thứ đều hoạt động tốt. Nhiều thiết bị (di động và máy tính xách tay) có kết nối websocket và mọi thiết bị đều nhận được JSON của Foo. Nhưng đôi khi (+/- một lần trong 2 tuần), một "ống" bị hỏng nặng xảy ra (xem bình luận của tôi tại câu trả lời của @Pavel Uvarov). Các kết nối websocket vẫn được thực hiện và máy chủ vẫn gửi heartbeats, nó chỉ không gửi JSONs của Foo nữa. Tôi không nghĩ đó là một điều tường lửa. Bất kỳ ý tưởng nào khác? –

+0

Điều này có ảnh hưởng đến bất kỳ khách hàng nào sau khi đường ống bị hỏng "nặng" - ngoại lệ hay chỉ một trường hợp cụ thể gây ra ngoại lệ? –

+0

Nó ảnh hưởng đến tất cả khách hàng. Khi nó bị hỏng (do đó không có JSON), một khách hàng liên lạc với tôi. Tôi thử nghiệm nếu nó thực sự bị hỏng bằng cách mở trang web trong nhiều tab. Tất cả các tab có cùng một vấn đề khi "Broken" Broken Pipe xảy ra. Giải pháp duy nhất sau đó là khởi động lại chương trình java trên máy chủ sản xuất. –

1

Nếu sự cố này xảy ra vô tình, có thể bạn gặp sự cố với bất kỳ bộ nhớ cache nào - vui lòng kiểm tra xem spring hoặc SocksJS có bộ nhớ cache riêng cho tương tác socket hay không.

Điều này có xảy ra trên thiết bị của bạn (hoặc trên các thiết bị mà bạn kiểm soát) không?

Ngoài ra tôi có thể đề nghị bạn sử dụng một số bộ phân tích gói mạng như wireshark. Với công cụ này bạn sẽ thấy hoạt động hiện tại mạng 'trực tuyến'

Một số nguyên nhân bên ngoài có thể desctroy kết nối mà không đúng dừng nó (và bạn không thể quản lý nó mà không cần kiểm tra sức khỏe kết nối):

  • thiết bị đình chỉ/poweroff
  • mạng thất bại
  • trình duyệt đóng cửa trên một số lỗi

tôi nghĩ rằng đó là một phần nhỏ trong danh sách đầy đủ các lý do có thể để tiêu diệt kết nối.

+0

Điều này xảy ra trên thiết bị di động và máy tính xách tay. –

+0

Có "loại" khác nhau của các ngoại lệ ống bị hỏng. Tôi có thể tạo ra một bản thân mình bằng cách làm mới trình duyệt rất nhiều, nhưng sau khi làm mới cuối cùng mọi thứ vẫn hoạt động tốt (sau đó máy chủ vẫn gửi JSON của Foo cho khách hàng). Nhưng đôi khi tôi nhận được một ngoại lệ ống bị hỏng đó là "nặng", máy chủ không gửi JSON nữa (ngay cả khi tôi làm mới trang). Điều kỳ lạ là, máy chủ vẫn gửi heartbeats và máy chủ vẫn ghi nhật ký "gửi tin nhắn" và "gửi tin nhắn" (các bản ghi trước và sau phương thức Session.sendMessage. Tôi cần khởi động lại toàn bộ chương trình java để sửa lỗi này ... –

+0

Bất kỳ ý tưởng nào tại sao Ống bị hỏng "nặng" xảy ra? Đó không phải vì lý do được liệt kê của bạn một cách không may. –

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