Heroku H15 Error on web socket close

余生长醉 提交于 2020-01-24 00:12:13

问题


I have a Go service serving as a web socket server on Heroku. The client pings the server every 20 seconds and it seems to keep the connection open. The problem is that when the socket connection is closed, Heroku router throws H15 error thinking that the request took too much time. For example, if web socket connection has been open for 300 seconds, Heroku log would show:

….H15…. dyno=web.1 connect=1ms service=300000ms status=503 bytes=147….

Anyone has experienced this?


回答1:


I solved the problem by sending pings from the server every second, as in the heroku nodejs example: https://github.com/heroku-examples/node-websockets/blob/master/server.js




回答2:


If anyone comes here looking for a solution from Java perspective:

@Component
public class SocketHandler extends TextWebSocketHandler {

    public static Map<String, WebSocketSession> sessions = new ConcurrentHashMap<>();

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        String userName = (String) session.getAttributes().get("userName");
        sessions.put(userName, session);
        super.afterConnectionEstablished(session);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        String userName = (String) session.getAttributes().get("userName");
        sessions.remove(userName);
        super.afterConnectionClosed(session, status);
    }
}


@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(new SocketHandler(), "/webSocket/AppName/*").addInterceptors(auctionInterceptor());;
    }

    @Bean
    public HandshakeInterceptor auctionInterceptor() {
        return new HandshakeInterceptor() {
            public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response,
                                           WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {

                // Get the URI segment corresponding to the auction id during handshake
                String path = request.getURI().getPath();
                String userName = path.substring(path.lastIndexOf('/') + 1);

                // This will be added to the websocket session
                attributes.put("userName", userName);
                return true;
            }

            public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response,
                                       WebSocketHandler wsHandler, Exception exception) {
                // Nothing to do after handshake
            }
        };
    }
}

Above is my WebSocket configuration in Spring boot, as I only want the connection to be created and keep it in a map with userName and session details.

After that in Springboot main method just added a ping every 30 seconds like this :

public static void main(String[] args) {
    SpringApplication.run(MayAppName.class, args);
    ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    Runnable r = () -> {
        if(SocketHandler.sessions != null && !SocketHandler.sessions.isEmpty()) {
            for (Map.Entry<String, WebSocketSession> stringWebSocketSessionEntry : SocketHandler.sessions.entrySet()) {
                try {
                    // Dummy ping to keep connection alive.
                    stringWebSocketSessionEntry.getValue().sendMessage(new TextMessage("Dummy Ping"));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    };

    scheduler.scheduleAtFixedRate(r, 0, 30, TimeUnit.SECONDS);
}

What this does is, it keeps pinging the subscriber every 30 seconds so that the default 55 seconds does not affect websocket connection, as suggested in Heroku docs.

Timeouts The normal Heroku HTTP routing timeout rules apply to WebSocket connections. Either client or server can prevent the connection from idling by sending an occasional ping packet over the connection.



来源:https://stackoverflow.com/questions/32728030/heroku-h15-error-on-web-socket-close

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!