hprose / hprose-swoole

Hprose asynchronous client & standalone server based on swoole

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

在使用特定设备访问接口的情况下,swoole服务会卡住,不再接收其它接口的访问请求

zhan3333 opened this issue · comments

commented

一句话描述

  • 在使用hprose-swoole 2.0.7搭建服务,用户使用iphone 6s QQ浏览器访问服务发布的接口时,接口会停止服务,其它任何方式的访问接口都无返回值,重启服务后恢复正常。
  • 对于这个问题,我目前的解决办法是使用hprose 1.5.6版本。
  • 希望确认问题后与我联系,这个bug稳定重现。

bug重现环境

bug出现环境:

  • 服务端
    • 使用库:hprose-swoole: 2.0.7/2.0.11
  • 客户端
    • 操作系统: apple 6s
    • 浏览器:qq浏览器 7.0.0.2825
  • 操作
    • 使用上述客户端,通过hprose-html5访问接口,处理该次请求的服务器进程即拒绝包含这次服务的以后所有服务,只有通过重启服务解决。

异常数据头信息

{
    "host":"192.168.2.67:8003",
    "origin":"http://192.168.2.102:8080",
    "accept-encoding":"gzip, deflate",
    "connection":"keep-alive",
    "accept":"*/*",
    "user-agent":"Mozilla/5.0 (iPhone 6sp; CPU iPhone OS 10_1_1 like Mac OS X) AppleWebKit/602.2.14 (KHTML, like Gecko) Version/10.0 MQQBrowser/7.2 Mobile/14B100 Safari/8536.25 MttCustomUA/2 QBWebViewType/1",
    "content-length":"0",
    "referer":"http://192.168.2.102:8080/hprose-web/index.html?_ijt=g21st5f9d04he2p1dd96tbhgoh",
    "accept-language":"zh-cn"
}

测试

测试目标

  • 使用hprose-swoole库的不同版本
  • 使用hprose库的不同版本
  • 使用不同浏览器
  • 使用不同操作系统
  • 使用不同方式访问: hprosehttp
  • 模拟异常数据头信息进行访问

测试结果

  1. 使用hprose-swoole在2.0.7与2.0.11两个版本中,使用apple 6s qq浏览器通过hprose访问,将出现这个问题。其中2.0.11为最新版本。
  2. 使用hprose版本为1.5.6时,任意浏览器或访问方式均访问正常。1.5.61.*.* 最后一个版本。其中1.*.*自带swoole服务的创建,而到了2.*.*时,不带swoole服务的创建,已经转向了hprose-swoole库中。
  3. 使用arc工具模拟异常包的头信息发送,bug未重现。
  4. 红米note3上的qq浏览器,使用hprose访问接口,bug未出现。
  5. 使用apple 6s qq浏览器通过http访问接口,无bug出现。
  6. 在服务器获取到异常包时,手动unsetcontent-length头信息,无效果。

重现方式

  • 服务端使用下面测试代码中的 hprose-swoole-2.0.11 代码
  • web端使用下面的 web端代码代码
  • 使用 apple 6s qq浏览器访问web端页面,此时bug重现。

结论

  • 这是存在于hprose-swoole库中的一个bug。
  • 目前只发现在使用iphone 6s qq浏览器通过hprose方式访问hprose-swoole的服务时,会出现此bug。
  • 因为发现异常包与正常包之间,差别在于:只存在于异常包的content-length: 0,故临时解决办法,在服务器获取到content-length: 0的包时,不做处理直接return。
  • 长远解决办法
    • 提交bug到hprose-swoole的git issues中,等待bug确认并修复。
    • hprose-swoole库更换为1.5.6版本的hprose

附测试代码

web端代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>测试</title>
    <script type="text/javascript" src="hprose/hprose-html5.src.js"></script>
    <script src="//cdn.jsdelivr.net/eruda/1.0.5/eruda.min.js"></script>
    <script>eruda.init();</script>
</head>
<body>
<div id="retData"></div>
<script type="text/javascript">
    var retData = document.getElementById('retData')
    var url = 'http://192.168.2.67:8089'    // 服务地址
    var client = hprose.Client.create(url)
    // 访问服务
    client.invoke('hello', [], function (data) {
        console.info('success', data)
        retData.textContent = data
    },function (error) {
        console.info('error', error)
        retData.textContent = error
    })

</script>
</body>
</html>

hprose-swoole-2.0.11 代码

composer.json

{
    "require": {
        "hprose/hprose-swoole": "2.0.11"
    }
}

SwooleServer.php

<?php
require_once "./vendor/autoload.php";
use Hprose\Swoole\Server;
function hello($name) {
    return "Hello $name!";
}
$url = "http://0.0.0.0:8089";
echo "url is $url" . PHP_EOL;
$server = new Server($url);
$server->addFunction('hello');
$server->start();

hprose-swoole-2.0.7 代码

composer.json

{
    "require": {
        "hprose/hprose-swoole": "2.0.7"
    }
}

SwooleServer

<?php
require_once "./vendor/autoload.php";
use Hprose\Swoole\Server;
function hello($name) {
    return "Hello $name!";
}
$url = "http://0.0.0.0:8086";
echo "url is $url" . PHP_EOL;
$server = new Server("http://0.0.0.0:8086");
$server->addFunction('hello');
$server->start();

hprose-1.5.6

composer.json

{
  "require": {
    "hprose/hprose": "1.5.6"
  }
}

SwooleServer.json

<?php
require_once "./vendor/autoload.php";
use Hprose\Swoole\Server;
function hello($name) {
    return 'Hello ' . $name;
}
$url = "http://0.0.0.0:8087";
echo "url is $url" . PHP_EOL;
$server = new Hprose\Swoole\Server($url);
$server->addFunction('hello');
$server->start();

使用 hprose 1.5.6 时,使用的 swoole 扩展是哪个版本的?跟使用 hprose-swoole 2.0.x 时使用的 swoole 扩展是否是相同版本?我看代码中,1.5.6 和 2.0.x 中获取请求都是使用的 $request->rawContent(); 并没有发现在获取请求数据时,有什么不同之处。

commented

1.5.6与2.0.*版本均使用swoole 1.8.9版本。以上测试中,只更改了库的版本,并没有更换测试环境其他东西。

如果仅仅是头部异常会触发这个问题的话,那应该模拟异常包的头信息发送时也会导致 bug 重现才对,但是看你的描述,貌似只有用 apple 6s + 7.0.0.2825 QQ 浏览器才会重写该 bug,这种情况下,我没办法定位 bug 的位置啊。

commented

对,特定设备与浏览器下才会重现这个bug,所以我定位不到,只能根据头信息的差别来去掉异常访问。是异常访问->差别头信息,而不是差别头信息->bug。重现方式已经提供了,也就是在其它任何使用了高版本的hprose-swoole服务中,能够有稳定的办法中止掉服务。这个bug是必须解决。