云原生 | go-micro@v4.9.0源码解析(建议收藏)

news2024/10/5 13:01:16

go-micro@v4.9.0源码阅读

  • 一、前言
  • 二、创建微服务
  • 三、源码阅读
    • 操作一:注册服务处理
    • 操作二:组件配置
    • 操作三:启动微服务
      • Step 1 :启动微服务
      • Step 2 :开启服务关闭监听
      • Step 3 :停⽌Server组件
      • Step 4 :停⽌Profile组件

一、前言

Go是一款开源的编程语言,能更容易地构造简单、可靠且高效的软件,具备高并发,静态编译等特性,在性能、安全等方面具备非常大的优势。

而go-micro则是基于Go的微服务编程框架,操作简单、编码高效、功能强大。想进一步了解go-micro,请查看我们的往期文章:go-micro学习与实践

本文章基于基于go-micro@v4.9.0版本,内容全面详实,预计阅读时长10分钟,建议先收藏! 那么下面就让我们开启go-micro源码阅读之旅吧!

二、创建微服务

使⽤官⽹提供的cli插件直接创建⼀个微服务。

插件下载:go install github.com/go-micro/cli/cmd/go-micro@latest

创建微服务 :go-micro new service helloworld

依赖更新及下载 :make init proto update tidy

微服务创建成功后,微服务包含以下⼏个⽬录结构:

图片

三、源码阅读

下面我们先从微服务的启动入口 main.go 开始分析起。

main.go


func main() {
// 组件配置
srv := micro.NewService(
//micro.Name(service),
//micro.Version(version),
micro.Server(server.DefaultServer),
micro.Client(client.DefaultClient),
micro.Broker(broker.DefaultBroker),
micro.Registry(registry.DefaultRegistry),
micro.Transport(transport.DefaultTransport),
micro.Auth(auth.DefaultAuth),
micro.Cache(cache.DefaultCache),
micro.Cmd(cmd.DefaultCmd),
micro.Config(config.DefaultConfig),
micro.Runtime(runtime.DefaultRuntime),main进⾏了三个操作:组件配置,注册服务处理,启动微服务
注册服务处理
proto:定义服务
helloworld.proto:protobuf格式的协议定义服务
上述定义了⼀个服务Helloworld,该服务包含4个⽅法:Call, ClientStream, ServerStream, BidiStream
helloworld.pb.go:由protoc --go_out=:. proto/helloworld.proto⽣成。该⽂件会包含⽅法⼊参,出参的结构体及
对应的编码规范。
helloworld.pb.micro.go:由protoc --micro_out=. proto/hellloworld.proto⽣成。该⽂件会包含
HelloworldHandler接⼝(该接⼝包含了4个服务⽅法),及该接⼝注册到微服务的RegisterHelloworldHandler。
handler:微服务的具体处理逻辑
helloworld.go:实现helloworld.pb.micro.go中定义的HelloworldHandler接⼝。
注册流程,详⻅核⼼组件server.Server组件讲解;调⽤流程,详⻅client.Client组件讲解。
组件配置
micro.Profile(profile.DefaultProfile),
micro.Store(store.DefaultStore),
micro.Logger(logger.DefaultLogger),
)
srv.Init()
// 注册服务处理
pb.RegisterHelloworldHandler(srv.Server(), new(handler.Helloworld))
// 启动微服务
if err := srv.Run(); err != nil {
log.Fatal(err)
}
}

可以看到,main进⾏了三个操作:

注册服务处理

组件配置

启动微服务

下面我们逐个来看这三个操作。

操作一:注册服务处理

1.1 proto:定义服务

helloworld.proto: protobuf格式的协议定义服务

service Helloworld {
rpc Call(CallRequest) returns (CallResponse) {}
rpc ClientStream(stream ClientStreamRequest) returns (ClientStreamResponse) {}
rpc ServerStream(ServerStreamRequest) returns (stream ServerStreamResponse) {}
rpc BidiStream(stream BidiStreamRequest) returns (stream BidiStreamResponse) {}
}

上述定义了⼀个服务Helloworld,该服务包含4个⽅法:Call, ClientStream, ServerStream, BidiStream。

helloworld.pb.go

由protoc --go_out=:. proto/helloworld.proto⽣成。该⽂件会包含⽅法⼊参,出参的结构体及对应的编码规范。

helloworld.pb.micro.go

由protoc --micro_out=. proto/hellloworld.proto⽣成。

该⽂件会包含HelloworldHandler接⼝(该接⼝包含了4个服务⽅法),及该接⼝注册到微服务的RegisterHelloworldHandler。

1.2 handler:微服务的具体处理逻辑

helloworld.go

实现helloworld.pb.micro.go中定义的HelloworldHandler接⼝。

