Compare commits

..
3 Commits
5 changed files with 108 additions and 12 deletions
+7 -2
View File
@@ -342,8 +342,13 @@ pub fn (mut app Hono) listen(port string) {
return return
} }
// 默认使用 picoev 高性能服务器 // 使用优化配置的 picoev 高性能服务器(支持高并发)
app.listen_picoev(port_num) app.listen_picoev_with_config(PicoevConfig{
port: port_num
timeout_secs: 120 // 高并发场景需要更长超时
keepalive_timeout: 30 // Keep-Alive 超时 30 秒
max_keepalive_req: 10000 // 单连接最大请求数
})
} }
// 使用传统 http.Server 启动(保留兼容性) // 使用传统 http.Server 启动(保留兼容性)
+69
View File
@@ -0,0 +1,69 @@
# Quick concurrent test using runspaces
$url = "http://127.0.0.1:8888/"
$concurrency = 300
$requestsEach = 20
Write-Host "Testing $url with $concurrency concurrent workers, $requestsEach requests each"
Write-Host "Total: $($concurrency * $requestsEach) requests"
$runspacePool = [runspacefactory]::CreateRunspacePool(1, $concurrency)
$runspacePool.Open()
$scriptBlock = {
param($url, $count)
$s = 0; $f = 0
for ($i = 0; $i -lt $count; $i++) {
try {
$req = [System.Net.WebRequest]::Create($url)
$req.Timeout = 30000
$resp = $req.GetResponse()
if ($resp.StatusCode -eq "OK") { $s++ } else { $f++ }
$resp.Close()
} catch {
$f++
}
}
return @{Success=$s; Failed=$f}
}
$sw = [System.Diagnostics.Stopwatch]::StartNew()
$runspaces = @()
for ($i = 0; $i -lt $concurrency; $i++) {
$ps = [powershell]::Create()
$ps.RunspacePool = $runspacePool
$ps.AddScript($scriptBlock).AddArgument($url).AddArgument($requestsEach) | Out-Null
$runspaces += @{PS=$ps; Handle=$ps.BeginInvoke()}
}
$totalSuccess = 0
$totalFailed = 0
foreach ($rs in $runspaces) {
$result = $rs.PS.EndInvoke($rs.Handle)
$totalSuccess += $result.Success
$totalFailed += $result.Failed
$rs.PS.Dispose()
}
$sw.Stop()
$runspacePool.Close()
$total = $totalSuccess + $totalFailed
$rps = [math]::Round($total * 1000 / $sw.ElapsedMilliseconds, 2)
$rate = [math]::Round($totalSuccess * 100 / $total, 2)
Write-Host ""
Write-Host "Results:"
Write-Host " Total: $total"
Write-Host " Success: $totalSuccess"
Write-Host " Failed: $totalFailed"
Write-Host " Duration: $($sw.ElapsedMilliseconds) ms"
Write-Host " RPS: $rps"
Write-Host " Success Rate: $rate%"
if ($totalFailed -eq 0) {
Write-Host "PASSED - No connection errors!" -ForegroundColor Green
} else {
Write-Host "FAILED - $totalFailed errors occurred" -ForegroundColor Red
}
+24
View File
@@ -0,0 +1,24 @@
// 测试服务器 - 用于高并发测试
module main
import hono
import net.http
fn main() {
mut app := hono.Hono.new()
// 简单的测试路由
app.get('/', fn (mut c hono.Context) http.Response {
return c.text('OK')
})
app.get('/delay', fn (mut c hono.Context) http.Response {
// 模拟一些处理延迟
return c.text('OK with delay')
})
println('测试服务器启动中...')
println('配置: timeout_secs=120, keepalive_timeout=30, max_keepalive_req=10000')
app.listen(':8888')
}
+7 -9
View File
@@ -11,12 +11,12 @@ pub:
port int = 8080 port int = 8080
host string host string
family net.AddrFamily = .ip6 family net.AddrFamily = .ip6
timeout_secs int = 8 timeout_secs int = 120 // 高并发场景需要更长超时(原 8 秒太短)
max_headers int = 100 max_headers int = 100
max_read int = 8192 max_read int = 8192
max_write int = 65536 max_write int = 65536
keepalive_timeout int = 5 keepalive_timeout int = 30 // Keep-Alive 超时延长到 30 秒
max_keepalive_req int = 1000 max_keepalive_req int = 10000 // 单连接最大请求数提升到 10000
} }
// picoev 请求上下文 // picoev 请求上下文
@@ -229,14 +229,16 @@ fn send_picoev_response(mut res picohttpparser.Response, ctx Context, response h
mut has_content_type := false mut has_content_type := false
mut has_connection := false mut has_connection := false
mut has_content_length := false
for key, value in ctx.headers { for key, value in ctx.headers {
// 跳过 Content-Length,picohttpparser 会在 body() 时自动添加
if key.to_lower() == 'content-length' {
continue
}
res.header(key, value) res.header(key, value)
key_lower := key.to_lower() key_lower := key.to_lower()
if key_lower == 'content-type' { has_content_type = true } if key_lower == 'content-type' { has_content_type = true }
if key_lower == 'connection' { has_connection = true } if key_lower == 'connection' { has_connection = true }
if key_lower == 'content-length' { has_content_length = true }
} }
if content_type := response.header.get(.content_type) { if content_type := response.header.get(.content_type) {
@@ -250,10 +252,6 @@ fn send_picoev_response(mut res picohttpparser.Response, ctx Context, response h
res.header('Content-Type', 'text/plain; charset=utf-8') res.header('Content-Type', 'text/plain; charset=utf-8')
} }
if !has_content_length {
res.header('Content-Length', response.body.len.str())
}
if !has_connection { if !has_connection {
if keepalive { if keepalive {
res.header('Connection', 'keep-alive') res.header('Connection', 'keep-alive')
+1 -1
View File
@@ -1,7 +1,7 @@
Module { Module {
name: 'hono' name: 'hono'
description: 'A high-performance V language web framework inspired by Hono.js, featuring hybrid routing, LRU cache, middleware support, and more.' description: 'A high-performance V language web framework inspired by Hono.js, featuring hybrid routing, LRU cache, middleware support, and more.'
version: '0.3.3' version: '0.3.4'
license: 'MIT' license: 'MIT'
dependencies: [] dependencies: []
} }