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);
}
}
}
}
}
Đ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? –
Đ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ệ? –
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. –