gin 源码
gin 实现了 http.ServeHTTP(ResponseWriter, *Request) 接口;
engine context
- 获取context;pool 较少gc压力;
- 获取标准库request,包括:uri,method;
- 路由匹配:engine.methodTrees 前缀树的匹配查找;
- 找到HandlersChain
- 解析请求参数
- 遍历执行HandlersChain;
- response 写入header;
- render :根据request accept 协商render,渲染最终返回的格式数据;
- html
- json
- msgpack
- string
- Jsonp
- XML
- YAML
http.ListenAndServe TCP server
- onceListener
- Accept
- goroutine serve
- panic recover
- tls
- read:bufioReaderPool
- ServeHTTP
- BufioWriter
- close
路由功能
- 路由前缀树(基树):空间换时间,提高路由性能,支持模糊匹配
详细说明:https://en.wikipedia.org/wiki/Radix_tree
go-micro 源码分析
代码启动流程
-
新建服务
- 客户端初始化:auth、trace等
- 服务端初始化:auth、trace、Stats 等
-
初始化
- 初始化配置
- 加载插件
- 设置应用名字
- 初始化cmd 的全部组件: 命令行配置
-
注册服务
- Pb 代码注册handler: context.Context, *XXXRequest, *XXXResponse
-
启动
- 产生一个auth account
- 根据id、secret
- 获得account
- 生成 token
- 独立协程
- 定时任务
- 过期刷新
- 更新client token
- 注册默认handler
- DefaultLog
- DefaultStats
- DefaultTracer
- 启动Profile
- 启动Server,和指定的启动函数,以grpc 为例
- net.Listener
- Listen
- 启动broker
- 注册服务
- 启动服务:和net 的tcp 是一样的
- 定时刷新注册
- 系统退出时
- 卸载服务
- 等待sub 停止
- 优雅退出
- disconnect broker
- 产生一个auth account
option 方式,提高扩展行
- options struct 声明
- option func(*options)
- newOption(...option) 初始化:默认值、ops 修改
全部组件抽象 interface
- Service
- Client
- Server
- Auth
- Borker
- Cmd
- Config
- Store
- Runtime
- Transport
- Profile
- Tracer
- Cmd
- Registry
- Selector
// and initialising services.
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
}
// Client is the interface used to make requests to services.
// It supports Request/Response via Transport and Publishing via the Broker.
// It also supports bidirectional streaming of requests.
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
}
// Server is a simple micro server abstraction
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
}
// Auth providers authentication and authorization
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)
// Grant access to a resource
Grant(role string, res *Resource) error
// Revoke access to a resource
Revoke(role string, res *Resource) error
// Verify an account has access to a resource
Verify(acc *Account, res *Resource) error
// Inspect a token
Inspect(token string) (*Account, error)
// Token generated using refresh token
Token(opts ...TokenOption) (*Token, error)
// String returns the name of the implementation
String() string
}
// Broker is an interface used for asynchronous messaging.
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
}
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
}
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)
}
// Store is a data storage interface
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
}
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
}
// Runtime is a service runtime manager
type 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
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
}
// Transport is an interface which is used for communication between
// services. It uses connection based socket send/recv semantics and
// has various implementations; http, grpc, quic.
type Transport interface {
Init(...Option) error
Options() Options
Dial(addr string, opts ...DialOption) (Client, error)
Listen(addr string, opts ...ListenOption) (Listener, error)
String() string
}
type Profile interface {
// Start the profiler
Start() error
// Stop the profiler
Stop() error
// Name of the profiler
String() string
}
// Tracer is an interface for distributed tracing
type Tracer interface {
// Start a trace
Start(ctx context.Context, name string) (context.Context, *Span)
// Finish the trace
Finish(*Span) error
// Read the traces
Read(...ReadOption) ([]*Span, error)
}
// Handler interface represents a request handler. It's generated
// by passing any type of public concrete object with endpoints into server.NewHandler.
// Most will pass in a struct.
//
// Example:
//
// type Greeter struct {}
//
// func (g *Greeter) Hello(context, request, response) error {
// return nil
// }
//
type Handler interface {
Name() string
Handler() interface{}
Endpoints() []*registry.Endpoint
Options() HandlerOptions
}
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
}
// Selector builds on the registry as a mechanism to pick nodes
// and mark their status. This allows host pools and other things
// to be built using various algorithms.
type Selector interface {
Init(opts ...Option) error
Options() Options
// Select returns a function which should return the next node
Select(service string, opts ...SelectOption) (Next, error)
// Mark sets the success/error against a node
Mark(service string, node *registry.Node, err error)
// Reset returns state back to zero for a service
Reset(service string)
// Close renders the selector unusable
Close() error
// Name of the selector
String() string
装饰器模式(包装器)
Wrapper 嵌入修饰对象接口,和特性的接口,然后实现对修饰对象和特性对象的联合
- traceWrapper 实现对client 的追踪
- authWrapper 实现对client 的鉴权
- fromServiceWrapper 实现服务调用者名字设置
- WrapHandler func(HandlerFunc) HandlerFunc
// TraceCall is a call tracing wrapper
func TraceCall(name string, t trace.Tracer, c client.Client) client.Client {
return &traceWrapper{
name: name,
trace: t,
Client: c,
}
}
type traceWrapper struct {
client.Client
name string
trace trace.Tracer
}
func (c *traceWrapper) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error {
newCtx, s := c.trace.Start(ctx, req.Service()+"."+req.Endpoint())
s.Type = trace.SpanTypeRequestOutbound
err := c.Client.Call(newCtx, req, rsp, opts...)
if err != nil {
s.Metadata["error"] = err.Error()
}
// finish the trace
c.trace.Finish(s)
return err
}
type authWrapper struct {
client.Client
auth func() auth.Auth
}
func (a *authWrapper) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error {
// parse the options
var options client.CallOptions
for _, o := range opts {
o(&options)
}
// check to see if the authorization header has already been set.
// We dont't override the header unless the ServiceToken option has
// been specified or the header wasn't provided
if _, ok := metadata.Get(ctx, "Authorization"); ok && !options.ServiceToken {
return a.Client.Call(ctx, req, rsp, opts...)
}
// if auth is nil we won't be able to get an access token, so we execute
// the request without one.
aa := a.auth()
if aa == nil {
return a.Client.Call(ctx, req, rsp, opts...)
}
// check to see if we have a valid access token
aaOpts := aa.Options()
if aaOpts.Token != nil && aaOpts.Token.Expiry.Unix() > time.Now().Unix() {
ctx = metadata.Set(ctx, "Authorization", auth.BearerScheme+aaOpts.Token.AccessToken)
return a.Client.Call(ctx, req, rsp, opts...)
}
// call without an auth token
return a.Client.Call(ctx, req, rsp, opts...)
}
插件模式-插拔式
目的
- 可以热更新式扩展应用程序的功能列表
- 应对多变的业务需求,方便功能上下线
- 对于任意的go应用,能进行增量架构、代码分发以及代码上下线
Brokers map[string]func(...broker.Option) broker.Broker
Configs map[string]func(...config.Option) (config.Config, error)
Clients map[string]func(...client.Option) client.Client
Registries map[string]func(...registry.Option) registry.Registry
Selectors map[string]func(...selector.Option) selector.Selector
Servers map[string]func(...server.Option) server.Server
Transports map[string]func(...transport.Option) transport.Transport
Runtimes map[string]func(...runtime.Option) runtime.Runtime
Stores map[string]func(...store.Option) store.Store
Tracers map[string]func(...trace.Option) trace.Tracer
Auths map[string]func(...auth.Option) auth.Auth
Profiles map[string]func(...profile.Option) profile.Profile
package main
func Add(x, y int) int {
return x + y
}
func Subtract(x, y int) int {
return x - y
}
//go build -buildmode=plugin -o aplugin.so aplugin.go
package main
import (
"fmt"
"plugin"
)
func main() {
p, _ := plugin.Open("./aplugin.so")
add, _ := p.Lookup("Add")
subtract, _ := p.Lookup("Subtract")
sum := add.(func(int, int) int)(11, 2)
fmt.Println("sum=", sum)
sub := subtract.(func(int, int) int)(11, 2)
fmt.Println("sum=", sub)
}