Home
Document
Q&A
Video
Donate
Source Code
Code-Galaxy 云原生平台
Business
Swoole Tracker
Swoole Compiler
Login
Register
全部
提问
分享
讨论
建议
公告
开发框架
发表新帖
swoole coroutine http server 协程池模式的可行性
研究了一下协程版本的http server,发现在`start`方法中,处理请求比较粗暴,跟`go`的原生的`net/http`实现很像,一个请求就开一个协程。 swoole实现: ```c static PHP_METHOD(swoole_http_server_coro, start) { //..... while (hs->running) { auto conn = sock->accept(); if (conn) { zval zsocket; php_swoole_init_socket_object(&zsocket, conn); long cid = PHPCoroutine::create(&fci_cache, 1, &zsocket); zval_dtor(&zsocket); if (cid < 0) { goto _wait_1s; } } else { /* * Too many connection, wait 1s */ if (sock->errCode == EMFILE || sock->errCode == ENFILE) { _wait_1s: System::sleep(SW_ACCEPT_RETRY_TIME); } else if (sock->errCode == ETIMEDOUT || sock->errCode == SW_ERROR_SSL_BAD_CLIENT) { continue; } else if (sock->errCode == ECANCELED) { http_server_set_error(ZEND_THIS, sock); break; } else { http_server_set_error(ZEND_THIS, sock); php_swoole_fatal_error(E_WARNING, "accept failed, Error: %s[%d]", sock->errMsg, sock->errCode); break; } } } //..... } ``` go实现: ```go for { rw, err := l.Accept() if err != nil { select { case <-srv.getDoneChan(): return ErrServerClosed default: } if ne, ok := err.(net.Error); ok && ne.Temporary() { if tempDelay == 0 { tempDelay = 5 * time.Millisecond } else { tempDelay *= 2 } if max := 1 * time.Second; tempDelay > max { tempDelay = max } srv.logf("http: Accept error: %v; retrying in %v", err, tempDelay) time.Sleep(tempDelay) continue } return err } connCtx := ctx if cc := srv.ConnContext; cc != nil { connCtx = cc(connCtx, rw) if connCtx == nil { panic("ConnContext returned nil") } } tempDelay = 0 c := srv.newConn(rw) c.setState(c.rwc, StateNew) // before Serve can return go c.serve(connCtx) } ``` 所以go方面有了一个新idea,`valyala/fasthttp`。那swoole在实现协程版本的http server时,是不是也可以借鉴一下,预先初始化一个worker pool,分配好相关资源,处理请求时,直接从协程池获取空闲worker进行处理,省去了分配资源的过程。
发布于9月前 · 24 次浏览 · 来自
讨论
church1117
研究了一下协程版本的http server,发现在`start`方法中,处理请求比较粗暴,跟`go`的原生的`net/http`实现很像,一个请求就开一个协程。 swoole实现: ```c static PHP_METHOD(swoole_http_server_coro, start) { //..... while (hs->running) { auto conn = sock->accept(); if (conn) { zval zsocket; php_swoole_init_socket_object(&zsocket, conn); long cid = PHPCoroutine::create(&fci_cache, 1, &zsocket); zval_dtor(&zsocket); if (cid < 0) { goto _wait_1s; } } else { /* * Too many connection, wait 1s */ if (sock->errCode == EMFILE || sock->errCode == ENFILE) { _wait_1s: System::sleep(SW_ACCEPT_RETRY_TIME); } else if (sock->errCode == ETIMEDOUT || sock->errCode == SW_ERROR_SSL_BAD_CLIENT) { continue; } else if (sock->errCode == ECANCELED) { http_server_set_error(ZEND_THIS, sock); break; } else { http_server_set_error(ZEND_THIS, sock); php_swoole_fatal_error(E_WARNING, "accept failed, Error: %s[%d]", sock->errMsg, sock->errCode); break; } } } //..... } ``` go实现: ```go for { rw, err := l.Accept() if err != nil { select { case <-srv.getDoneChan(): return ErrServerClosed default: } if ne, ok := err.(net.Error); ok && ne.Temporary() { if tempDelay == 0 { tempDelay = 5 * time.Millisecond } else { tempDelay *= 2 } if max := 1 * time.Second; tempDelay > max { tempDelay = max } srv.logf("http: Accept error: %v; retrying in %v", err, tempDelay) time.Sleep(tempDelay) continue } return err } connCtx := ctx if cc := srv.ConnContext; cc != nil { connCtx = cc(connCtx, rw) if connCtx == nil { panic("ConnContext returned nil") } } tempDelay = 0 c := srv.newConn(rw) c.setState(c.rwc, StateNew) // before Serve can return go c.serve(connCtx) } ``` 所以go方面有了一个新idea,`valyala/fasthttp`。那swoole在实现协程版本的http server时,是不是也可以借鉴一下,预先初始化一个worker pool,分配好相关资源,处理请求时,直接从协程池获取空闲worker进行处理,省去了分配资源的过程。
赞
0
分享
收藏
提问
分享
讨论
建议
公告
开发框架
评论
还没有评论!
微信公众号
热门内容
- Swoole 4.8.10 已发布
- 云原生时代 PHP/Golang 项目如何实现微服务
- 异步风格的写法,如何同时开启http和websocket?
- 使用全局变量,一个worker进程同时执行多个onRequest协程问题
- HTTP服务器出发热更新,看到工作进程的worker_id也变了,但重新请求response的结果不更新
- 清空redis key
- PDO配置长连接在并发请求时候会报一个bug工作进程自动重启
- Swoole 团队云原生新项目 Code-Galaxy 介绍
- swoole 进程繁忙时候\Swoole\Process::kill($pid, SIGTERM)终止运行后出现一大堆僵尸进程
- 给官方建议 [SWOOLE LINUX 独立版本,加上PHP-event的扩展]
暂无回复的问答
- 关于openssl CURL WARNING swSSL_connect: SSL_connect(fd=69) failed. Error: error:141A318A:SSL routines:tls_process_ske_dhe:dh key too small[1|394]
- 请问那个一键协程化的代码是放外面还是set里面
- 多个模型如何进行事务异常回退?
- websocket开启wss报错
- 协程tcp服务器如何使用多进程?recv()方法接收信息,打印出来的pid一直是同一个。没用使用到多进程啊。