你可以开启服务监听任何 net.Listener 或者 http.Server 类型的实例。初始化服务器的方法应该在最后传递给 Run 函数。

Go 开发者最常用的方法是通过传递一个形如 hostname:ip 形式的网络地址来开启一个服务。Iris 中我们使用iris.Addr,它是一个 iris.Runner 类型。

// Listening on tcp with network address 0.0.0.0:8080
app.Run(iris.Addr(":8080"))

有时候你在你的应用程序的其他地方创建一个标准库 het/http 服务器,并且你想使用它作为你的 Iris web 程序提供服务。

// Same as before but using a custom http.Server which may being used somewhere else too
app.Run(iris.Server(&http.Server{Addr:":8080"}))

最高级的用法是创建一个自定义的或者标准的 net/Listener,然后传递给 app.Run

// Using a custom net.Listener
l, err := net.Listen("tcp4", ":8080")
if err != nil {
    panic(err)
}
app.Run(iris.Listener(l))

一个更加完整的示例,使用的是仅Unix套接字文件特性

package main

import (
    "os"
    "net"

    "github.com/kataras/iris/v12"
)

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 (
    // Package tcplisten provides customizable TCP net.Listener with various
    // performance-related options:
    //
    //   - SO_REUSEPORT. This option allows linear scaling server performance
    //     on multi-CPU servers.
    //     See https://www.nginx.com/blog/socket-sharding-nginx-release-1-9-1/ for details.
    //
    //   - TCP_DEFER_ACCEPT. This option expects the server reads from the accepted
    //     connection before writing to them.
    //
    //   - TCP_FASTOPEN. See https://lwn.net/Articles/508865/ for details.
    "github.com/valyala/tcplisten"

    "github.com/kataras/iris/v12"
)

// 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 using files
app.Run(iris.TLS("127.0.0.1:443", "mycert.cert", "mykey.key"))

当你的应用准备部署生产时,你可以使用 iris.AutoTLS 方法,它通过 https://letsencrypt.org 免费提供的证书来开启一个安全的服务。

// Automatic TLS
app.Run(iris.AutoTLS(":443", "example.com", "admin@example.com"))

任意iris.Runner

有时你想要监听一些特定的东西,并且这些东西不是 net.Listener 类型的。你能够通过 iris.Raw
方法做到,但是你得对此方法负责。

// Using any func() error,
// the responsibility of starting up a listener is up to you with this way,
// for the sake of simplicity we will use the
// ListenAndServe function of the `net/http` package.
app.Run(iris.Raw(&http.Server{Addr:":8080"}).ListenAndServe)

host配置

形如上面所示的监听方式都可以在最后接受一个 func(*iris.Supervisor) 的可变参数。通过函数的传递用来为特定 host 添加配置器。

例如,我们想要当服务器关闭的时候触发的回调函数:

app.Run(iris.Addr(":8080", func(h *iris.Supervisor) {
    h.RegisterOnShutdown(func() {
        println("server terminated")
    })
}))

你甚至可以在再 app.Run 之前配置,但是不同的是,这个 host 配置器将会在所有的主机上执行(我们将在稍后看到 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 字段提供的所有 hosts 你的应用服务都可以访问。

但是最常用的场景是你可能需要在运行 app.Run 之前访问 hosts,这里有2中方法来获得访问 hosts 的监管,阅读下面。

我们已经看到通过 app.Run 的第二个参数或者 app.ConfigureHost 方法来配置所有的应用程序 hosts 。还有一种更加适合简单场景的方法,那就是使用 app.NewHost 来创建一个新的 host,然后使用它的 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))

多个主机

你可以使用多个 hosts 来启动你的 iris 程序,iris.Router 兼容 net/http/Handler 函数,因此我们可以理解为,它可以被适用于任何 net/http 服务器,然而,通过使用 app.NewHost 是一个更加简单的方法,它也会复制所有的 host 配置器,并在 app.Shutdown 时关闭所有依附在特定web 服务的主机 host 。
app := iris.New()
app.Get(“/“, indexHandler)

// run in different goroutine in order to not block the main "goroutine".
go app.Run(iris.Addr(":8080"))
// start a second server which is listening on tcp 0.0.0.0:9090,
// without "go" keyword because we want to block at the last server-run.
app.NewHost(&http.Server{Addr:":9090"}).ListenAndServe()

优雅地关闭

让我们继续学习怎么接受 CONTROL + C / COMMAND + C 或者 unix kill 命令,优雅地关闭服务器。(默认是启用的)

为了手动地管理app被中断时需要做的事情,我们需要通过使用 WithoutInterruptHandler 选项禁用默认的行为,然后注册一个新的中断处理器(在所有可能的hosts上)。

示例代码:

package main

import (
    "context"
    "time"

    "github.com/kataras/iris/v12"
)
func main() {
    app := iris.New()

    iris.RegisterOnInterrupt(func() {
        timeout := 5 * time.Second
        ctx, cancel := context.WithTimeout(context.Background(), timeout)
        defer cancel()
        // close all hosts
        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)
文档更新时间: 2020-08-14 10:50   作者:kuteng