注册流程,详⻅核⼼组件server.Server组件讲解;调⽤流程,详⻅client.Client组件讲解。

操作二:组件配置

图片

2.1 顶层结构

micro.Service

微服务的顶层抽象。⽤于定义微服务的服务信息及控制着整个微服务⽣命周期。包含以下⼏个⽅法。

type Service interface {
// The service name
Name() string
// Init initialises options
Init(...Option)
// Options returns the current options
Options() Options
// Client is used to call services
Client() client.Client
// Server is for handling requests and events
Server() server.Server
// Run the service
Run() error
// The service implementation
String() string
}

默认实现的结构体为micro.service

type service struct {
opts Options
once sync.Once
}

opts Options 是微服务的配置项,包含该微服务⽤到的其他组件,⽣命周期执⾏钩⼦函数(服务启动前执⾏钩⼦函数,服务关闭前执⾏的钩⼦函数,服务启动后执⾏的钩⼦函数,服务关闭后执⾏的钩⼦函数),服务上下⽂,是否启⽤系统信号关闭服务的配置项。

once sync.Once 保证只执⾏⼀次加载启动参数。

2.2 核心组件

核⼼组件是构成微服务的必要组件。

server.Server:微服务的服务端

type Server interface {
// Initialise options
Init(...Option) error
// Retrieve the options
Options() Options
// Register a handler
Handle(Handler) error
// Create a new handler
NewHandler(interface{}, ...HandlerOption) Handler
// Create a new subscriber
NewSubscriber(string, interface{}, ...SubscriberOption) Subscriber
// Register a subscriber
Subscribe(Subscriber) error
// Start the server
Start() error
// Stop the server
Stop() error
// Server implementation
String() string
}

以mucp的实现为例。实现组件的结构体为server.rpcServer

type rpcServer struct {
router *router
exit chan chan error
sync.RWMutex
opts Options
handlers map[string]Handler
subscribers map[Subscriber][]broker.Subscriber
// marks the serve as started
started bool
// used for first registration
registered bool
// subscribe to service name
subscriber broker.Subscriber
// graceful exit
wg *sync.WaitGroup
rsvc *registry.Service
}

rpcServer 包含以下⼏种信息:

#1 服务处理

rpcServer有两种服务处理:

⼀种是表示服务请求的rpcHandler

⼀种是表示消息处理的subscriber

rpcHandler:⼀个微服务可定义多个rpc服务,每个rpc服务对应⼀个的rpcHandler,通过map的形式保存在rpcServer中。

通过NewHandler⽅法⽣成, handler为⼀个⾃定义的结构体,该结构体对应rpc服务名,结构体上的外部⽅法对应rpc服务⽅法。

subscriber:⼀个微服务可订阅多个消息,每个消息对应⼀个subscriber,通过map的形式保存在rpcServer中。

通过NewSubscriber⽅法⽣成,参数topic表示订阅的消息;参数sub是⼀个⽅法,⽅法签名为:

“func(context.Context, interface{}) error”

表示该消息的处理逻辑。

#2 路由

构建路由信息

图片

绑定服务:⽤户将服务注册到框架中。rpcServer针对两种请求类型有不同的绑定⽅法。

解析服务:解析路由信息,解析服务处理信息存储到router中。

服务注册:将服务信息,节点信息,路由信息,发送到服务注册中⼼进⾏注册。

**图片**

使⽤路由信息

图片

接收消息:从注册中⼼或消息中⼼,接收到需要处理的请求。

统⼀拦截:接受到请求后,执⾏中间件中的函数,先配置的先执⾏。

端点分发:根据请求端点,匹配到分发器中的对应处理⽅法的放射类型。

请求解码:根据content-type,对请求体进⾏解码,得到⽅法的⼊参。

服务处理:使⽤⼊参,执⾏反射⽅法。

rpcServer的router路由中存储着两种不同类型的路由。

在这里插入图片描述

#3 配置

rpcServer包含多种配置信息:

节点信息配置:包含服务id,服务名称,监听地址,节点元数据,上下⽂等。

组件配置:包含注册中⼼,消息中⼼,服务通信,编码器等

拦截器配置:包含服务请求拦截器,消息通知拦截器。

#4 状态信息

rpcServer的状态信息包含:服务运⾏状态,注册状态,退出执⾏状态等。

client.Client:微服务的客户端

type Client interface {
Init(...Option) error
Options() Options
NewMessage(topic string, msg interface{}, opts ...MessageOption) Message // 构建消息
NewRequest(service, endpoint string, req interface{}, reqOpts ...RequestOption)
Request // 构建服务请求
Call(ctx context.Context, req Request, rsp interface{}, opts ...CallOption) error //
调⽤服务端
Stream(ctx context.Context, req Request, opts ...CallOption) (Stream, error) // 构建
双向通信
Publish(ctx context.Context, msg Message, opts ...PublishOption) error // 发布消息
String() string
}

