B/S 架构下后端能否建立 TCP 长连接?

请问各位大大,有个问题我有点想不明白
前提:B/S 网站结构下,现在我在另一台服务器上实现了 ES 搜索,目前是以接口方式提供给原网站,(客户在网页发起搜索,传到 php 服务端php 服务端 再发起 curl 请求接口,获取数据后返回给前端)但是现在需求是一次关键词搜索会搜索十来个业务线(一个业务线对应一个索引),且业务线下还有几个分类。目前我还是用接口,接收数据后,循环搜索 ES 然后返回给 php 服务端,但是感觉这样的话效率估计会有点慢。
优化策略:目前我想到的是在 ES搜索服务端swoole 扩展建立一个 tcp server, php 服务端 不再访问接口,而访问该 tcp server, 也不一次发送所有业务线的搜索及筛选条件,而是循环发送,发送的同时接收 tcp server 的响应,双工通信。
但是我实验了很多次,发现了一些问题:

  1. php 服务端 建立的 stream client 请求数据后,fclose() 无法关闭该链接,会 一直链接不返回直到超时,用 php 的 socket 函数也是这样。除非服务端发送数据后立马断开链接,但是 swoole 文档告诫不要发送后立即断开,但是我也不知道服务端该何时断开这样链接(什么事件回调,或其他什么...),但客户端却又无法断开,所以卡住了。
  2. php 服务端 如何循环发送的同时接收 tcp server 的数据啊。
  3. 这种架构下,这样的优化策略能实现吗?能有作用吗?
    php 服务端请求 ES tcp server 部分代码
    $streamClient = stream_socket_client("tcp://{$tcpHost}:{$tcpPort}", $errno, $errstr);
    // 该数组是所有业务线的分类结构,及每条业务线要搜索的关键字,单个元素对应一条业务线
    $categoriesFilter = [];
    foreach ($categoriesFilter as $categoryFilter) {
        fwrite($streamClient, json_encode($categoryFilter);
    }

    然后我就不知道该如何实现写的同时接收数据了。并保证每条业务线的数据都发送了,也收到响应了。
    ES tcp server 部分代码

    $searchServer = new \swoole_server('0.0.0.0', 9501);
    $searchServer->on('connect', function (\Swoole\Server $server, $fd) {
            dump($server->connection_info($fd));
        });
    $searchServer->on('receive', function (\Swoole\Server $server, $fd, $reactor_id, $request) {
    global $keyword;
    global $elastic;
    $requestArray = json_decode($request, true);
    $keyword = $requestArray;
    // es 搜索代码
    $result = $elastic->indexFilterAndSearch($requestArray);
    $server->send($fd, json_encode($result));
    });
    $searchServer->on('WorkerStart', function (\Swoole\Server $server, $work_id) {
    global $elastic;
    $elastic = new ElasticSearch;
    });
    $searchServer->on('close', function (\Swoole\Server $server, $fd, $reactorId) {
    global $keyword;
    $clientConnectionInfo = $server->connection_info($fd);
    file_put_contents('swoole_log.log', json_encode([
        'connectionTime' => date('Y-m-d H:i:s', $clientConnectionInfo['connect_time']),
        'closeTime' => date('Y-m-d H:i:s'),
        'keyword' => $keyword,
        'ip' => $clientConnectionInfo['remote_ip']
    ]) . PHP_EOL, FILE_APPEND);
    });
    $searchServer->start();

    求各位大佬指点一下,这样优化行不行?如果行的话,我上面的两个问题该从那方面,那里入手解决啊。。。

《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 2

疑问,为啥建立连接后,如果不传输数据可以直接使用 fclose() 关闭连接,但是一旦调用了 fwrite() 则使用 fclose() 无法关闭连接。求解

5年前 评论

websocket 了解一下!直接用websocket去跨域访问es服务器就行没必要再走php服务器

5年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!