2015-05-26 22:39:48 +01:00
|
|
|
package server
|
|
|
|
|
|
|
|
import (
|
2018-03-03 11:53:52 +00:00
|
|
|
"context"
|
2016-01-26 23:32:27 +00:00
|
|
|
"time"
|
|
|
|
|
2015-11-20 16:17:33 +00:00
|
|
|
"github.com/micro/go-micro/broker"
|
2015-11-27 00:17:36 +00:00
|
|
|
"github.com/micro/go-micro/codec"
|
2015-11-20 16:17:33 +00:00
|
|
|
"github.com/micro/go-micro/registry"
|
2016-01-06 19:24:54 +00:00
|
|
|
"github.com/micro/go-micro/server/debug"
|
2015-11-20 16:17:33 +00:00
|
|
|
"github.com/micro/go-micro/transport"
|
2015-05-26 22:39:48 +01:00
|
|
|
)
|
|
|
|
|
2015-12-31 18:11:46 +00:00
|
|
|
type Options struct {
|
|
|
|
Codecs map[string]codec.NewCodec
|
|
|
|
Broker broker.Broker
|
|
|
|
Registry registry.Registry
|
|
|
|
Transport transport.Transport
|
|
|
|
Metadata map[string]string
|
|
|
|
Name string
|
|
|
|
Address string
|
|
|
|
Advertise string
|
|
|
|
Id string
|
|
|
|
Version string
|
|
|
|
HdlrWrappers []HandlerWrapper
|
|
|
|
SubWrappers []SubscriberWrapper
|
|
|
|
|
Add option to enable TCP check with Consul registry
One disadvantage of using TTL based health check is the high network
traffic between Consul agent (either between servers, or between server
and client).
In order for the services considered alive by Consul, microservices must
send an update TTL to Consul every n seconds (currently 30 seconds).
Here is the explanation about TTL check from Consul documentation [1]
Time to Live (TTL) - These checks retain their last known state for a
given TTL. The state of the check must be updated periodically over
the HTTP interface. If an external system fails to update the status
within a given TTL, the check is set to the failed state. This
mechanism, conceptually similar to a dead man's switch, relies on the
application to directly report its health. For example, a healthy app
can periodically PUT a status update to the HTTP endpoint; if the app
fails, the TTL will expire and the health check enters a critical
state. The endpoints used to update health information for a given
check are the pass endpoint and the fail endpoint. TTL checks also
persist their last known status to disk. This allows the Consul agent
to restore the last known status of the check across restarts.
Persisted check status is valid through the end of the TTL from the
time of the last check.
Hint:
TTL checks also persist their last known status to disk. This allows
the Consul agent to restore the last known status of the check
across restarts.
When microservices update the TTL, Consul will write to disk. Writing to
disk means all other slaves need to replicate it, which means master need
to inform other standby Consul to pull the new catalog. Hence, the
increased traffic.
More information about this issue can be viewed at Consul mailing list [2].
[1] https://www.consul.io/docs/agent/checks.html
[2] https://groups.google.com/forum/#!topic/consul-tool/84h7qmCCpjg
2018-03-14 18:51:38 +07:00
|
|
|
RegisterTCPCheck bool
|
|
|
|
RegisterTTL time.Duration
|
|
|
|
RegisterInterval time.Duration
|
2016-01-27 12:23:18 +00:00
|
|
|
|
2016-01-06 19:24:54 +00:00
|
|
|
// Debug Handler which can be set by a user
|
|
|
|
DebugHandler debug.DebugHandler
|
|
|
|
|
2016-01-06 16:25:12 +00:00
|
|
|
// Other options for implementations of the interface
|
|
|
|
// can be stored in a context
|
|
|
|
Context context.Context
|
2015-12-31 18:11:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func newOptions(opt ...Option) Options {
|
|
|
|
opts := Options{
|
|
|
|
Codecs: make(map[string]codec.NewCodec),
|
|
|
|
Metadata: map[string]string{},
|
2015-11-25 19:50:05 +00:00
|
|
|
}
|
2015-05-26 22:39:48 +01:00
|
|
|
|
|
|
|
for _, o := range opt {
|
|
|
|
o(&opts)
|
|
|
|
}
|
|
|
|
|
2015-12-31 18:11:46 +00:00
|
|
|
if opts.Broker == nil {
|
|
|
|
opts.Broker = broker.DefaultBroker
|
2015-06-12 19:52:27 +01:00
|
|
|
}
|
|
|
|
|
2015-12-31 18:11:46 +00:00
|
|
|
if opts.Registry == nil {
|
|
|
|
opts.Registry = registry.DefaultRegistry
|
2015-06-01 18:55:27 +01:00
|
|
|
}
|
|
|
|
|
2015-12-31 18:11:46 +00:00
|
|
|
if opts.Transport == nil {
|
|
|
|
opts.Transport = transport.DefaultTransport
|
2015-05-26 22:39:48 +01:00
|
|
|
}
|
|
|
|
|
2016-01-06 19:24:54 +00:00
|
|
|
if opts.DebugHandler == nil {
|
|
|
|
opts.DebugHandler = debug.DefaultDebugHandler
|
|
|
|
}
|
|
|
|
|
2015-12-31 18:11:46 +00:00
|
|
|
if len(opts.Address) == 0 {
|
|
|
|
opts.Address = DefaultAddress
|
2015-05-26 22:39:48 +01:00
|
|
|
}
|
|
|
|
|
2015-12-31 18:11:46 +00:00
|
|
|
if len(opts.Name) == 0 {
|
|
|
|
opts.Name = DefaultName
|
2015-05-26 22:39:48 +01:00
|
|
|
}
|
|
|
|
|
2015-12-31 18:11:46 +00:00
|
|
|
if len(opts.Id) == 0 {
|
|
|
|
opts.Id = DefaultId
|
2015-05-26 22:39:48 +01:00
|
|
|
}
|
|
|
|
|
2015-12-31 18:11:46 +00:00
|
|
|
if len(opts.Version) == 0 {
|
|
|
|
opts.Version = DefaultVersion
|
2015-06-03 01:25:37 +01:00
|
|
|
}
|
|
|
|
|
2015-05-26 22:39:48 +01:00
|
|
|
return opts
|
|
|
|
}
|
|
|
|
|
2015-11-26 00:23:36 +00:00
|
|
|
// Server name
|
2015-06-03 01:25:37 +01:00
|
|
|
func Name(n string) Option {
|
2015-12-31 18:11:46 +00:00
|
|
|
return func(o *Options) {
|
|
|
|
o.Name = n
|
2015-06-03 01:25:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-26 00:23:36 +00:00
|
|
|
// Unique server id
|
2015-06-03 01:25:37 +01:00
|
|
|
func Id(id string) Option {
|
2015-12-31 18:11:46 +00:00
|
|
|
return func(o *Options) {
|
|
|
|
o.Id = id
|
2015-06-03 01:25:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-26 00:23:36 +00:00
|
|
|
// Version of the service
|
2015-06-03 01:25:37 +01:00
|
|
|
func Version(v string) Option {
|
2015-12-31 18:11:46 +00:00
|
|
|
return func(o *Options) {
|
|
|
|
o.Version = v
|
2015-06-03 01:25:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-26 00:23:36 +00:00
|
|
|
// Address to bind to - host:port
|
2015-06-03 01:25:37 +01:00
|
|
|
func Address(a string) Option {
|
2015-12-31 18:11:46 +00:00
|
|
|
return func(o *Options) {
|
|
|
|
o.Address = a
|
2015-06-03 01:25:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-26 00:23:36 +00:00
|
|
|
// The address to advertise for discovery - host:port
|
2015-11-11 18:22:04 +00:00
|
|
|
func Advertise(a string) Option {
|
2015-12-31 18:11:46 +00:00
|
|
|
return func(o *Options) {
|
|
|
|
o.Advertise = a
|
2015-11-11 18:22:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-26 00:23:36 +00:00
|
|
|
// Broker to use for pub/sub
|
2015-06-12 19:52:27 +01:00
|
|
|
func Broker(b broker.Broker) Option {
|
2015-12-31 18:11:46 +00:00
|
|
|
return func(o *Options) {
|
|
|
|
o.Broker = b
|
2015-06-12 19:52:27 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-26 00:23:36 +00:00
|
|
|
// Codec to use to encode/decode requests for a given content type
|
2015-11-28 11:22:29 +00:00
|
|
|
func Codec(contentType string, c codec.NewCodec) Option {
|
2015-12-31 18:11:46 +00:00
|
|
|
return func(o *Options) {
|
|
|
|
o.Codecs[contentType] = c
|
2015-11-25 19:50:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-26 00:23:36 +00:00
|
|
|
// Registry used for discovery
|
2015-06-03 01:25:37 +01:00
|
|
|
func Registry(r registry.Registry) Option {
|
2015-12-31 18:11:46 +00:00
|
|
|
return func(o *Options) {
|
|
|
|
o.Registry = r
|
2015-06-03 01:25:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-26 00:23:36 +00:00
|
|
|
// Transport mechanism for communication e.g http, rabbitmq, etc
|
2015-06-03 01:25:37 +01:00
|
|
|
func Transport(t transport.Transport) Option {
|
2015-12-31 18:11:46 +00:00
|
|
|
return func(o *Options) {
|
|
|
|
o.Transport = t
|
2015-06-03 01:25:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-06 19:24:54 +00:00
|
|
|
// DebugHandler for this server
|
|
|
|
func DebugHandler(d debug.DebugHandler) Option {
|
|
|
|
return func(o *Options) {
|
|
|
|
o.DebugHandler = d
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-26 00:23:36 +00:00
|
|
|
// Metadata associated with the server
|
2015-06-03 01:25:37 +01:00
|
|
|
func Metadata(md map[string]string) Option {
|
2015-12-31 18:11:46 +00:00
|
|
|
return func(o *Options) {
|
|
|
|
o.Metadata = md
|
2015-06-03 01:25:37 +01:00
|
|
|
}
|
|
|
|
}
|
2015-12-02 00:47:52 +00:00
|
|
|
|
2016-01-27 12:23:18 +00:00
|
|
|
// Register the service with a TTL
|
|
|
|
func RegisterTTL(t time.Duration) Option {
|
|
|
|
return func(o *Options) {
|
|
|
|
o.RegisterTTL = t
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Add option to enable TCP check with Consul registry
One disadvantage of using TTL based health check is the high network
traffic between Consul agent (either between servers, or between server
and client).
In order for the services considered alive by Consul, microservices must
send an update TTL to Consul every n seconds (currently 30 seconds).
Here is the explanation about TTL check from Consul documentation [1]
Time to Live (TTL) - These checks retain their last known state for a
given TTL. The state of the check must be updated periodically over
the HTTP interface. If an external system fails to update the status
within a given TTL, the check is set to the failed state. This
mechanism, conceptually similar to a dead man's switch, relies on the
application to directly report its health. For example, a healthy app
can periodically PUT a status update to the HTTP endpoint; if the app
fails, the TTL will expire and the health check enters a critical
state. The endpoints used to update health information for a given
check are the pass endpoint and the fail endpoint. TTL checks also
persist their last known status to disk. This allows the Consul agent
to restore the last known status of the check across restarts.
Persisted check status is valid through the end of the TTL from the
time of the last check.
Hint:
TTL checks also persist their last known status to disk. This allows
the Consul agent to restore the last known status of the check
across restarts.
When microservices update the TTL, Consul will write to disk. Writing to
disk means all other slaves need to replicate it, which means master need
to inform other standby Consul to pull the new catalog. Hence, the
increased traffic.
More information about this issue can be viewed at Consul mailing list [2].
[1] https://www.consul.io/docs/agent/checks.html
[2] https://groups.google.com/forum/#!topic/consul-tool/84h7qmCCpjg
2018-03-14 18:51:38 +07:00
|
|
|
//
|
|
|
|
// RegisterTCPCheck will tell the service provider to check the service address
|
|
|
|
// and port every `t` interval. It will enabled only if `t` is greater than 0.
|
|
|
|
// This option is for registry using Consul, see `TCP + Interval` more
|
|
|
|
// information [1].
|
|
|
|
//
|
|
|
|
// [1] https://www.consul.io/docs/agent/checks.html
|
|
|
|
//
|
|
|
|
func RegisterTCPCheck(t time.Duration) Option {
|
|
|
|
return func(o *Options) {
|
|
|
|
if t > time.Duration(0) {
|
|
|
|
o.RegisterTCPCheck = true
|
|
|
|
o.RegisterInterval = t
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-31 19:47:50 +01:00
|
|
|
// Wait tells the server to wait for requests to finish before exiting
|
|
|
|
func Wait(b bool) Option {
|
|
|
|
return func(o *Options) {
|
|
|
|
if o.Context == nil {
|
|
|
|
o.Context = context.Background()
|
|
|
|
}
|
|
|
|
o.Context = context.WithValue(o.Context, "wait", b)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-02 00:47:52 +00:00
|
|
|
// Adds a handler Wrapper to a list of options passed into the server
|
2015-12-02 11:54:36 +00:00
|
|
|
func WrapHandler(w HandlerWrapper) Option {
|
2015-12-31 18:11:46 +00:00
|
|
|
return func(o *Options) {
|
|
|
|
o.HdlrWrappers = append(o.HdlrWrappers, w)
|
2015-12-02 00:47:52 +00:00
|
|
|
}
|
|
|
|
}
|
2015-12-02 11:54:36 +00:00
|
|
|
|
|
|
|
// Adds a subscriber Wrapper to a list of options passed into the server
|
|
|
|
func WrapSubscriber(w SubscriberWrapper) Option {
|
2015-12-31 18:11:46 +00:00
|
|
|
return func(o *Options) {
|
|
|
|
o.SubWrappers = append(o.SubWrappers, w)
|
2015-12-02 11:54:36 +00:00
|
|
|
}
|
|
|
|
}
|