Iris 默认不支持多端口监听,因其 app.Run() 底层复用单个 http.Server 实例并阻塞主 goroutine;需禁用自动启动、调用 app.Build() 后,手动创建多个 http.Server 并并发 Serve(),且必须复用 app.Handler()。

为什么 Iris 默认不支持多端口监听
Iris 的 app.Run() 底层调用的是 Go 标准库的 http.Server.Serve(),一次只能绑定一个 net.Listener。直接多次调用 app.Run() 会 panic:"http: Server closed" 或 "address already in use" —— 因为默认复用同一个 http.Server 实例,且主 goroutine 被阻塞。
用 app.ConfigureHost() + 手动启动多个 http.Server
核心思路是:禁用 app.Run() 的自动启动,改用 app.Build() 构建服务实例,再为每个端口创建独立的 http.Server 并并发运行。
-
app.ConfigureHost()必须在app.Build()前调用,用于定制底层http.Server(如设置ReadTimeout、IdleTimeout) - 每个端口需单独
net.Listen("tcp", ":8080"),不能共用 listener - 必须显式传入
app.Handler()(不是app本身),否则路由不生效 - 建议用
sync.WaitGroup或errgroup.Group管理多个 server 的生命周期
package main
import (
"log"
"net/http"
"net"
"github.com/kataras/iris/v12"
)
func main() {
app := iris.New()
app.Get("/ping", func(ctx iris.Context) {
ctx.WriteString("pong")
})
// 阻止自动启动
app.ConfigureHost(func(su *iris.Supervisor) {
su.DisableAutoFire = true
})
app.Build() // 必须调用,否则 Handler() 未初始化
servers := []struct {
addr string
port int
}{
{":8080", 8080},
{":9090", 9090},
{":3000", 3000},
}
for _, s := range servers {
listener, err := net.Listen("tcp", s.addr)
if err != nil {
log.Fatal(err)
}
server := &http.Server{
Addr: s.addr,
Handler: app.Handler(),
}
go func() {
log.Printf("Server listening on %s", s.addr)
if err := server.Serve(listener); err != http.ErrServerClosed {
log.Fatal(err)
}
}()
}
// 阻塞主 goroutine,避免退出
select {}
}
多个 Iris 实例共享中间件或配置时怎么避免重复初始化
如果需要完全隔离的服务(比如不同域名、不同 TLS 配置、不同中间件栈),应创建多个独立 iris.Application 实例;但若只是端口不同、逻辑相同,更推荐复用同一 app.Handler(),而非复制 app。
- 不要对每个端口都 new 一个
iris.New()—— 路由、中间件、模板等会重复注册,内存浪费且行为不可控 - 静态资源路径(
app.HandleDir())、错误处理器(app.OnErrorCode())等全局配置,在app.Build()后已固化,可安全复用 - 若需差异化中间件(如 :9090 开启 CORS,:8080 不开),应在 handler 内部用
ctx.Path()或自定义 header 分流,而非拆成多个 app
HTTPS 和 HTTP 同时监听的注意事项
HTTP 和 HTTPS 不能共用同一个 http.Server,必须分两个 server;且 app.TLS() 是阻塞式封装,不能和普通 Run() 混用。
- HTTPS server 必须用
server.ListenAndServeTLS("cert.pem", "key.pem"),不能用Serve()+net.Listen()(除非自己 wrap TLS listener) - 证书文件路径必须存在且可读,否则 panic 报错:
open cert.pem: no such file or directory - 若要重定向 HTTP 到 HTTPS,需额外起一个只做 301 跳转的轻量 server,监听 :80 并返回
http.Redirect(..., http.StatusMovedPermanently)
app.Build() 的调用时机和 app.Handler() 的复用边界 —— 漏掉 Build() 会导致 handler 为空,而误以为要 new 多个 app 则会引发路由冲突和内存泄漏。


















