In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-26 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/01 Report--
This article mainly explains "what is the organization of the basic components of microservices". The content of the explanation is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn "what is the organization of the basic components of microservices"?
Brief introduction
Micro is a micro-service framework implemented in go language. The framework itself implements several common elements for services, such as gateways, agents, registries, messaging, and also supports pluggable extensions. This book explores how the project implements these components and organizes them to work together through a core object deployment in micro.
Notice: go code is sometimes cumbersome. When intercepting the source code, it will delete part of the code that does not affect the mind and will be marked as.
Core service
Micro creates a service instance through micro.NewService, and all micro-service instances (including gateways, agents, etc.) need to interact with other services through this instance.
Type service struct {opts Options once sync.Once}
There is very little code, but all the micro-service elements in micro will eventually converge on this type, because option is all-inclusive.
Type Options struct {Broker broker.Broker Cmd cmd.Cmd Client client.Client Server server.Server Registry registry.Registry Transport transport.Transport / / Before and After funcs BeforeStart [] func () error BeforeStop [] func () error AfterStart [] func () error AfterStop [] func () error / / Other options for implementations of the interface / / can be stored in a context Context context.Context}
Here you can see the common components of microservices. When micro.Server is initialized, the corresponding component is set to this object. The setting method of the component includes default value, cli assignment and env read.
Func (s * service) Init (opts... Option) {/ / process options for _, o: = range opts {o (& s.opts)} s.once.Do (func () {/ / Initialise the command flags, overriding new service _ = s.opts.Cmd.Init (cmd.Broker (& s.opts.Broker)) Cmd.Registry (& s.opts.Registry), cmd.Transport (& s.opts.Transport), cmd.Client (& s.opts.Client), cmd.Server (& s.opts.Server),)})
Server is the ultimate behavioral entity, listening on the port and providing business services, registering local services with the registry. Broker asynchronous messages, mq and other methods can replace this type of Client service invocation client Registry registry Cmd cli client Transport similar to socket, message synchronous communication, service monitoring, etc.
Type of service
Currently, the types of services supported are rpc,grpc. If there are two different rpc protocols in the service, the protocol will be converted when the message is delivered. The default rpc service is described in more detail here. Rpc service is based on HTTP POST protocol. When the service starts, it tries to connect to Broker, then registers the service with the registry, and finally listens to the service port. Briefly mention how to achieve protocol conversion here. If the message from http is to be delivered to a grpc protocol service, you need to set the corresponding destination service agreement type application/grpc,SerConn in Content-Type to read it from Content-Type to obtain the corresponding Codec for protocol conversion, and finally deliver it to the corresponding service. The returned content of the service should also be processed and returned.
Type Service interface {Init (... Option) Options () Options Client () client.Client Server () server.Server Run () error String () string}
Rpc server
Func (s * rpcServer) Start () error {... Ts, err: = config.Transport.Listen (config.Address) / / swap address... / / connect to the broker if err: = config.Broker.Connect (); err! = nil {return err}... / / use RegisterCheck func before register if err = s.opts.RegisterCheck (s.opts.Context) Err! = nil {log.Logf ("Server% s muri% s register check error:% s", config.Name, config.Id, err)} else {/ / announce self to the world if err = s.Register () Err! = nil {log.Logf ("Server% s muri% s register error:% s", config.Name, config.Id, err)}}. Go func () {for {/ / listen for connections err: = ts.Accept (s.ServeConn)... } (). Return nil}
Protocol conversion
Func (s * rpcServer) ServeConn (sock transport.Socket) {. For {var msg transport.Message if err: = sock.Recv (& msg) Err! = nil {return}... / / we use this Content-Type header to identify the codec needed ct: = msg.Header ["Content-Type"] / / strip our headers hdr: = make (map [string] string) for k V: = range msg.Header {hdr [k] = v} / / set local/remote ips hdr ["Local"] = sock.Local () hdr ["Remote"] = sock.Remote (). / / TODO: needs better error handling var err error if cf, err = s.newCodec (ct); err! = nil {/ / request protocol converter. Error return} is returned. Rcodec: = newRpcCodec (& msg, sock, cf) / / return converter / / internal request request: = & rpcRequest {service: getHeader ("Micro-Service", msg.Header), method: getHeader ("Micro-Method", msg.Header), endpoint: getHeader ("Micro-Endpoint", msg.Header), contentType: ct Codec: rcodec, header: msg.Header, body: msg.Body, socket: sock, stream: true,} / / internal response response: = & rpcResponse {header: make (map [string] string) Socket: sock, codec: rcodec,} / / set router r: = Router (s.router). / / serve the actual request using the request router if err: = r.ServeRequest (ctx, request, response) Err! = nil {/ / write an error response err = rcodec.Write (& codec.Message {Header: msg.Header, Error: err.Error (), Type: codec.Error,} Nil) / / could not write the error response if err! = nil {log.Logf ("rpc: unable to write error response:% v" Err)} if s.wg! = nil {s.wg.Done ()} return}...}} registry
The registry includes service discovery and service registration. Every registry type in micro implements the registry interface
Type Registry interface {Init (... Option) error Options () Options Register (* Service,... RegisterOption) error Deregister (* Service) error GetService (string) ([] * Service, error) ListServices () ([] * Service, error) Watch (. WatchOption) (Watcher, error) String () string}
The default registry is mdns, which listens locally to a multicast address to receive all the information in the network and its broadcasts, and the information sent can also be found by all other machines. Every time the program starts, it broadcasts its own service information. Other nodes receive this information and add it to their own service list. When the service is closed, it will send out a shutdown message. Mdns itself does not have health check, fuse and other functions, and its starting point is only convenient for testing, so it is not recommended to be used in production environment.
Resolve
The lookup service needs to obtain the service name according to the url or content information. After searching the registry through the service name, the service is randomly delivered by a node.
Type Resolver interface {Resolve (r * http.Request) (* Endpoint, error) String () string} / / default api resolve instance, in addition to three host,path,grpc resolve You can specify or set it in the environment variable / / func (r * Resolver) Resolve (req * http.Request) (* resolver.Endpoint, error) {var name, method string switch r.Options.Handler {/ / internal handlers case "meta", "api", "rpc" when starting the program according to your needs. "micro": / foo/bar/zool = > go.micro.api.foo method: Bar.Zool / foo/bar = > go.micro.api.foo method: Foo.Bar name Method = apiRoute (req.URL.Path) default: / / if handler is web, it will come here / foo/bar/zool = > go.micro.api.foo method bar/zool / / 1/foo/bar/ = > go.micro.api.1.foo method bar method = req.Method name = proxyRoute (req.URL.Path)} Return & resolver.Endpoint {Name: name Method: method,}, nil} plug-ins
A plugin is defined in the code, but this plugin is not intended to introduce a component, but to add a layer to the request pipeline so that it is easier to add new logic. However, what needs to be emphasized is the way of introducing new components into micro. Several important members of micro service have their corresponding interface specifications. As long as the interfaces are implemented correctly, they can easily access new components. Here is an example of introducing kubernetes as a registry.
The kubernetes component is located in github.com\ micro\ go-plugins
Go get-u github.com\ micro\ go-plugins\ kubernetes
Because the dynamic loading function of package in java/c# can not be realized in go, the language itself does not provide global type and function scanning. Often can only be achieved through some tortuous methods. On the other hand, micro uses the init function to write the required functional components into a map by importing the package in the portal file. Add plug-ins to import
_ "github.com/micro/go-plugins/registry/kubernetes" micro api-registry=kubernetes-registry_address=yourAddress
How it works: there is a map in github.com\ micro\ go-micro\ config\ cmd\ cmd.go to save all registry creation functions
DefaultRegistries = func (. Registry.Option) registry.Registry {"consul": consul.NewRegistry, "gossip": gossip.NewRegistry, "mdns": mdns.NewRegistry, "memory": rmem.NewRegistry,}
Kubernetes writes the corresponding creation function in the init of the package
Func init () {cmd.DefaultRegistries ["kubernetes"] = NewRegistry}
Effective position
If name: = ctx.String ("registry") Len (name) > 0 & & (* c.opts.Registry). String ()! = name {r, ok: = c.opts.Registries [name] if! ok {return fmt.Errorf ("Registry% s not found", name)} * c.opts.Registry = r () serverOpts = append (serverOpts Server.Registry (* c.opts.Registry)) clientOpts = append (clientOpts, client.Registry (* c.opts.Registry)) if err: = (* c.opts.Selector) .Init (selector.Registry (* c.opts.Registry)) Err! = nil {log.Fatalf ("Error configuring registry:% v", err)} clientOpts = append (clientOpts, client.Selector (* c.opts.Selector)) if err: = (* c.opts.Broker) .Init (broker.Registry (* c.opts.Registry)) Err! = nil {log.Fatalf ("Error configuring broker:% v", err)}}
Finally, a diagram is attached to illustrate the reference relationship of the core object, the component reference is only drawn in the registry, and Broker,Server is a similar principle.
Thank you for your reading. the above is the content of "how the basic components of microservices are organized". After the study of this article, I believe you have a deeper understanding of the organization of the basic components of microservices, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.