V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
abcbuzhiming
V2EX  ›  Java

有没有人做过 Http, socket 混合服务器的

  •  
  •   abcbuzhiming · 2017-06-26 09:38:30 +08:00 · 7067 次点击
    这是一个创建于 2711 天前的主题,其中的信息可能已经有所发展或是发生改变。
    之前用 spring-mvc 做的 http 服务,现在需要实时推送,限于技术原因。不能使用 http2,本来打算用 websocket 的,但是发现一个问题,webscorket 在 java 下必须单独使用一个 servlet,不能和处理 http 请求的 servlet 复用,导致 session 等安全认证信息无法复用。于是就陷入僵局了,该如何改造现有这个系统?
    35 条回复    2017-06-28 11:09:18 +08:00
    janxin
        1
    janxin  
       2017-06-26 09:42:19 +08:00 via iPhone
    websocket 不是 http,你说的这些本来就不一定能用
    nutting
        2
    nutting  
       2017-06-26 09:45:56 +08:00 via Android
    用 spring 引入 mina 这种 socket 框架?
    hncqp
        3
    hncqp  
       2017-06-26 09:46:59 +08:00
    如果用 cpp 就简单了,不过 java 应该也是可以直接用 socket 的吧?
    HunterPan
        4
    HunterPan  
       2017-06-26 09:50:20 +08:00
    可以用 spring-websocket
    des
        5
    des  
       2017-06-26 10:04:09 +08:00 via Android
    如果实在没辙何不单独再写一套专门用来推送的?
    RainFinder
        6
    RainFinder  
       2017-06-26 10:10:36 +08:00
    @des 什么叫专门用来推送的?
    dthor
        7
    dthor  
       2017-06-26 10:17:06 +08:00
    如果只是服务端推送的话,可以考虑 server sent event
    ixiaohei
        8
    ixiaohei  
       2017-06-26 10:32:59 +08:00
    以前我搞过,当时选 spring 的 websocket 集成,但是不了解框架内部原理集成失败了,后面 netty 搞的 socket 长连接做的推送,用 listener 启动 netty 服务就行,另外主要 keepalive 和 tcp 粘包处理。
    ixiaohei
        9
    ixiaohei  
       2017-06-26 10:37:17 +08:00
    注意做好 keepalive 和 tcp 粘包处理,注意区分 keepalive 时候服务器推和客户端推各自的好处,主要是清除 tcp 非意外断开的链接,忘记这个学术名词叫啥了。
    abcbuzhiming
        10
    abcbuzhiming  
    OP
       2017-06-26 10:41:07 +08:00
    @des 核心问题时想复用现在的这一套用户验证机制,结果发现目前基于 session ( cookie )的验证机制没法用在新的推送上
    abcbuzhiming
        11
    abcbuzhiming  
    OP
       2017-06-26 10:43:45 +08:00
    @RainFinder 以前的交换模型是纯粹的“请求——响应”,而且用用户验证机制,基于 session ( shiro )的,要推送的话,也是必须先沿着用户身份的,所以开始才考虑 websocket,希望能无痛升级,结果发现无法复用,java 实现的 websocket 有一个要求,用于处理 websocket 请求的那个 servlet 必须是独立的,并不能复用处理普通 http 请求的那个,于是就无法复用现有的用户验证体系。就僵在这里了
    RainFinder
        12
    RainFinder  
       2017-06-26 10:55:38 +08:00
    @dthor 看了介绍,其实也就是一种长连接吧,做了事件监听
    RainFinder
        13
    RainFinder  
       2017-06-26 10:57:51 +08:00
    记得当初看 websocket 是在 header 中加入了特殊字段标识 websocket 吧,其他验证信息也是可以获取的啊,你的认证信息是怎么实现的,cookie 吗
    fzleee
        14
    fzleee  
       2017-06-26 11:14:02 +08:00
    可以这么做:
    1. 假定 http 的服务和 websocket 的服务各有一个,运行在独立的进程甚至独立的服务器上。
    2.浏览器首次建立 websocket 连接时,websocket 服务器从浏览器请求的 cookie 里面获取认证 token。
    3. websocket 服务器同步或者异步将 cookie 发送给 http 服务进行认证。认证失败则断开连接。
    vjnjc
        15
    vjnjc  
       2017-06-26 11:41:13 +08:00
    感兴趣,貌似 socket 和 http server 没法在同一个 domain(schema://host:port)下面混用吧。
    坐等高手
    wucao219101
        16
    wucao219101  
       2017-06-26 11:48:00 +08:00
    可以用 spring-websocket,另外 Session 是可以复用的。

    具体配置:
    ```
    <websocket:handlers>
    <websocket:mapping path="/websocket/chat" handler="chatWebsocketHandle" />
    <websocket:handshake-interceptors>
    <bean class="org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor" />
    </websocket:handshake-interceptors>
    </websocket:handlers>
    <bean id="yourWebsocketHandle" class="com.xxg.YourWebsocketHandle" />
    ```
    在 YourWebsocketHandle 中再通过
    ```
    String value = (String) webSocketSession.getAttributes().get("your-session-key");
    ```
    可以获取 session 的值。
    sagaxu
        17
    sagaxu  
       2017-06-26 12:17:29 +08:00
    真有意思,我记得之前用 websocket,配置文件改改就好了啊
    NUT
        18
    NUT  
       2017-06-26 12:21:29 +08:00 via iPhone
    最好的是自己用 Netty 开发一个服务端,鉴权通过目前系统实现。开发工作量不小。
    zander1024
        19
    zander1024  
       2017-06-26 12:21:50 +08:00
    。。。 没做过 java 的 .net 的做过一个简易的 。

    java 实现的 websocket 有一个要求,用于处理 websocket 请求的那个 servlet 必须是独立的,并不能复用处理普通 http 请求的那个,于是就无法复用现有的用户验证体系。就僵在这里了

    .net 里需要继承 webapi 但是貌似没有规定必须是一个独立的服务
    fzleee
        20
    fzleee  
       2017-06-26 13:10:45 +08:00
    @vjnjc 这个可以做到的。比如用一个 nginx 做服务分发
    3dwelcome
        21
    3dwelcome  
       2017-06-26 13:17:31 +08:00
    我做过,但不是用 java。判断如果 socket 开始四个字节是"GET "或"POST",就走 http 服务器。如果不是,那么就走正常的 socket 二进制协议。
    liuxu
        22
    liuxu  
       2017-06-26 13:31:16 +08:00
    你可以用 http server + workerman
    如果要处理 session 同步问题,可以做一个内网用的接口给 workerman 查询

    详细的你可以加他们官方群,群主以前也是 V2EX 玩的,技术厉害而且对新人的问题会很耐心的解答
    QQ2171775959
        23
    QQ2171775959  
       2017-06-26 13:54:33 +08:00
    用独立的服务器来做,性能比较能够满足的。
    qieqie
        24
    qieqie  
       2017-06-26 15:13:54 +08:00
    websocket 就是为了直接复用 web infrastructure 搞出来的,
    没道理不能复用,要不然和直接用 TCP 有什么区别
    yuchting
        25
    yuchting  
       2017-06-26 17:40:54 +08:00
    我知道你们都是标准前后端的。
    我歪个楼,我用的 Java + Netty 直接写底层 socket+http 协议,直接就混了。。。
    z5864703
        26
    z5864703  
       2017-06-26 17:44:21 +08:00
    直接监听一个端口实现 websocket 和 http 服务,根据请求内容格式分发到对应业务逻辑,是可以实现的
    notreami
        27
    notreami  
       2017-06-26 19:31:19 +08:00
    为什么要用 session,而不是自行弄一个 token ?
    abcbuzhiming
        28
    abcbuzhiming  
    OP
       2017-06-26 21:32:51 +08:00
    @notreami 因为已有的代码都是基于 session 的,搞个新的,你得把之前的代码全改了
    azh7138m
        29
    azh7138m  
       2017-06-26 22:25:17 +08:00 via Android
    @fzleee schema 不一样唉,一个 ws 一个是 http
    hsmocc
        30
    hsmocc  
       2017-06-27 00:38:53 +08:00 via iPhone
    没搞过 websocket,我也想知道权限如何控制的。搜了一下,ws 的 session 是可以关联页面中 httpsession 的,它们关联的时机是在 ws 握手的时候,因为 ws 的握手是通过 http 完成的。所以我感觉权限控制可以在 ws 握手时候,如果没有权限握手就失败。
    cctrv
        31
    cctrv  
       2017-06-27 00:42:51 +08:00 via Android
    socket.io
    正在使用,java 支持 https,不用 http2
    raofeng
        32
    raofeng  
       2017-06-27 11:29:42 +08:00
    我们有个项目是这样搞的。网站用 Rails 4 + socket.io.js,然后 websocket 服务器用的 nodejs+socket.io+socket.io-emitter,session 是存在 redis 里边的。
    在前端 js 里边连接 websocket 服务器的时候会把 session_id 传过去,然后 nodejs 这边就能读取到 session 的数据。
    网站需要推送的时候用一个 Ruby Gem 包 emit 一下,就实现了推送。
    colincat
        33
    colincat  
       2017-06-27 17:35:43 +08:00 via iPhone
    可以复用,以前搞过,不过当时是基于 tomcat7 做的,session 也可以复用的
    abcbuzhiming
        34
    abcbuzhiming  
    OP
       2017-06-27 23:14:58 +08:00
    @colincat 我遇到个新问题,你们当时在 tomcat 下做 websocket,是如何解决服务端超时检测这个问题的,即一段时间没有收到来自客户端的数据就断开。这个在别的 socket 实现下很简单的功能在 tomcat 下好难啊,放狗了两天,没找到肯定的答案
    colincat
        35
    colincat  
       2017-06-28 11:09:18 +08:00 via iPhone
    @abcbuzhiming 我们是自己做心跳啊,就可以判断超时
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3545 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 04:54 · PVG 12:54 · LAX 20:54 · JFK 23:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.