Iris HTTP 主机配置

监听和服务

你可以启动服务监听任何类型为 net.Listener 乃至 http.Server 实例。服务器的初始化方法应该是在最后, 通过 Run 方法执行。

Go 开发者使用最常用的方法是通过使用包含「hostname:ip」的网络地址来为服务器提供服务。在 Iris 中,我们使用类型为 iris.Runneriris.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.Routernet/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)
}

下一章:iris 配置信息和文件

iris 所有的配置项都有默认值,所有默认配置都会在当使用 iris.New() 时设置。 配置项在监听函数调用之前是无效的,它需要作为 iris.Application.Run 函数的参数传入。Run 配置信息参 ...