Websocket 在 localhost 但不是 Heroku

Posted

技术标签:

【中文标题】Websocket 在 localhost 但不是 Heroku【英文标题】:Websocket working on localhost but not Heroku 【发布时间】:2017-08-27 12:06:15 【问题描述】:

我有一个使用 websockets(STOMP over SockJs)的应用程序,后端有 Spring。应用程序在 Tomcat 的 localhost 上运行良好(websockets),但是当我部署到 Heroku 或 AWS Web Sockets 时停止工作。 我在 Angular2 中的 websocket 配置

        let sockjs = new SockJS('/rest/add?jwt=' + this.authService.getToken(), "devel":true,"debug":true, "transports":["websocket"]);

我也试过

"disabled_transports":["websocket"]

但两者都失败了。 web.xml

 <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
     http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
     version="3.1">

<context-param>
    <param-name>spring.profiles.default</param-name>
    <param-value>default</param-value>
</context-param>

<servlet>
    <servlet-name>ws</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:/spring/ws-context.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
    <async-supported>true</async-supported>
</servlet>
<servlet-mapping>
    <servlet-name>ws</servlet-name>
    <url-pattern>/rest/*</url-pattern>
</servlet-mapping>

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <async-supported>true</async-supported>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/rest/*</url-pattern>

</filter-mapping>
</web-app>

春天的websocket

    <websocket:message-broker
    application-destination-prefix="/app">
    <websocket:stomp-endpoint path="/add">
        <websocket:sockjs/>
    </websocket:stomp-endpoint>
    <websocket:simple-broker prefix="/topic, /queue" />
</websocket:message-broker>

我在 Heroku 上的应用程序的 URL,因此您可以在 Web 浏览器的控制台中自行检查。 Link 请查看更新的日志,这篇文章让我很担心No TransportHandler

CJyb2xlcyI6IkNVU1RPTUVSIn0.wFqNOduN-lD1-9GIRnG1X1aLJZTxtz9c6vmO7jmPPiE2017-04-06T16:23:32.439917+00:00 app[web.1]: 2017-04-06 16:2332 WARN  DefaultSockJsService:239 - No TransportHandler for http://myapp-ws.herokuapp.com/rest/add/097/eyocvxic/websocket?jwt=eyJhbGciOiJI

【问题讨论】:

您的日志无关紧要,检查 vegur 日志 - 可能 vegur 配置不正确并断开 websocket 连接。并且不要禁用 websocket,你需要启用 websocket。 我可以在日志中看到 H27 错误devcenter.heroku.com/changelog-items/662 但没有关于 Heroku 上需要更改的内容(原因可能是我有一个免费帐户而不是付费帐户)。我还与 Heroku 支持团队一起创建了一张票来查看这个。 我不是 Heroku 方面的专家。我想您的连接已被代理/负载平衡器中断,但我无法帮助您,抱歉。 这个例子对我不起作用 - websocket 连接立即断开并出现 404 http 状态。也许是 Heroku 的问题。作为替代方案可以尝试 OpenShift - 它声明支持 websockets 并有免费计划 http-session-affinity - 粘性会话参数,用于负载均衡。如果您的集群至少有 2 个实例,但在集群之间没有共享会话,则很有用。例如 - 这里是 apache 的配置,它作为 2 个 tomcat 实例的代理和负载均衡器,只是为了说明复杂性***.com/a/42578769/1516873 Heroku 使用 Verur 作为代理,它应该有类似的设置。 【参考方案1】:

好的,所以最后我让它工作了。原来,heroku 上的 Tomcat 没有标准的库集。 首先,我在 webapp-runner https://devcenter.heroku.com/articles/java-webapp-runner 上本地部署,之后我看到了一个奇怪的错误。我测试了几个库,最后在添加后

<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-websocket</artifactId>
    <version>8.5.11</version>
</dependency>

<build>
...
<plugins>
    ...
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <version>2.3</version>
        <executions>
            <execution>
                <phase>package</phase>
                <goals><goal>copy</goal></goals>
                <configuration>
                    <artifactItems>
                        <artifactItem>
                            <groupId>com.github.jsimone</groupId>
                            <artifactId>webapp-runner</artifactId>
                            <version>8.5.11.3</version>
                            <destFileName>webapp-runner.jar</destFileName>
                        </artifactItem>
                    </artifactItems>
                </configuration>
            </execution>
        </executions>
    </plugin>
</plugins>

我让它在本地工作。 然后我添加了具有以下内容的 PROCFILE

web:    java $JAVA_OPTS -jar myapp-ws/target/dependency/webapp-runner.jar --port $PORT myapp-ws/target/*.war

并致力于 GITHUB(我已将 git 与 Heroku 集成),从 Heroku 内部触发构建并且它可以工作。

【讨论】:

Bump 1 因为你不仅解决了你的问题,而且还把答案留给了下一个程序员 谢谢卢卡斯。现在我们还需要“webapp-runner”和“tomcat-embed-websocket”来在 Heroku 上使用 Websocket 吗?我正在将 webapp-runner 升级到 8.5.27.0。但是我认为如果我们可以直接在 Heroku 部署的 Tomcat 上运行 App 会更好。 当您将应用程序移至 Spring Boot 并将其作为 jar 运行时,webapp-runner 和 tomcat-embed-websocket 都是多余的 是的,我仍在使用 Spring 经典。但我认为 tomcat 8.5.30 已经集成了 tomcat-websocket.jar 所以现在它不需要: tomcat-embed-websocket 但当然仍然需要 webapp-runner 8.5.30。无论如何,谢谢

以上是关于Websocket 在 localhost 但不是 Heroku的主要内容,如果未能解决你的问题,请参考以下文章

"error": "无法连接到 websocket 端点 ws://localhost:8000/subscriptions。请检查端点 url 是不是正确。"

如何通过 ngrok 使用 ws(websocket)

WebSocket 连接到 'ws://localhost:4444/subscriptions' 失败:WebSocket 在连接建立之前关闭

javascript websocket 是不是加密任何正在发送的数据?

rxjs/webSocket - 到“ws://localhost:3000/”的 WebSocket 连接失败:连接在收到握手响应之前关闭

如何在实时服务器而不是本地主机上使用 Tornado 实现 WebSocket