以mucp的实现为例。实现组件的结构体为client.rpcClient

type rpcClient struct {
seq uint64
once atomic.Value
opts Options
pool pool.Pool
}

rpcClient 包含以下⼏种信息:

#1 请求链

图片

构建请求: rpcClient针对两种不同的请求类型,有不同构建⽅法。

在这里插入图片描述

请求备份:发起请求后,通过BackoffFunc函数对请求进⾏备份,备份时,会阻塞请求。rpcClient没有默认的请求备份,⽀持⾃定义配置BackoffFunc函数。

选择节点:从注册中⼼获取请求⽬标服务对应的所有节点。通过Selector选择器选取节点, rpcClient默认使⽤随机算法来选取节点,⽀持⾃定义选择器。

中间件:选取节点后,执⾏中间件函数。先配置的先执⾏。

发送请求

  • 选择好的服务节点建⽴连接,连接建⽴成功后,将连接放⼊连接池,请求重试时,后续相同的请求可以直接在连接池中获取
  • 使⽤编码器对请求编码,发送请求数据

解析响应:获取响应后,使⽤解码器对响应解码并依次返回到最上层⽅法。

#2 配置

组件配置:消息中⼼,编码/解码器,注册中⼼,节点选择器,通信⽅式等。

请求配置:连接池,中间件,超时时间等。

2.2 核心组件衍生

broker.Broker

消息组件,⽤于与消息中⼼交互。

type Broker interface {
Init(...Option) error
Options() Options
Address() string
Connect() error
Disconnect() error
Publish(topic string, m *Message, opts ...PublishOption) error
Subscribe(topic string, h Handler, opts ...SubscribeOption) (Subscriber, error)
String() string
}

图片/ 组件基本逻辑

以http实现为例。 http是go-micro默认组件实现,具体的结构体为broker.HttpBroker

type httpBroker struct {
id string
address string
opts Options
mux *http.ServeMux
c *http.Client
r registry.Registry
sync.RWMutex
subscribers map[string][]*httpSubscriber
running bool
exit chan chan error
// offline message inbox
mtx sync.RWMutex
inbox map[string][][]byte
}

httpBroker 包含以下⼏种信息:

#1 发布消息

httpBroker通过Publish⽅法发布消息。

图片

消息编码:httpBroker默认使⽤json进⾏消息编码。编码完的消息缓存到inbox字段中。

获取订阅端:每个订阅端节点,都会以微服务的形式将订阅信息注册到服务注册中⼼。不同于其他⾃定义的微服务,订阅端微服务的名称为固定值:micro.http.broker。

(当⼀个节点有订阅消息时,会注册两个微服务信息,⼀个是⾃身service定义的微服务,⼀个是固定的消息订阅微服务)。

httpBroker先通过微服务名(micro.http.broker)获取所有的订阅端节点信息,然后通过topic过滤得到对应消息订阅端的节点列表。

发送http请求:httpBroker通过节点选取规则选择节点,从inbox中取出消息,并向这些节点发送http请求。

httpBroker有两种选取规则。通过broker.Queue()进⾏设置。

在这里插入图片描述

#2 订阅消息

httpBroker通过Subscribe⽅法订阅消息:

图片

注册订阅微服务:httpBroker构建微服务信息,并注册到注册中⼼。

微服务信息包含:服务名(固定值:
micro.http.broker),消息topic,处理函数,当前节点信息等。

#3 配置

httpBroker可配置的信息有: broker相关信息(地址, tls连接,上下⽂等), registry相关信息,编码器等

#4 状态信息

httpBroker有两种状态:

⼀种是连接状态,⼀种是断开状态。

在这里插入图片描述

registry. Registry

服务注册中⼼组件,⽤于与注册中⼼交互。服务注册中⼼存储所有的服务节点信息,以便于其他节点能够获取。

type Registry interface {
Init(...Option) error
Options() Options
Register(*Service, ...RegisterOption) error
Deregister(*Service, ...DeregisterOption) error
GetService(string, ...GetOption) ([]*Service, error)
ListServices(...ListOption) ([]*Service, error)
Watch(...WatchOption) (Watcher, error)
String() string
}

在这里插入图片描述

以etcd实现为例。etcd实现不是go-micro的默认实现,需要引⼊go-micro组件库。etcd实现的结构体为etcd.etcdRegistry。

type etcdRegistry struct {
client *clientv3.Client
options registry.Options
sync.RWMutex
register map[string]uint64
leases map[string]clientv3.LeaseID
}

etcdRegistry 包含以下信息:

#1 注册

etcdRegistry通过etcd的api进⾏注册、续约、删除等操作。

在这里插入图片描述

etcdRegistry包含两个注册相关数据:

register map[string]uint64:存储已注册节点的hash值,当该节点再次发起注册时,对⽐节点信息是否有更改。

leases map[string]clientv3.LeaseID:存储已注册节点的LeaseID,当该节点再次发起注册时(注册⼼跳维持场景),进⾏注册续约。

#2 配置

配置信息包含registry连接配置(地址, ttl, tls,上下⽂等), etcd连接客户端。

transport.Transport

微服务调⽤组件。定义服务间通信⽅式。

在这里插入图片描述

以http实现为例。transport.httpTransport是go-micro的默认实现。

type httpTransport struct {
opts Options
}

httpTransport 包含以下信息:

#1 监听

图片

端⼝监听:启动tcp端⼝监听。返回监听器httpTransportListener。

建⽴连接:⼀个微服务可订阅多个消息,每个消息对应⼀个subscriber,通过map的形式保存在rpcServer中。

#2 请求

在这里插入图片描述

创建连接:创建tcp连接到服务端。返回客户端httpTransportClient。

发送数据:通过Send⽅法,将请求写⼊到连接中。

接收数据:通过Recv⽅法,从连接中读取响应。

#3 配置

配置包含:连接地址, tls, ttl,上下⽂等。

2.3 功能组件

功能组件在核⼼流程中并未使⽤。应根据需要⾃⾏使⽤。

auth.Auth

认证组件

type Auth interface {
// Init the auth
Init(opts ...Option)
// Options set for auth
Options() Options
// Generate a new account
Generate(id string, opts ...GenerateOption) (*Account, error)
// Inspect a token
Inspect(token string) (*Account, error)
// Token generated using refresh token or credentials
Token(opts ...TokenOption) (*Token, error)
// String returns the name of the implementation
String() string
}

在这里插入图片描述

以jwt实现为例。go-micro默认没有实现。组件库中jwt实现的结构体为jwt.jwt

type jwt struct {
sync.Mutex
options auth.Options
jwt jwtToken.Provider
}

jwt 包含以下⼏种信息:

#1 token⽣成器

在这里插入图片描述

组装账号信息:通过Generate⽅法⽣成账号信息,账号信息包含⽤户id, secret(由jwt⽣成器⽣成,⽤于传递到token解析),⾃定义信息等。

⽣成token:通过账号的secret解析出完整的账号信息(secret时效为15min,超时⽆法头盖⻣secret解析账号信息)。

然后再通过jwt⽣成器,对账号信息进⾏加密,⽣成具有指定时效的accesstoken和refreshtoken(refreshtoken的时效⽐accesstoken的⻓1h)。

解析token:从token值(accesstoken或refreshtoken)中解析出账号信息,超时的⽆法解析。

#2 配置

包含的配置信息有: jwt⽣成器配置(jwt公钥,私钥, token有效时间等),账号信息配置(⾃定义信息等)

cache.Cache

缓存组件

type Cache interface {
// Get gets a cached value by key.
Get(ctx context.Context, key string) (interface{}, time.Time, error)
// Put stores a key-value pair into cache.
Put(ctx context.Context, key string, val interface{}, d time.Duration) error
// Delete removes a key from cache.
Delete(ctx context.Context, key string) error
// String returns the name of the implementation.
String() string
}

在这里插入图片描述

以redis实现为例。go-micro的缓存是key-value格式,默认memory实现, redis的实现结构体为redis.redisCache

type redisCache struct {
opts cache.Options
client redis.UniversalClient
}

redisCache 包含以下⼏种信息:

#1 redis客户端

⽤于和redis进⾏交互。

#2 配置

配置信息包含:缓存有效时间,缓存服务器地址,上下⽂等。

cmd.Cmd

命令⾏组件,用于定义参数等

type Cmd interface {
// The cli app within this cmd
App() *cli.App
// Adds options, parses flags and initialise
// exits on error
Init(opts ...Option) error
// Options set within this command
Options() Options
}

go-micro的默认实现为cmd.cmd

type cmd struct {
opts Options
app *cli.App
}

cmd通过urfave/cli实现参数的设置与读取

设置参数:通过设置cli.App的Flags进⾏参数设置。Flags包含参数类型,命令⾏参数名称,环境变量(多个值),参数说明,默认值等。

解析参数:cli.App会将参数写⼊到cli.Context中,然后通过设置cli.App的Action进⾏参数的解析。

config.Config

配置组件,与配置中⼼交互

type Config interface {
// provide the reader.Values interface
reader.Values
// Init the config
Init(opts ...Option) error
// Options in the config
Options() Options
// Stop the config loader/watcher
Close() error
// Load config sources
Load(source ...source.Source) error
// Force a source changeset sync
Sync() error
// Watch a value for changes
Watch(path ...string) (Watcher, error)
}

go-micro的默认实现为config.config

type config struct {
exit chan bool
opts Options
sync.RWMutex
// the current snapshot
snap *loader.Snapshot
// the current values
vals reader.Values
}

命令⾏组件,用于定义参数等

config 包含以下⼏种信息:

#1 获取数据

config通过Load⽅法或Sync⽅法,从数据源获取数据。获取到数据后,⽣成数据快照。

#2 监听数据

连接到数据源后, config每隔1s从数据源同步数据,监控配置中⼼数据是否发⽣变化,当数据变动时,重新⽣成新的快照数据。

#3 ⽣成快照

数据快照由两个部分构成:

配置数据:从配置中⼼读取到的数据

版本:⽣成快照的时间戳,保证缓存的快照都是最新的。

#4 读取数据

go-micro的配置数据会解析为json格式

获取:通过path获取对于值

删除/更新:只能操作本地的内存数据,配置中⼼的数据不会发⽣变化

runtime.Runtime

服务管理组件。可⽤于管理其他微服务

t

ype Runtime interface {
// Init initializes runtime
Init(...Option) error
// Create registers a service
Create(*Service, ...CreateOption) error
// Read returns the service
Read(...ReadOption) ([]*Service, error)
// Update the service in place以kubernetes实现为例。go-micro的默认实现为runtime.runtime,只适⽤于所有服务在同⼀个操作系统中的场
景。组件的kubernetes实现为kubernetes.kubernetes,适⽤于kubernetes环境。
为了区分,以下通过kubernetes表示runtime的组件, k8s表示kubernetes环境
go-micro中的微服务节点对应kubernetes中的pod,可通过Deployment和Service进⾏控制。故对runtime对微服
务的管理,就是对k8s资源的管理。
kubernetes包含以下信息
kubernetes客户端
kubernetes客户端⽤于请求kubernetes的kube-apiserver。管理k8s资源。
监听微服务事件:runtime组件启动后,会监听从微服务传递过来的事件,事件包含:服务创建,服务更新,服务
删除。
传递到kubernetes:调⽤kube-apiserver,操作Deployment和Service资源。
配置信息
Update(*Service, ...UpdateOption) error
// Remove a service
Delete(*Service, ...DeleteOption) error
// Logs returns the logs for a service
Logs(*Service, ...LogsOption) (LogStream, error)
// Start starts the runtime
Start() error
// Stop shuts down the runtime
Stop() error
// String describes runtime
String() string
}


以kubernetes实现为例。 go-micro的默认实现为runtime.runtime,只适⽤于所有服务在同⼀个操作系统中的场景。组件的kubernetes实现为kubernetes.kubernetes,适⽤于kubernetes环境。



为了区分,以下通过kubernetes表示runtime的组件, k8s表示kubernetes环境

type kubernetes struct {
sync.RWMutex
// options configure runtime
options *runtime.Options
// indicates if we're running
running bool
// used to stop the runtime
closed chan bool
// client is kubernetes client
client client.Client
// namespaces which exist
namespaces []client.Namespace
}

go-micro中的微服务节点对应kubernetes中的pod,可通过Deployment和Service进⾏控制。故对runtime对微服务的管理,就是对k8s资源的管理。

jwt 包含以下⼏种信息:

#1 kubernetes客户端

kubernetes客户端⽤于请求kubernetes的kube-apiserver。管理k8s资源。

监听微服务事件:runtime组件启动后,会监听从微服务传递过来的事件。

事件包含:服务创建,服务更新,服务删除

传递到kubernetes:调⽤kube-apiserver,操作Deployment和Service资源。

#2 配置信息

包含的配置信息有:定时任务(组件启动后执⾏,可创建微服务事件), kubernetes信息(镜像名称,资源类型等)

#3 状态信息

微服务运⾏的命名空间
组件的运⾏状态(启动,关闭)

profile.Profile

pprof组件,采集性能数据

type Profile interface {
// Start the profiler
Start() error
// Stop the profiler
Stop() error
// Name of the profiler
String() string
}

以profiler实现为例。 实现结构体为pprof.profiler

type profiler struct {
opts profile.Options
sync.Mutex
running bool
// where the cpu profile is written
cpuFile *os.File
// where the mem profile is written
memFile *os.File
}

profiler 包含以下⼏种信息:

#1 性能分析

profiler使⽤go⾃带的pprof进⾏性能分析。

cpuFile *os.File:cpu性能分析结果⽂件,通过pprof.StartCPUProfile⽅法记录。

memFile *os.File:内存性能分析结果⽂件,通过pprof.WriteHeapProfile⽅法记录。

#2 配置信息

包含的配置信息有: 分析名称(⽣成临时⽂件的名称)

#3 状态信息

状态信息包含:组件的运⾏状态。

store.Store

数据存储组件。与数据中⼼交互, go-micro数据存储组件⽀持key-value格式数据。

type Store interface {
// Init initialises the store. It must perform any required setup on the backing
storage implementation and check that it is ready for use, returning any errors.
Init(...Option) error
// Options allows you to view the current options.
Options() Options
// Read takes a single key name and optional ReadOptions. It returns matching
[]*Record or an error.
Read(key string, opts ...ReadOption) ([]*Record, error)
// Write() writes a record to the store, and returns an error if the record was not
written.
Write(r *Record, opts ...WriteOption) error
// Delete removes the record with the corresponding key from the store.
Delete(key string, opts ...DeleteOption) error
// List returns any keys that match, or an empty list with no error if none matched.
List(opts ...ListOption) ([]string, error)
// Close the store
Close() error
// String returns the name of the implementation.
String() string
}

以redis实现为例。 redis实现的结构体为redis.rkv

type rkv struct {
ctx context.Context
options store.Options
Client redis.UniversalClient
}

rkv 包含以下⼏种信息:

#1 数据中⼼客户端

通过redis客户端与redis进⾏交互,实现数据的增删改查。

#2 配置

包含的配置信息有: 数据中⼼节点配置,数据库,数据表。

logger.Logger

⽇志记录组件

type Logger interface {
// Init initialises options
Init(options ...Option) error
// The Logger options
Options() Options
// Fields set fields to always be logged
Fields(fields map[string]interface{}) Logger
// Log writes a log entry
Log(level Level, v ...interface{})
// Logf writes a formatted log entry
Logf(level Level, format string, v ...interface{})
// String returns the name of logger
String() string
}

go-micro默认⽇志记录实现为logger.defaultLogger

type defaultLogger struct {
sync.RWMutex
opts Options
}

defaultLogger 包含以下⼏种信息:

#1 日志记录

defaultLogger将⽇志记录的当前时间戳,⽇志等级,公共字段(通过Filed⽅法设置),具体信息。通过fmt.Printf函数输出到系统的STDOUT中

#2 配置

包含的配置信息有:⽇志记录等级,公共字段,输出,上下⽂等。

操作三:启动微服务

Step 1 :启动微服务

使⽤micro.Service的Run⽅法启动微服务时,调⽤server.Server的Start⽅法来启动Server组件。

如果profile.Profile已经配置到了micro.Service的Options中,调⽤profile.Profile的Start⽅法来启动Profile组件。

Step 2 :开启服务关闭监听

服务启动完成后,开启服务关闭监听,服务关闭有以下两种⽅式:

信号关闭:系统接收到SIGTERM、 SIGINT、 SIGQUIT或SIGKILL信号时,关闭服务。可通过配置项(Signal)取消该关闭⽅式。

上下⽂关闭:触发了micro.Service中的定义的上下⽂的取消⽅法时,关闭服务。

Step 3 :停⽌Server组件

使⽤server.Server的Stop⽅法,停⽌Server组件。

Step 4 :停⽌Profile组件

使⽤profile.Profile的Stop⽅法,停⽌Profile组件。

下面我们具体来看其中几点。

  • 启动Server组件

在这里插入图片描述

  • 启动Server

使⽤server.Server的Start⽅法启动Server

  • 开启服务监听

使⽤transport.Transport的Listen⽅法开启服务监听。

  • 开启消息监听

使⽤broker.Broker的Connect⽅法开启消息监听。

  • 开启服务注册

先使⽤RegisterCheck定义的⽅法进⾏服务注册检查。检查通过后,再使⽤Register⽅法进⾏服务注册。

  • 处理请求线程

处理请求线程,是⽤来接收到服务请求。并进⾏后续处理。

  • 服务注册⼼跳保持线程

在这里插入图片描述

系统正常运⾏时,开启定时任务。每隔30s使⽤RegisterCheck定义的⽅法进⾏注册检查,检查通过时,直接使⽤Register注册;检查失败时,先使⽤Deregister⽅法取消注册,再使⽤Deregister⽅法重新注册。

使⽤通道监听服务状态,当收到服务关闭时,停⽌定时任务,使⽤Deregister⽅法取消注册。

  • 服务注册(Register⽅法)

开始注册后,先从缓存中获取服务信息,由于需要进⾏服务注册⼼跳保持机制,每次注册的服务信息不会发⽣变化,故可以将需要注册的服务信息进⾏缓存。

服务已经进⾏了缓存,直接获取缓存中的服务信息,使⽤registry.Registry的Register⽅法在注册中⼼注册务。

服务未进⾏缓存,先⽣成节点信息。节点信息包含有:服务名称,服务版本,服务监听的端点(服务请求处理端点和消息通知处理端点),节点信息。

使⽤broker.Broker的Subscribe⽅法在消息中⼼订阅消息,消息订阅端是⽤来绑定订阅的消息和对该消息的处理逻辑。

使⽤regisry.Registry的Register⽅法在注册中⼼注册服务。注册失败时会进⾏重试,共3次。

注册成功后,将服务信息进⾏缓存。

  • 取消注册(Deregister⽅法)

取消注册时,先⽣成节点的简要信息。

根据节点简要信息,使⽤registry.Registry的Deregister⽅法取消该节点的注册。

调⽤每个订阅端端Unsubscribe⽅法,在消息中⼼取消订阅

清除服务信息的缓存

  • 启动Profile组件

使⽤go⾃带的pprof进⾏启动性能分析。

  • 停⽌Server组件

使⽤通道通知服务注册⼼跳保持线程服务已关闭,修改服务的启动状态。

  • 停⽌Profile组件

停⽌pprof性能分析。

我们致力于用数字技术重构企业价值,助力企业实现数字化转型升级!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/102515.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

毕业设计 基于java web的网上零食销售系统的设计与实现

文章目录前言一、项目设计1. 模块设计功能分析前台功能后台功能2. 实现效果二、部分源码项目源码前言 今天学长向大家分享一个 web项目: 基于java web的网上零食销售系统的设计与实现 一、项目设计 1. 模块设计 功能分析 经过对时下大型电商网站的调查,对该系统…

计算机毕业设计 SSM与Vue的垃圾分类系统(源码+论文)

文章目录1 项目简介2 实现效果2.1 界面展示3 设计方案3.1 概述3.2 系统流程3.2.1 系统开发流程3.2.2 登录流程3.3 系统结构设计4 最后1 项目简介 Hi,各位同学好呀,这里是M学姐! 今天向大家分享一个今年(2022)最新完成的毕业设计项目作品&am…

学人工智能好找工作吗 ?Python就业前景怎么样?

学人工智能好找工作吗?Python就业前景怎么样?人工智能前景很好,中国正在产业升级,工业机器人和人工智能方面都会是热点,而且正好是学习的好时机。但是,也有一个问题大家要注意: 学习的难度比较高…

[附源码]Python计算机毕业设计Django智能衣橱APP

项目运行 环境配置: Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术: django python Vue 等等组成,B/S模式 pychram管理等等。 环境需要 1.运行环境:最好是python3.7.7,…

数据类型相关笔记

C、C、java强调类型&#xff1b; JavaScript、python、php不看重类型&#xff0c;甚至不需要事先定义。 类型 ○ 整数 ○ 浮点数 ○ 逻辑 ○ 指针 ○ 自定义类型 sizeof 查看所占字节 给出某个类型或变量在内存中所占据的字节数 # include <stdio.h>int main(void) …

怎么把avi转成mp4格式?

怎么把avi转成mp4格式&#xff1f;这是最近大家问的比较频繁的一个问题&#xff0c;avi是一种音频视频的交错格式&#xff0c;可以极大的压缩视频文件本身所占用的内存空间&#xff0c;但是同时引起的负面缺点是使视频画质受损&#xff0c;所以大家在遇到avi格式视频时。可以转…

编程明明是程序员的工作,关学生什么事?

写在前面&#xff1a; 我手里这个魔方&#xff0c;任何一个人都可以轻松地把它打乱&#xff0c;但要想把它复原&#xff0c;就不是每个人都能做到的了。我会还原魔方&#xff0c;而你不会&#xff0c;这能不能说明我比你聪明呢&#xff1f;并不能。 还原一个三阶魔方是有特定的…

12基于储能电站服务的冷热电多微网系统双层优化配置(matlab程序)

参考文献 基于储能电站服务的冷热电多微网系统双层优化配置——吴盛军&#xff08;2020电网技术&#xff09; 主要内容 分析共享储能电站的运行方式和盈利机制。将储能电站服务应用到冷热电联供型多微网系统中&#xff0c;建立考虑两个不同时间尺度问题的双层规划模型&#…

pyTorch入门(四)——导出Minist模型,C++ OpenCV DNN进行识别

学更好的别人&#xff0c;做更好的自己。——《微卡智享》本文长度为2548字&#xff0c;预计阅读8分钟前言前三章介绍了pyTorch训练的相关&#xff0c;我们也保存模型成功了&#xff0c;今天这篇就是使用C OpenCV的DNN模块进行手写图片的推理。实现效果导出的推理模型使用的是M…

