HttpServer [编辑本页]

swoole-1.7.7增加了内置Http服务器的支持,通过几行代码即可写出一个异步非阻塞多进程的Http服务器。

$http = new swoole_http_server("127.0.0.1", 9501);
$http->on('request', function ($request, $response) {
    $response->end("<h1>Hello Swoole. #".rand(1000, 9999)."</h1>");
});
$http->start();

swoole_http_server对Http协议的支持并不完整,建议仅作为应用服务器。并且在前端增加Nginx作为代理

通过使用apache bench工具进行压力测试,在Inter Core-I5 4核 + 8G内存的普通PC机器上,swoole_http_server可以达到近11万QPS。远远超过php-fpm,golang自带http服务器,node.js自带http服务器。性能几乎接近与Nginx的静态文件处理。

ab -c 200 -n 200000 -k http://127.0.0.1:9501

使用Http2协议

  • 需要依赖nghttp2库,下载nghttp2后编译安装
  • 使用Http2协议必须开启openssl
  • 需要高版本openssl必须支持TLS1.2ALPNNPN
./configure --enable-openssl --enable-http2

设置http服务器的open_http2_protocoltrue

$serv = new swoole_http_server("127.0.0.1", 9501, SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL);
$serv->set([
    'ssl_cert_file' => $ssl_dir . '/ssl.crt',
    'ssl_key_file' => $ssl_dir . '/ssl.key',
    'open_http2_protocol' => true,
]);

nginx+swoole配置

server {
    root /data/wwwroot/;
    server_name local.swoole.com;

    location / {
        proxy_http_version 1.1;
        proxy_set_header Connection "keep-alive";
        proxy_set_header X-Real-IP $remote_addr;
        if (!-e $request_filename) {
             proxy_pass http://127.0.0.1:9501;
        }
    }
}

