HTTP 主机配置
监听和服务
你可以启动服务监听任何类型为 net.Listener
乃至 http.Server
实例。服务器的初始化方法应该是在最后, 通过 Run
方法执行。
Go 开发者使用最常用的方法是通过使用包含「hostname:ip」的网络地址来为服务器提供服务。在 Iris 中,我们使用类型为 iris.Runner
的 iris.Addr
。
// 在 Tcp 上监听网络地址 0.0.0.0:8080
app.Run(iris.Addr(":8080"))
有时你会创建一个标准的 net/http 服务在你的应用中,并且使用它为你的 Iris 网站提供服务。
// 和前面一样,但是使用自定义 http.Server 也可以在其他地方运行
app.Run(iris.Server(&http.Server{Addr:":8080"}))
最先进的使用方法是创建一个自定义或者标准的 net.Listener
并传递给 app.Run
// 使用自定义 net.Listener
l, err := net.Listen("tcp4", ":8080")
if err != nil {
panic(err)
}
app.Run(iris.Listener(l))
来看一个更完整的例子,使用仅在 Unix 上的 socket 文件特性
package main
import (
"os"
"net"
"github.com/kataras/iris"
)
func main() {
app := iris.New()
// UNIX socket
if errOs := os.Remove(socketFile); errOs != nil && !os.IsNotExist(errOs) {
app.Logger().Fatal(errOs)
}
l, err := net.Listen("unix", socketFile)
if err != nil {
app.Logger().Fatal(err)
}
if err = os.Chmod(socketFile, mode); err != nil {
app.Logger().Fatal(err)
}
app.Run(iris.Listener(l))
}
UNIX 和 BSD 主机可以接受复用端口这一特性带来的好处
package main
import (
// tcplisten 包提供可定制的 TCP net.Listener以及各种性能相关选项:
//
// - SO_REUSEPORT。这个选项允许在多 CPU 服务器上线性扩展服务器性能。
// 查看 https://www.nginx.com/blog/socket-sharding-nginx-release-1-9-1/ 了解详情.
//
// - TCP_DEFER_ACCEPT。这个选项期望服务器在写入前从已接受的连接中读取。
//
// - TCP_FASTOPEN. 查看 https://lwn.net/Articles/508865/ 获取详情
"github.com/valyala/tcplisten"
"github.com/kataras/iris"
)
// go get github.com/valyala/tcplisten
// go run main.go
func main() {
app := iris.New()
app.Get("/", func(ctx iris.Context) {
ctx.HTML("<h1>Hello World!</h1>")
})
listenerCfg := tcplisten.Config{
ReusePort: true,
DeferAccept: true,
FastOpen: true,
}
l, err := listenerCfg.NewListener("tcp", ":8080")
if err != nil {
app.Logger().Fatal(err)
}
app.Run(iris.Listener(l))
}
HTTP/2 和安全
如果你有签名文件秘钥,你可以基于这些认证秘钥用 iris.TLS
来启动 https
服务
// TLS 使用文件例子
app.Run(iris.TLS("127.0.0.1:443", "mycert.cert", "mykey.key"))
当你使用由 letsencrypt.org 免费提供的自动认证安全服务时,你应该在你的应用即将用于生产环境时使用 iris.AutoTLS
这个方法。
// 自动 TLS
app.Run(iris.AutoTLS(":443", "example.com", "admin@example.com"))
一些 iris.Runner
有些时候你也许想要监听一些特殊的东西,它们的类型不属于 net.Listener
。你可以使用 iris.Raw
,但是你要自己完成这个方法哟
// 使用任何 func() 差错,
// 使用这种方式启动一个监听器,是要你自己负责的,
// 简单起见,我们使用 `net/http` 包的 ListenAndServe 方法
app.Run(iris.Raw(&http.Server{Addr:":8080"}).ListenAndServe)
主机配置程序
以上所有的监听都是接受 func(*iris.Supervisor)
为最后一个变量。 可以通过这些函数传递的特定主机来添加配置程序。
举个例子,我们现在要在服务器关闭时,触发一个我们自己添加的回调
app.Run(iris.Addr(":8080", func(h *iris.Supervisor) {
h.RegisterOnShutdown(func() {
println("server terminated")
})
}))
你甚至可以在 app.Run
这个方法前做点东西,但是不同之处在于这些主机配置程序将会在所有应用服务的主机上运行。(通过 app.NewHost
我们将会立马看到)
app := iris.New()
app.ConfigureHost(func(h *iris.Supervisor) {
h.RegisterOnShutdown(func() {
println("server terminated")
})
})
app.Run(iris.Addr(":8080"))
Run
方法完成后,你就可以访问由 Application#Hosts
提供应用程序的所有主机。
但是最常见的场景是你需要在 app.Run
方法执行前访问主机,这有两种方式让你访问主机管理器,阅读以下内容。
我们已经看到通过 app.Run
或者 app.ConfigureHost
的第二个参数来配置所有的应用。还有一种更适合简单场景的方法,就是使用 app.NewHost
来创建一个新的主机并使用 Serve
或者 Listen
函数中的一个通过 iris#Raw
启动应用。
注意这种方式需要额外引入 net/http
包。
示例代码:
h := app.NewHost(&http.Server{Addr:":8080"})
h.RegisterOnShutdown(func(){
println("server terminated")
})
app.Run(iris.Raw(h.ListenAndServe))
多主机
你可以使用多个服务器去服务你的 Iris web 应用程序,iris.Router
与 net/http/Handler
函数是兼容的,因此,那就可以理解,它可以用于任何 net/http
服务,然后还有一种更简单的方式,那就是,通过使用 app.NewHost
,它也可以复制所有的主机配置并且使用 app.Shutdown
去关闭所有附加到特定的 web 应用程序上的主机。
app := iris.New()
app.Get("/", indexHandler)
// 在不同的 gorotuine 中运行,为了不阻塞主要的 goroutine
go app.Run(iris.Addr(":8080"))
//开启第二个服务,它正在监听 tcp 0.0.0.0:9090,
//没有用 go 关键字,是因为我们想在最后一次服务运行的时候,让他阻塞。
app.NewHost(&http.Server{Addr:":9090"}).ListenAndServe()
关闭服务(优雅的)
让我们继续学习如何捕获 CONTROL + C / COMMAND + C 或 unix kill 命令并优雅地关闭服务器。
在 CONTROL + C/COMMAND+C 命令或者当 发送 ENABLED BY-DEFAULT 的 kill 命令时候,去优雅的关闭主机
为了手动管理应用程序中断时要执行的操作,我们必须使用选项「WithoutInterruptHandler」来禁用默认行为并注册新的中断处理程序(全局,跨所有可能的主机)。
代码:
package main
import (
"context"
"time"
"github.com/kataras/iris"
)
func main() {
app := iris.New()
iris.RegisterOnInterrupt(func() {
timeout := 5 * time.Second
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
// 关闭所有主机
app.Shutdown(ctx)
})
app.Get("/", func(ctx iris.Context) {
ctx.HTML(" <h1>hi, I just exist in order to see if the server is closed</h1>")
})
app.Run(iris.Addr(":8080"), iris.WithoutInterruptHandler)
}
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
推荐文章: