Go build a microservices framework based on GRPC-service registration and discovery

Source: Internet
Author: User
Tags etcd
This is a creation in Article, where the information may have evolved or changed.


GRPC is the Google Open source RPC framework, based on HTTP2 implementation, and supports cross-language, now basically covers the mainstream language. The implementation of cross-language is mainly due to the protobuf, by writing the proto file, and using the Protobuf tool to generate the corresponding language class library.

For a new language like go, the eco-chain is still in the development stage, as is the microservices framework, which will build a microservices communication framework based on the grpc-go version.

1. Mechanism for registration and release of services

1.1 Resolved issues

Service registration and release are primarily resolved service dependency issues, in general, if a service invokes B service, the most straightforward approach is to configure the IP address and port. But as service dependencies change, the configuration will be complex and the configuration of all related services needs to be modified when the service is migrated. This will be very difficult to maintain and prone to problems.
Therefore, in order to solve this service dependency, service registration and release came into being.

1.2 mechanism

Service registration and discovery are mainly divided into the following points.

    • Service Information Release

This is primarily the service name, IP information, and some attachment metadata. Register to the Service Registration Publishing center via the registration interface.

    • Survival detection

When the service stops unexpectedly, the client needs to perceive that the service is stopped and kicks the IP address of the service to a list of available IP addresses, which can be achieved using a timed heartbeat.

    • Client Load Balancing

Through service registration and publication, a service can be deployed to deploy multiple instances, and the client realizes the direct load balancing of the instances, thus realizing the scale-out of the service.

Therefore, service registration and release can be summarized as the service will escalate information, the client pulls the service information, call through the service name, when the service goes down, the client kicks off the service, the client automatically added to the call list when the service is new.

2. Implement

Grpc-go the entire implementation of the full use of Go interface features, so through the expansion of the interface, can easily realize the registration and discovery of services, where the service registry to consider the availability and consistency, generally using ETCD or zookeeper to achieve, here to implement ETCD version.
For complete code and usage examples see: https://github.com/g4zhuj/grp ...

2.1 Client

The specific need to implement a few interfaces, for the client, the simplest way to implement only two interface methods to implement resolve (), and Next (), and then use the polling load balancing method.
It is implemented mainly through the get interface of ETCD and the Watch interface.

    • Resolve () interface
//用于生成Watcher,监听注册中心中的服务信息变化func (er *etcdRegistry) Resolve(target string) (naming.Watcher, error) {    ctx, cancel := context.WithTimeout(context.TODO(), resolverTimeOut)    w := &etcdWatcher{        cli:    er.cli,        target: target + "/",        ctx:    ctx,        cancel: cancel,    }    return w, nil}
    • Next () interface
The next interface is mainly used to obtain registered service information, through channel and watch, when the service information occurs//changes, the next interface will return the changes to the GRPC framework for service information changes. Func (EW *etcdwatcher) Next ([ ]*naming. Update, error) {var updates []*naming. When Update//is first acquired, the Listener channel is created and the service information obtained is returned if Ew.watchchan = = Nil {//create new Chan resp, err: = Ew.cli. Get (Ew.ctx, Ew.target, Etcd. Withprefix (), Etcd. Withserializable ()) if err! = Nil {return nil, err} for _, KV: = Range resp. Kvs {var upt naming. Update If err: = json. Unmarshal (KV. Value, &upt); Err! = Nil {Continue} updates = append (updates, &upt)}//Create ETCD        Watcher Monitor the target (service name) information. OPTs: = []ETCD. Opoption{etcd. Withrev (resp. Header.revision + 1), Etcd. Withprefix (), Etcd. Withprevkv ()} Ew.watchchan = Ew.cli.Watch (context.        TODO (), Ew.target, opts ...) Return updates, nil}//Block listener, return to upper WRSP when service changes, OK: = <-ew.watchchan if!ok {err: = status. Error (Codes. Unavailable, "Etcd Watch closed") return nil, err} if wrsp. ERR ()! = nil {return nil, wrsp. ERR ()} for _, E: = Range wrsp. Events {var upt naming. Update var err error switch E.type {case ETCD. Eventtypeput:err = json. Unmarshal (E.kv.value, &upt) upt. Op = naming. ADD case Etcd. Eventtypedelete:err = json. Unmarshal (E.prevkv.value, &upt) upt. Op = naming. Delete} if Err! = Nil {Continue} updates = append (updates, &upt)} RET Urn updates, nil}

2.2 Service Side

The server only needs to escalate the service information and keep the heartbeat on time, which is achieved through the ETCD put interface and the KeepAlive interface.
Specific as follows:

Func (er *etcdregistry) Register (CTX context. Context, target string, update naming. Update, opts ... wrapper. registryoptions) (err Error) {//Serializes the service information into JSON format var upbytes []byte if upbytes, err = json. Marshal (update); Err! = Nil {return status. Error (codes. Invalidargument, Err. Error ()} ctx, Cancel: = context. Withtimeout (context. TODO (), resolvertimeout) er.cancal = Cancel Rgopt: = wrapper. Registryoption{ttl:wrapper. Defaultreginfttl} for _, opt: = Range opts {opt (&rgopt)} switch update. Op {case naming. ADD:LSRSP, err: = Er.lsCli.Grant (CTX, Int64 (Rgopt.ttl/time. Second)) If err! = Nil {return ERR}//put service information to ETCD, and set the value of key TTL, through the KeepAlive interface behind/ /To renew the TTL and not receive a renewal request at a time exceeding the TTL, the service may be suspended, thereby clearing the service information etcdopts: = []ETCD. Opoption{etcd. Withlease (Lsrsp.id)} key: = target + "/" + update.        Addr _, Err = Er.cli.KV.Put (CTX, Key, String (upbytes), etcdopts ...) If err! = Nil {REturn Err}//Keep heartbeat Lsrspchan, err: = er.lsCli.KeepAlive (context.                TODO (), lsrsp.id) if err! = Nil {return err} go func () {for { _, OK: = <-lsrspchan if!ok {grpclog. Fatalf ("%v keepalive channel is closing", key) Break}}} () Case n Aming. Delete: _, Err = Er.cli.Delete (CTX, target+ "/" +update. ADDR) Default:return status. Error (codes. Invalidargument, "Unsupported op")} return nil}

3. Reference

Https://github.com/g4zhuj/grp ...

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.