在swoole中通过读取$request->header['x-real-ip']来获取客户端的真实IP


  • vergil

    碉堡了

  • 小eye

    求一份swoole_http_server与nginx反向代理搭配的例子

  • oodece

    我居然把 end 看成了 send ,怎么跑都报错

  • Jack

    哈哈,激动呢。

  • 井田 何渐兴

    厉害,支持!!

  • 愚安

    测了一下 确实比node的要快好多

  • jhl

    WARN swReactorThread_onReceive_http_request: get protocol failed. 这是什么错误啊

  • chris_guojn

    把打印去掉,因为你打印的东西没有报的错

  • 小马哥

    是不是只有用nginx代理 HttpServer服务才可以用呢

  • kenshin

    。。。。我也是

  • 键盘侠

    这个nginx的配置有点问题吧,那个location里面的if判断是不是应该不要呢。

  • 木子

    [闭嘴]proxy_pass 是不能放在 if 里面的吧! nginx[5555]: Starting nginx: nginx: [emerg] "proxy_set_header" directive is not allowed here in ...

  • 开飞机的小蜗牛

    到处都看到在宣传 Swoole 性能比其他语言实现(nodejs golang)要高,都是异步,为什么 Swoole 性能就会比其它的高呢,希望有人从代码或者实现上面分析下。

  • Rango-韩天峰

    Swoole的高性能是因为Server逻辑代码全部使用C语言实现,并且使用了全内存缓存和异步IO。Node.js默认是单线程的无法利用全部CPU,Golang的协程调度本身有一定性能消耗。

  • 渡边至秦

    proxy_http_version 1.1;proxy_set_header Connection "keep-alive";放在if语句里面会报错

  • 骑龟上阵

    onRequest 收到一个http请求是不是就会分配一个worker进程处理 ?然后这个worker进程在 response->end 前都一直被占用不能再处理别的请求了?

  • 郝多

    ERROR swPort_onRead_http(:417): recv from connection#17 failed. Error: Software caused connection abort[113] 这是什么鬼?

  • 郝多

    swoole 1.8.5beta,cygwin下 ,http_server 用ab发送10w次ok,但是通过chrome连续刷新几十次后后会导致服务器端不停滚动抛错“ERROR swPort_onRead_http(:417): recv from connection#14 failed. Error: Software caused connection abort[113].”,不中断程序,滚动不停,咋回事?用的官网例子

  • 郝多

    ab -k:keep alive,保持连接相当于长连接进行ab压力测试,,这样得出测试结果没说服力

  • 韦元晓

    的确 -k 参数挺耍流氓的, 实际上的高并发是多用户的高并发,而不是一个连接内多个请求的并发。测试要根据实际情况来进行。

  • 韦元晓

    我认为目前要推广swoole,就要解决广大PHPer的痛点,我认为痛点在于是否可以使用swoole调用目前各种现成的php 服务程序(基于各种框架tp laravel symphony...等),可以不再依赖于Apache/nginx, 而同时又能无缝使用swoole的高效率,异步等特点。

    毕竟,用swoole在web服务之外写一些服务程序,属于锦上添花功能,并非第一痛点。

    也许我孤陋寡闻了。没有完全理解swoole的思想及能力。不知道博主怎么看。

  • 半夏

    说的很有道理,支持一下

  • 宗霖

    我也认为这个是一个比较好的方案。在http的环节,如何无缝的和yii tp laravel 框架结合而不依赖于nginx,实现类似node js 或者golang 及openresty 常作的业务层,是一个比较好的方向。对比了swoole和wokerman,都主要集中在了socket server上。

  • Rango-韩天峰

    压测必须要增加-k参数,不使用-k,那么所有程序很大部分消耗都在处理连接的connect/close上,不同软件的性能差异降低了。增加-k参数排除了connect/close的消耗,剩下就是对比不同软件的处理能力了。

  • 龙飞_无锡

    用nginx+swoole配置的方式跑ab 到nginx,在本机还是产生大量的127.0.0.1:9501 TIME_WAIT 连接,直接ab到127.0.0.1:9501 没有这个问题,ab通过nginx proxy到另外一个nginx也没问题

  • 晕咗

    应该是有人需要这个的(用纯 swoole_http_server 启动web然后转发给php-fpm处理,支持DOCKER): https://github.com/cmptech/cmp_app_server/blob/master/cmp_app_server.php https://github.com/cmptech/cmp_app_server/blob/master/PhpfpmClient.php https://github.com/cmptech/cmp/blob/master/app_root/webroot/cmp_root_controller.php

  • 晕咗

    看我下面的评论。能解决你说的问题。我们自己的项目就在用

  • 鬼眼

    遇到一个比较棘手的问题。我们打算在正式环境里使用swoole的http server。 正常的get post请求swoole可以相应。 但是如果使用 purge 这类非正常http头来请求。swoole不回应,也不断开连接。 这容易被攻击。应该断开链接吧?

  • xxx

    同求,文档太少了,轻描淡写的就过去了

  • 海诺

    地址换了

  • 马驰

    放在大括号外面来即可

  • keaixiaou

    基于swoole的异步非阻塞框架zapi:欢迎大神们提意见https://github.com/keaixiaou/zapi

  • TT

    go 的gc一直在优化,恐怖现在再来一次对比,swoole比不上咯~

  • Rango-韩天峰

    GC不是性能瓶颈,主要开销在于协程的调度。

  • TT

    协程的调度开销相对于线程和进程已经小很多了吧,当swoole在业务上需要实现高并发的时候底层是通过什么调度呢,例如一个请求给到worker处理的时候,里面涉及到很多io操作,go是通过派生协程实现异步处理,swoole可以通过几个异步函数进行处理,也可以通过add_event_loop进行异步处理,两者的开销,哪个大一点

  • keaixiaou

    请求有post参数,但是request 里没有,什么样的情况下会出现这种情况,nginx版本1.4.4,swoole 1.9.1

  • 郎明

    这个nginx简直就是误导人,文件不存在转到swoole处理什么啊!

  • 小六HI

    gitHub地址已经不存在了,能不能重新分享地址?

  • 奔跑吧!羊驼!

    TP兴许有问题,不过laravel symfony,尤其是symfony,别说无缝了,简直是救星,symfony最大问题在于初始化过程大量的装载和配置解析非常浪费性能,而且每次执行都要重复一次,虽然有缓存,但是毕竟问题还在,这个就完美解决而且平滑过度,主要是现在swoole看到实际商用的项目不多,自己玩玩还好,真正上公司项目就是怕到时候会不会有什么意料之外的问题。

  • oldchiken

    在这里处理php会更快吗????

  • 借口!/ty

    他能应用在生产环境,配合nginx当服务器用吗

  • jianrun

    运行 /Applications/XAMPP/xamppfiles/bin/ab -n 500 -c 5 http://127.0.0.1:8080/ 后 报错 ERROR swReactorKqueue_del(:238): kqueue->del(211, SW_EVENT_WRITE) failed. Error: No such file or directory[2].

    code: //创建服务 $http = new Swoole\Http\Server($config['server']['ip'], $config['server']['port']); $http->set([ 'worker_num' => 100, 'max_request' => 10, // 'daemonize' => true, // 'pid_file' => ROOTPATH . '/server.pid', ]);

    //监听请求 $http->on('request', function ($request, $response) { return; }); 什么业务逻辑都没写就报错,是怎么回事

  • 胜不了的是自己

    使用SwooleHttpServer第一次请求OK,第二次就打不开,并且报下面这个:

    [2017-10-20 09:55:42 #12491.0]  WARNING swConnection_sendfile (ERROR 505): length or offset is invalid.
    [2017-10-20 09:55:42 #12491.0]  WARNING swConnection_sendfile (ERROR 505): length or offset is invalid.
    [2017-10-20 09:55:42 #12491.0]  WARNING swConnection_sendfile (ERROR 505): length or offset is invalid.
    [2017-10-20 09:55:42 #12491.0]  WARNING swConnection_sendfile (ERROR 505): length or offset is invalid.
    [2017-10-20 09:55:42 #12491.0]  WARNING swConnection_sendfile (ERROR 505): length or offset is invalid.
    

    发现的现象: 1. firefox浏览器 勾上 禁用缓存 也没问题。 2. 在每个静态文件后面加一个随机版本号,也没问题。

    这是什么问题呀?怎么处理?总不能真在每个静态文件后面加一个随机版本号吧。