重启实现思路
通过go 1.8 提供的net/http/server.go
中的 func (srv *Server) Shutdown(ctx context.Context) error
方法可以实现运行中的Web服务关闭。
如下:
- 监听端口
- 启动服务
- 关闭后
- 再次启动: 监听端口,启动服务
package main
import (
"context"
"io"
"log"
"net"
"net/http"
"time"
)
func off(w http.ResponseWriter, r *http.Request) {
_, _ = io.WriteString(w, "Hello now server will down!\n")
go func() {
if err := server.Shutdown(context.TODO()); err != nil {
panic(err)
}
}()
}
func hello(writer http.ResponseWriter, request *http.Request) {
_, _ = io.WriteString(writer, "Hello World!\n")
}
var server *http.Server
func main() {
// 配置HTTP映射
http.HandleFunc("/", hello)
http.HandleFunc("/off", off)
// 启动服务
log.Printf("main: starting HTTP Server")
ln, err := net.Listen("tcp", ":8080")
if err != nil {
panic(err)
}
server = &http.Server{}
if err = server.Serve(ln); err != http.ErrServerClosed{
panic(err)
}
log.Println("Server Down.")
log.Println("After 3 second Restart...")
time.Sleep(time.Second * 3)
log.Println("Server Run.")
// 再次启动服务
ln, err = net.Listen("tcp", ":8080")
if err != nil {
panic(err)
}
server = &http.Server{}
if err = server.Serve(ln); err != http.ErrServerClosed{
panic(err)
}
}
通过使用curl,验证
curl -v 127.0.0.1:8080/off
输出
说明服务已经成功的关闭
通过使用curl,验证可以返还Hello world!
curl -v 127.0.0.1:8080/
服务关闭后
Web服务的关闭并不会导致已经建立的连接关闭
我们稍微调整一下上面的程序,并增加一个回声接口
func echo(w http.ResponseWriter, r *http.Request) {
hj, _ := w.(http.Hijacker)
conn, bufrw, err := hj.Hijack()
if err != nil {
panic(err)
}
_, _ = bufrw.WriteString("Echo [OK]\r\n")
_ = bufrw.Flush()
go io.Copy(conn, conn)
}
该接口在创建之后将会持续保持连接,然后把从连接中读取到的数据发回发送方。
main函数调整如下:
var server *http.Server
func main() {
// 配置HTTP映射
http.HandleFunc("/", hello)
http.HandleFunc("/off", off)
// 回显程序
http.HandleFunc("/echo", echo)
// 启动服务
log.Printf("main: starting HTTP Server")
ln, err := net.Listen("tcp", ":8080")
if err != nil {
panic(err)
}
server = &http.Server{}
if err = server.Serve(ln); err != http.ErrServerClosed{
panic(err)
}
log.Println("Web Server Down, Program still running...")
select{}
}
为了测试需要我们还需要一个类似于telnet的测试程序,功能就是建立连接之后读取收到的数据并打印,通过用户输入数据并发出。
如下:
func main() {
conn, err := net.Dial("tcp", "127.0.0.1:8080")
if err != nil {
panic(err)
}
reqStr := "GET /echo HTTP/1.1\r\n" +
"Host: 127.0.0.1\r\n" +
"User-Agent: GoNet\r\n" +
"Accepect: */*\r\n" +
"\r\n"
_, _ = conn.Write([]byte(reqStr))
go func() {
_, _ = io.Copy(os.Stdout, conn)
}()
scanner := bufio.NewReader(os.Stdin)
for {
msg, err := scanner.ReadBytes('\n')
if err == io.EOF {
break
}
_, _ = conn.Write(msg)
}
}
首先启动服务器
启动测试程序,然后随便发送一条消息验证回音程序是否已经在运行
我们通过telnet 调用服务关闭接口
curl -v 127.0.0.1:8080/off
可以看到服务已经关闭,打印了我们的文字
此时你再访问 curl -v 127.0.0.1:8080/
是没有任何返还值的,因为Web服务已经关闭。
但是此时我们的回音测试程序还在运行,我们可以试下回音程序是否能够工作
从测试的结果上来说我们的回声程序仍然在正常工作,连接仍然可用。