This repository has been archived by the owner on Sep 24, 2022. It is now read-only.
forked from carousell/Orion
-
Notifications
You must be signed in to change notification settings - Fork 0
/
documentation.go
217 lines (164 loc) · 5.91 KB
/
documentation.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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
/*
Lets create a minimal service with Orion
API Interface
Your service starts with the API interface, In orion we define all API interfaces as a protobuf file (stringsvc/stringproto/stringproto.proto)
syntax = "proto3";
package stringproto;
service StringService{
rpc Upper (UpperRequest) returns (UpperResponse){
}
rpc Count (CountRequest) returns (CountResponse) {
}
}
message UpperRequest {
string msg = 1;
}
message UpperResponse {
string msg = 1;
}
message CountRequest{
string msg = 1;
}
message CountResponse{
int64 count = 1;
}
Above protobuf file describes a service called "StringService" and defines the endpoints "Upper" and "Count", As we can see all our API Contracts are clearly laid out and makes it easy for other services to integrate with our service
Generating Service Code
we can execute
protoc -I . stringproto.proto --go_out=plugins=grpc:. --orion_out=.
to generate protobuf/orion code, you will see following files are generated
stringproto.pb.go
stringproto.pb.orion.go
Service Lifecycle
Orion manages lifecycle of the service by ServiceFactory (stringsvc/service/init.go)
package service
import "github.com/go-orion/Orion/orion"
type svcFactory struct{}
func (s *svcFactory) NewService(orion.Server) interface{} {
return &svc{}
}
func (s *svcFactory) DisposeService(svc interface{}) {
//do nothing
}
func GetFactory() orion.ServiceFactory {
return &svcFactory{}
}
"NewService" is called when a new service is initialized, "DisposeService" is called when a service is disposed.
A new service is initialized and older service is disposed every time config reloads.
Implementing Service
we need to implement the "StringServiceServer" interface generated by protoc plugin, this is where our application logic lives
(stringsvc/service/service.go)
package service
import (
"context"
"strings"
proto "github.com/go-orion/Orion/example/stringsvc/stringproto"
)
// svc implements proto.StringServiceServer
type svc struct{}
func (s *svc) Upper(ctx context.Context, req *proto.UpperRequest) (*proto.UpperResponse, error) {
resp := new(proto.UpperResponse)
resp.Msg = strings.ToUpper(req.GetMsg())
return resp, nil
}
func (s *svc) Count(ctx context.Context, req *proto.CountRequest) (*proto.CountResponse, error) {
resp := new(proto.CountResponse)
resp.Count = int64(len(req.GetMsg()))
return resp, nil
}
Building Server
in only a few lines of code we can get a server started serving gRPC and HTTP (stringsvc/cmd/server/main.go)
package main
import (
"github.com/go-orion/Orion/example/stringsvc/service"
proto "github.com/go-orion/Orion/example/stringsvc/stringproto"
"github.com/go-orion/Orion/orion"
)
func main() {
server := orion.GetDefaultServer("StringService")
proto.RegisterStringServiceOrionServer(service.GetFactory(), server)
server.Start()
server.Wait()
}
Running Server
we can start the server by running "go run cmd/server/main.go"
ᐅ go run cmd/server/main.go
2018/02/01 16:20:57 msg Reading config
2018/02/01 16:20:57 Config config could not be read Config File "StringService" Not Found in "[. /opt/config]"
2018/02/01 16:20:57 HTTPListnerPort 9282
2018/02/01 16:20:57 gRPCListnerPort 9281
2018/02/01 16:20:57 HystrixPort 9283
2018/02/01 16:20:57 warning rollbar token is empty not initializing rollbar
___ ____ ___ ___ _ _
/ _ \| _ \|_ _/ _ \| \ | |
| | | | |_) || | | | | \| |
| |_| | _ < | | |_| | |\ |
\___/|_| \_\___\___/|_| \_|
2018/02/01 16:20:57 GRPC server starting
2018/02/01 16:20:57 PprofPort 9284
Mapped URLs:
[POST] /stringservice/upper
[POST] /stringservice/count
Orion automatically generates and initializes HTTP/gRPC servers based on our defined proto
as we can see the path for our endpoints Upper and Count are as follows
[POST] /stringservice/upper
[POST] /stringservice/count
Making HTTP Calls
Lets call Upper
ᐅ curl -X POST -i -d '{"msg":"Hello World"}' http://127.0.0.1:9282/stringservice/upper
HTTP/1.1 200 OK
Content-Type: application/json
Date: Thu, 01 Feb 2018 08:27:32 GMT
Content-Length: 21
{"msg":"HELLO WORLD"}
By default orion responds in "application/json" for HTTP calls, We can even ask for response in "protobuf" by setting the Accept HTTP header
ᐅ curl -X POST -i -H "Accept:application/protobuf" -d '{"msg":"Hello World"}' http://127.0.0.1:9282/stringservice/upper
HTTP/1.1 200 OK
Content-Type: application/octet-stream
Date: Thu, 01 Feb 2018 08:30:21 GMT
Content-Length: 13
// binary data omitted
HELLO WORLD
Orion also logs response time and errors for each API call
2018/02/01 16:27:32 path /stringservice/upper method POST error <nil> took 132.96µs
2018/02/01 16:30:21 path /stringservice/upper method POST error <nil> took 766.984µs
Making gRPC calls
we can build a client using StringServiceClient generated by protoc grpc plugin (stringsvc/cmd/client/main.go)
package main
import (
"context"
"log"
proto "github.com/go-orion/Orion/example/stringsvc/stringproto"
"google.golang.org/grpc"
)
const (
address = "127.0.0.1:9281"
)
func main() {
// establish connection
conn, err := grpc.Dial(address, grpc.WithInsecure())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
client := proto.NewStringServiceClient(conn)
uppercase(client)
}
func uppercase(client proto.StringServiceClient) {
r := new(proto.UpperRequest)
r.Msg = "Hello World"
log.Println("making gRPC calls for Upper")
resp, err := client.Upper(context.Background(), r)
log.Println("resp", resp)
log.Println("error", err)
}
On running this client we can see
ᐅ go run cmd/client/main.go
2018/02/01 16:50:06 making gRPC calls for Upper
2018/02/01 16:50:06 resp msg:"HELLO WORLD"
2018/02/01 16:50:06 error <nil>
we will see the following on server
2018/02/01 16:50:06 method /stringproto.StringService/Upper error <nil> took 19.764µs
*/
package example
//go:generate godoc2ghmd -ex -file=README.md github.com/go-orion/Orion/example