Spring websockets Tubulação quebrada e cliente não recebendo mensagens

10

Eu tenho alguns problemas com o uso de websockets:

  • java.io.IOException: Broken Pipe
  • O cliente não recebe mensagens TL; DR

Principais coisas que quero saber:

  • Por favor, liste todos os cenários possíveis porque o lado do cliente fecha a conexão (além de atualizar ou fechar a aba).
  • Pode ocorrer uma exceção de tubulação quebrada, além do servidor enviar uma mensagem ao cliente por uma conexão interrompida? Se sim, então como?
  • Quais são os cenários possíveis pelos quais um servidor não envia uma mensagem, embora o servidor envie pulsações? (Quando isso acontece, eu preciso reiniciar o aplicativo para que ele funcione novamente. Essa é uma solução terrível, porque já está em produção.)

Eu tenho um projeto SpringMVC que usa websockets ; SockJS lado do cliente e org.springframework.web.socket.handler.TextWebSocketHandler lado do servidor.

Um JSON é gerado no lado do servidor e enviado para o cliente. Às vezes, recebo um java.io.IOException: Broken Pipe . Eu pesquisei / StackOverflowed muito e encontrei muitas coisas que eu não entendo, mas a razão é provavelmente a conexão é fechada do lado do cliente e o servidor ainda envia uma mensagem (por exemplo, um heartbeat). Isso soa bem? Quais são outras causas para esta exceção? Quais são as razões para o lado do cliente fechar a conexão (além de atualizar ou fechar a guia)?

Além disso, às vezes, o lado do cliente não recebe mensagens do servidor, embora o servidor deva enviá-las. Eu faço o log antes e depois de enviar a mensagem, e ambas as instruções de log são impressas. Alguém tem uma idéia porque isso pode ocorrer? Não tenho erros no log do console do Chrome. A atualização da página não funciona, preciso reiniciar o projeto da primavera ...

Se precisar de mais informações, por favor, deixe um comentário.

Lado do cliente
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.
    };
}

Lado do servidor
Serviço

@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);
                }
            }
        }
    }
}
    
por J. Kamans 14.11.2016 в 17:00
fonte

2 respostas

1

Apenas um palpite: verifique seu equipamento de rede. Talvez exista um firewall mal configurado que termina essas conexões; ou, pior ainda, equipamentos de rede quebrados fazendo com que as conexões terminem. Se o seu servidor tiver várias NICs (o que provavelmente é o caso), também é possível que haja algum erro de configuração usando essas NICs ou ao conectar-se ao servidor por meio de diferentes NICs.

    
por Mr.Radar 24.11.2016 / 11:34
fonte
1

Se este problema ocorrer acidentalmente do que é possível que você tenha algum problema com qualquer cache - por favor, verifique se o Spring ou o SocksJS tem caches próprios para interação do soquete.

Isso acontece nos seus dispositivos (ou nos dispositivos que você controla)?

Além disso, posso sugerir que você use algum analisador de pacotes de rede como o wireshark . Com essa ferramenta, você verá a atividade de rede atual "on-line"

Alguns motivos externos que podem desctroy-se à conexão sem a interrupção correta (e não é possível gerenciá-lo sem verificações de conexão):

  • suspender / desligar o dispositivo
  • falha de rede
  • fechamento do navegador em algum erro

Acho que é uma pequena parte da lista completa de possíveis motivos para destruir a conexão.

    
por Pavel Uvarov 24.11.2016 / 13:45
fonte