基于JSP数码产品交易

开发工具(eclipse/idea/vscode等)&#xff1a; 数据库(sqlite/mysql/sqlserver等)&#xff1a; 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a; 网站前台&#xff1a;网站介绍、帮助信息、数码资讯、数码产品、讨论信息 管理员功能&#xff1a; 1、管理网站介绍、帮…

运维基础【黑马系列笔记整理分享(上)】

运维基础【黑马系列笔记整理分享(上&#xff09;】 因为笔记所记内容太多&#xff0c;所以我分成了上下两部分来分享给大家查看学习&#xff01;同时我会持续更新博客发布更加优质的文章&#xff0c;希望大家多多支持与关注&#xff01;感谢&#xff01; 一、运维概述 1、运维…

基于PHP+Mysql全品类在线购物商城设计

开发软件&#xff1a;VsCode/Dreamweaver等都行&#xff0c;mysql数据库&#xff0c;apache服务器 开发技术&#xff1a;PHP MVC模式&#xff0c;DIVCSS,Jquery等 这是一个全品类购物商城&#xff0c;可以销售所有品类的商品&#xff0c;包括前端用户和后端管理员2个身份&…

[ 妙用css ]:用css变量解决开发实际问题

各位看官&#xff0c;如何实现以上这种方块的移动&#xff0c;相信对于大家来说并不陌生&#xff0c;无非是几个步骤 1.设置动画 2.进行移动 3.动画循环 <div class"f-box"><div class"box"></div> </div> <style> .f-box…

Springboot工厂制造业WMS仓库管理系统源码为工厂仓库提供高效率管理带小程序和调试视频完全开源 可以二开

系统全开源&#xff0c;无任何加密&#xff0c;适合学习和二次开发 1. 开发语言&#xff1a;JAVA 2. 数据库&#xff1a;MySQL 3. 后端框架&#xff1a;springboot 4. 前端框架&#xff1a;VUE 5. 带小程序端 6. 带调试视频 7. 带部署文档 项目运行环境&#xff1a;JDK1…

使用Echarts完成对中国地图的绘制

目录前言1.什么是Echarts插件2.如何在vue中使用Echarts3.中国地图的具体样式4.如何使用Echarts来完成中国地图的绘制5.总结前言 我们在使用代码绘画地图的时候通常使用的是canvas&#xff0c;但是canvas是H5新增的东西&#xff0c;用起来不免有些麻烦&#xff0c;代码多&#…

聊一聊MySQL的记录锁、间隙锁与 Next-Key Lock

有小伙伴在微信上表示面试时被问到了 Next-Key Lock 是啥&#xff0c;结果一脸懵逼&#xff0c;那么今天我们来捋一捋 MySQL 中的记录锁、间隙锁以及 Next-Key Lock。 1. Record Lock Record Lock 也就是我们所说的记录锁&#xff0c;记录锁是对索引记录的锁&#xff0c;注意…

如何在小程序中完成支付进件?

1. 完成企业认证 1.1. 创建试用小程序 打开一个待发布的项目。点击顶部导航栏的 发布。手机扫码生成试用小程序。点击二维码底部的 发布应用。 1.2. 使用企业主体 转正小程序选择转正类型为 企业认证。 公司代码。 公司名称。 法人姓名。 法人身份证。 法人微信号。 点…

〖产品思维训练白宝书 - 产品思维认知篇②〗- 破局高手都具备的一种底层认知 - 产品思维

大家好&#xff0c;我是 哈士奇 &#xff0c;一位工作了十年的"技术混子"&#xff0c; 致力于为开发者赋能的UP主, 目前正在运营着 TFS_CLUB社区。 &#x1f4ac; 人生格言&#xff1a;优于别人,并不高贵,真正的高贵应该是优于过去的自己。&#x1f4ac; &#x1f4e…

C代码中花括号写成这种风格竟被吐槽~

正文大家好&#xff0c;我是bug菌~最近来了位新同事&#xff0c;闲暇时分聊了几句&#xff0c;其中有一点让我记忆特别深刻&#xff0c;说:"怎么我们这边代码中的花括号风格都独立另起一行&#xff0c;看代码的时候挺不适应的~"&#xff0c;我笑着说:"习惯就好了…

CMD CD命令失效,无法到达指定目录?

方法1&#xff1a; a.先进入另一盘的首层。&#xff08;想进入同盘目录可忽略这步&#xff09; b.使用cd 进入指定目录。 方法2&#xff1a; 直接进入目录 e:\>cd /d F:\2022F:\2022>cmd的其他指令 内容含义盘符:例如想进入D盘 d:cd进入到当前盘某个目录cd | 进入当前…