MicroServices under Golang-Part 5th-event broker for Go Micro

Source: Internet
Author: User
Tags docker run
This is a creation in Article, where the information may have evolved or changed. In the [previous section] of this series (https://studygolang.com/articles/12485), we talked about user authentication and JWT. In this section, we will quickly explore the agent capabilities of Go-micro. As mentioned in the previous article, Go-micro is a pluggable framework that connects many different common technologies. If you look at [plugin warehouse] (https://github.com/micro/go-plugins), you will see how many plugins it supports. In our example, we will use the NATS proxy plugin. # # Event-Driven architecture [event-driven architecture] (https://en.wikipedia.org/wiki/Event-driven_architecture) is a very simple concept. We generally think that a good architecture is decoupled, that a service should not be coupled with other services or perceive other services. When we use a protocol such as ' Grpc ', in some cases it is correct, we take the request to ' Go.srv.user-service ' as an example. It uses the way service discovery is used to find the actual location of the service. Although this does not directly connect us to the implementation, it does couple the service to other services called ' Go.srv.user-service ', so it is not fully decoupled because it interacts directly with other services. So what makes the event-driven architecture truly decoupled? To understand this, let's look at the process of publishing and subscribing to events first. Service a completes a task X and then publishes an event ' x just happened ' to the system. The service does not need to know or care who is listening for this event, or what is happening with the event. These things are left to the client that listens for events. It's also easy if you expect N services to act on an event. For example, if you want 12 different services to act on creating a new user with ' Grpc ', you may need to instantiate 12 clients in User Services. With event publishing subscriptions or event-driven architectures, your services don't need to be concerned about these. Now, the client service only needs a simple listener event. This means that you need intermediate media to receive these events and to notify the client that subscribed to the event. In this article, we will create an event each time a user is created, and a new service will be created to send e-mail. We're not really going to implement the email feature, just simulate it. # # code First, we need to integrate the NATS proxy plug-in into our User services: ' go//shippy-user-service/main.gofunc maIn () {...//Init'll parse the command line Flags.srv.Init ()//Get instance of the broker using our defaultspubsub: = SR V.server (). Options (). broker//Register HANDLERPB. Registeruserservicehandler (SRV. Server (), &service{repo, Tokenservice, pubsub}) ...} "Now let's publish the event when we create a new user ([See full changes here] (https://github.com/EwanValentine/shippy-user-service/tree/tutorial-5)) ' go// Shippy-user-service/handler.goconst topic = "user.created" type service struct {repo Repositorytokenservice Authablepubsub Broker. Broker}...func (SRV *service) Create (CTX context. Context, req *PB. User, Res *PB. Response) Error {//generates a hashed version of our passwordhashedpass, err: = Bcrypt. Generatefrompassword ([]byte (req. Password), Bcrypt. Defaultcost) If err! = Nil {return err}req. Password = string (hashedpass) If err: = Srv.repo.Create (req); Err! = Nil {return err}res. User = Reqif Err: = Srv.publishevent (req); Err! = Nil {return Err}return nil}func (SRV *service) publishevent (user *pb. User) Error {//Marshal to JSON StriNgbody, err: = json. Marshal (user) if err! = Nil {return err}//Create a broker messagemsg: = &broker. message{header:map[string]string{"id": User. id,},body:body,}//Publish message to Brokerif err: = srv. Pubsub.publish (topic, MSG); Err! = Nil {log. Printf ("[Pub] Failed:%v", err)}return nil} ... "Make sure you're running Postgres and then let's run this service: ' shell$ Docker run-d-P 5432:5432 postgr Es$ made build$ make run "Now we create our email service. I created a [new warehouse] for this (https://github.com/EwanValentine/shippy-email-service): "' go//shippy-email-servicepackage Mainimport ("Encoding/json" "Log" PB "Github.com/ewanvalentine/shippy-user-service/proto/user" Micro "github.com/ Micro/go-micro "" Github.com/micro/go-micro/broker "_" github.com/micro/go-plugins/broker/nats ") const TOPIC =" User.created "Func main () {srv: = Micro. NewService (micro. Name ("Go.micro.srv.email"), Micro. Version ("latest"), SRV. Init ()//Get The broker instance using our environment variablespubsub: = srv. Server (). Options (). Brokerif err: = PubSub. Connect (); Err! = Nil {log.Fatal (Err)}//Subscribe to messages on the Broker_, err: = PubSub. Subscribe (Topic, func (P broker). Publication) Error {var user *pb. Userif ERR: = json. Unmarshal (P.message (). Body, &user); Err! = Nil {return err}log. PRINTLN (user) go SendEmail (user) return nil}) if err! = Nil {log. PRINTLN (Err)}//Run the Serverif err: = srv. Run (); Err! = Nil {log. PRINTLN (Err)}}func sendEmail (user *pb. User) Error {log. PRINTLN ("Sending email to:", user. Name) return nil} "" Before running, we need to start [NATS] (https://nats.io/) ... "$ docker run-d-P 4222:4222 NATS" and besides, I want to quickly explain Go-micro Part of it, I think it's important to understand how it works as a framework. You will notice: "' Gosrv. Init () PubSub: = srv. Server (). Options (). Broker ' ' Let's take a quick look. When we created the service with Go-micro, ' srv. Init () ' will automatically look for all configurations, such as plug-ins for all configurations, environment variables, or command-line options. It will instantiate these integrations as part of the service. In order to use these instances, we need to extract them from the service. In ' srv. Server (). Options () ', you can also find Transport (a core component of the GO-MICRO framework, transport is the interface between services for synchronous request/response communication) and Registry (a core component of the GO-MICRO framework, called the Registry, Provides a service discovery mechanism to resolve names to addresses). In our example, the ' go_micro_broker ' environment variable is used, the ' NATS ' proxy plugin is used, and an instance of the plugin is created, ready for us to connect and use. If you are creating a command-line tool, you canTo use ' cmd '. Init () ', make sure you import ' github.com/micro/go-micro/cmd '. This will have the same effect. Now build and run the service: ' Make build && makes run ' to ensure you are also running User services. Then go to the ' SHIPPY-USER-CLI ' project and run ' make run ' to see our email service output. You should see similar ... ' 2017/12/26 23:57:23 sending email To:ewan Valentine ' That's it! This is a simple example, because our email service implicitly listens to a single ' user.created ' event, but hopefully you can see how this approach allows you to write decoupled services. It is worth mentioning that using JSON over NATS will result in higher performance overhead than GRPC because we have returned to the realm of serializing JSON strings. However, for some use cases, this is perfectly acceptable. The NATS is very efficient and ideally suited for messages that are delivered at most once (fire and forget have a message to deliver at most once, this [link] (http://www.enterpriseintegrationpatterns.com/ patterns/conversation/fireandforget.html) can help in a deeper understanding). Go-micro also supports some of the most widely used queue/pubsub technologies for your use. [You can see a list of them here] (Https://github.com/micro/go-plugins/tree/master/broker). You don't need to change your implementation because GO-MICRO provides you with abstraction. You only need to change the environment variable from ' micro_broker=nats ' to ' micro_broker=googlepubsub ' and then import the Main.go from ' _ ' github.com/micro/go-plugins/ Broker/nats "' Changed to ' _ ' github.com/micro/go-plugins/broker/googlepubsub" '. If you do not use Go-micro, then there is a [NATS go Library] (https://github.com/nats-io/go-nats) (NATS is written with go, so support for Go is very solid). Publish an Event: ' Gonc, _: = Nats. Connect (Nats. Defaulturl)//Simple Publishernc.publish ("user.created", userjsonstring) ' Subscribe to an event: ' ' go//simple Async Subscribernc.subscribe ("user.created", func (M *nats). MSG) {User: = Convertuserstring (M.data) go sendEmail (user)}) "I mentioned earlier that when using a third-party message agent (such as NATS), you lose the use of protobuf. This is a shame because we lose the ability to communicate using binary streams, which of course is much less expensive than serialized JSON strings. But, as most people care, Go-micro can also solve this problem. The built-in Go-micro is the pubsub layer, above the agent layer, but does not require a third-party agent (such as NATS). But the real good part of this feature is that it takes advantage of the definition of protobuf. So we're back in the field of low latency binary streams. So let's update our user Service and replace the existing NATS agent with Go-micro pubsub: ' go//shippy-user-service/main.gofunc main () {... publisher: = Micro. Newpublisher ("user.created", srv. Client ())//Register HANDLERPB. Registeruserservicehandler (SRV. Server (), &service{repo, Tokenservice, publisher}) ...} "'" go//shippy-user-service/handler.gofunc (SRV *service) Create (CTX context. Context, req *PB. User, Res *PB. Response) Error {//generates a hashed version of our passwordhashedpass, err: = Bcrypt. Generatefrompassword ([]byte (req. Password),Bcrypt. Defaultcost) If err! = Nil {return err}req. Password = string (hashedpass)//Here's our new publisher code, much Simplerif err: = Srv.repo.Create (req); Err! = Nil {return err}res. User = Reqif Err: = srv. Publisher.publish (CTX, req); Err! = Nil {return Err}return nil} ' Now our mail service is like this: ' ' go//shippy-email-serviceconst topic = ' user.created ' type Subscriber Struct{}func (sub *subscriber) Process (CTX context. Context, user *PB. User) Error {log. Println ("Picked up a new message") log. PRINTLN ("Sending email to:", user. NAME) return Nil}func main () {... micro. Registersubscriber (topic, srv. Server (), new (subscriber)) ...} "Now we use our underlying User PROTOBUF definitions in our services, through GRPC, and do not use third-party agents." That's great! This is a wrapper! The next tutorial will focus on creating a user interface for our services and examining how WEB clients can begin interacting with our services. Any errors, feedback, or anything you will find useful in this article, please send me [email] (ewan.valentine89@gmail.com).

via:https://ewanvalentine.io/microservices-in-golang-part-5/

Author: Andrécarvalho Translator: Shniu proofreading: polaris1119

This article by GCTT original compilation, go language Chinese network honor launches

This article was originally translated by GCTT and the Go Language Chinese network. Also want to join the ranks of translators, for open source to do some of their own contribution? Welcome to join Gctt!
Translation work and translations are published only for the purpose of learning and communication, translation work in accordance with the provisions of the CC-BY-NC-SA agreement, if our work has violated your interests, please contact us promptly.
Welcome to the CC-BY-NC-SA agreement, please mark and keep the original/translation link and author/translator information in the text.
The article only represents the author's knowledge and views, if there are different points of view, please line up downstairs to spit groove

1282 Reads
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.