-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathserver.go
151 lines (122 loc) · 3.18 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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package rpc
import (
"net"
"math/rand"
"strconv"
"strings"
"time"
log "github.com/Sirupsen/logrus"
"github.com/prometheus/client_golang/prometheus"
"google.golang.org/grpc"
"net/http"
// registers pprof http handlers
_ "net/http/pprof"
)
// Server provides an RPC server that registers itself with discovery and uses HTTP/2 transport
type Server struct {
name string
listener net.Listener
}
// Serve will register with discovery and wait for queries
func (s *Server) Serve(name string, registrationFunc func(*grpc.Server)) error {
s.name = name
port, err := findExistingPort(name)
if err != nil {
log.WithField("error", err).Fatal("error finding port")
return err
}
if port == nil {
port = randomPort()
}
s.listener, err = net.Listen("tcp", laddr(*port))
if err != nil {
log.WithField("port", port).WithField("error", err).Fatal("failed to listen")
return err
}
grpcServer := grpc.NewServer()
grpc.EnableTracing = true
registrationFunc(grpcServer)
go grpcServer.Serve(s.listener)
err = registerWithDiscovery(name, *port)
if err != nil {
log.WithField("error", err).Error("failed to register with discovery")
return err
}
http.Handle("/metrics", prometheus.Handler())
err = http.Serve(s.listener, nil)
if err != nil {
log.WithField("error", err).Error("failed to serve http")
return err
}
return nil
}
// Stop will end serving and remove itself from discovery
func (s *Server) Stop() error {
err := s.listener.Close()
if err != nil {
log.WithField("error", err).Error("failed to stop listener")
return err
}
err = deregisterWithDiscovery(s.name)
if err != nil {
log.WithField("error", err).Error("failed to deregister with discovery")
return err
}
return nil
}
func findExistingPort(name string) (*int, error) {
discovery, err := connectToDiscovery()
services, err := discovery.GetLocalServices()
if err != nil {
return nil, err
}
for _, service := range services {
if strings.EqualFold(service.Name, name) {
log.WithField("port", service.Node.Port).Debug("found existing port")
return &service.Node.Port, nil
}
}
return nil, nil
}
func randomPort() *int {
rand.Seed(time.Now().UTC().UnixNano())
port := rand.Intn(1000) + 50000
log.WithField("port", port).Debug("Chose random port")
return &port
}
func laddr(port int) string {
return ":" + strconv.Itoa(port)
}
func registerWithDiscovery(name string, port int) error {
discovery, err := connectToDiscovery()
if err != nil {
return err
}
err = discovery.RegisterService(name, port)
if err != nil {
log.Fatalf("failed to register with discovery service: %v", err)
return err
}
log.WithField("name", name).WithField("port", port).Info("registered with discovery service")
return nil
}
func deregisterWithDiscovery(name string) error {
discovery, err := connectToDiscovery()
if err != nil {
return err
}
err = discovery.DeregisterService(name)
if err != nil {
log.Fatalf("failed to deregister with discovery service: %v", err)
return err
}
return nil
}
func connectToDiscovery() (*Discovery, error) {
discovery, err := NewDiscovery()
if err != nil {
log.Fatalf("failed to create discovery service: %v", err)
return nil, err
}
return discovery, nil
}