-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.go
126 lines (117 loc) · 3.54 KB
/
server.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package gosocket
import (
"crypto/tls"
"fmt"
"net"
"os"
"strconv"
"strings"
)
const (
kListenFd = 3
)
// Server is the class to handle incoming requests by serving and listening
type Server struct {
addr string //监听地址 listen address
signalChan chan os.Signal //接收重启信号的通道 the channel to receive restart signal
listener *Listener
}
// NewServer Create a new server
// 创建一个新的服务器
func NewServer(addr string) *Server {
server := &Server{
addr: addr,
signalChan: make(chan os.Signal),
}
return server
}
// ListenAndServe start listening and serving
// if the config isn't nil, then the tls will be enabled
// 启动服务器并开始监听,如果config不为nil,则启用TLS
func (server *Server) ListenAndServe(config *tls.Config) {
listener := server.getTCPListener(TcpApp.Config.TcpPort)
server.listener = NewListener(listener)
restartManager := GetRestartManager()
if restartManager != nil {
//记录文件描述符 record the fds
restartManager.MarkFd(kListenFd, listener)
//监听重启 set a handler to listen to restart event
restartManager.RegisterHandler(func() {
//如果子进程启动成功,主进程停止接受连接
//Stop main process from listening once the sub process has started
server.listener.Close()
})
}
//开始处理请求
//Start handling requests
server.serve(config)
}
// serve Start serving
// `config` pass nil to disable tls
func (server *Server) serve(config *tls.Config) {
pid := os.Getpid()
//Start to handle the connections
for {
acceptConn, err := server.listener.Accept()
if config != nil {
acceptConn = tls.Server(acceptConn, config)
}
if err != nil {
//if the listener is closed, then it could be the child process has started
if strings.HasSuffix(err.Error(), "use of closed network connection") {
//stop the loop
break
}
panic(err)
}
//For each connection, create a corresponding ClientConn instance to handle it
client := NewClientConn(acceptConn)
if client != nil {
//开始读和写队列
//Start the read and write queue
client.Start()
} else {
//初始化连接失败,直接关闭
//if init conn failed
acceptConn.Close()
}
}
//等待所有连接都结束后再结束进程
//Wait until all connections have closed
server.listener.WaitAllFinished()
fmt.Printf("All connection were closed, process %d is shutting down...\n", pid)
close(server.signalChan)
}
// get tcp listener from a fd or a certain address
// 从文件描述符或者指定地址监听
func (server *Server) getTCPListener(port int) *net.TCPListener {
var listener net.Listener
var err error
//Check from environment variable whether it should initialize graceful restart
//If the server has restarted gracefully
//Then the address and the port will be occupied, so the server should listen from the file that inherited from parent process
//从环境变量中判断是否为优雅重启
if os.Getenv(GracefulEnvironKey) != "" {
//fd 3 is inherited from parent process, fd 0 is stdin, fd 1 is stdout, fd 2 is stderr
//从父进程继承下来的文件描述符3监听,文件描述符012分别为stdin、stdout、stderr
file := os.NewFile(kListenFd, "")
listener, err = net.FileListener(file)
if err != nil {
panic(err)
}
} else {
address := server.addr
if port > 0 {
address += ":" + strconv.Itoa(port)
}
listener, err = net.Listen("tcp", address)
if err != nil {
panic(err)
}
}
tcpListener, ok := listener.(*net.TCPListener)
if !ok {
panic("get listener failed")
}
return tcpListener
}