Golang using NSQ

Source: Internet
Author: User

This is a creation in Article, where the information may have evolved or changed.

Why to use NSQ

has recently been looking for a high-performance, highly available message queue to do communication between internal services. At first think of using ZEROMQ, but in the process of finding information, accidentally found NSQ this Golang developed message queue, after all, is Golang original things, full-featured, the key is the performance is good. Which support dynamic expansion, eliminate the single point of failure and other characteristics, can be very good to meet my needs

The previous comparison between NSQ and other MQ looks really powerful. Here is a simple record of how NSQ is used


NSQ Service Side

NSQ Service-Side introduction

Before using the NSQ service, it is still necessary to understand several core components of NSQ

The entire NSQ service consists of three main parts

Nsqlookupd

Let's take a look at what the official words say:

NSQLOOKUPD is the daemon responsible for managing topology information. The client discovers the producer of the specified topic (topic) by querying NSQLOOKUPD, and the NSQD node broadcasts the topic (topic) and channel information

Simply put, NSQLOOKUPD is the central management Service, which uses TCP (default port 4160) to manage the NSQD service, using HTTP (the default port 4161) to manage the Nsqadmin service. Also provides query functionality for clients


In general, NSQLOOKUPD has the following features or features

    • Uniqueness, there is only one NSQLOOKUPD service in a NSQ service. It is also possible to deploy multiple nsqlookupd in the cluster, but there is no association between them

    • De-NSQLOOKUPD, even if it crashes, will not affect the running NSQD service

    • Serves as a middleware for NSQD and naqadmin information interactions

    • Provides an HTTP query service to periodically update the NSQD address directory for clients

Nsqadmin

Official quote: A WEB UI that aggregates real-time statistics for a cluster and performs different management tasks

In general, Nsqadmin has the following features or features

    • Provide a unified management of topic and channel operation interface and a variety of real-time monitoring data display, interface design is very simple, easy to operate

    • Show the number of all the message, uh .... Pack x Sharp

    • Be able to create topic and channel in the background, this should not be used to

    • All features of Nsqadmin must rely on nsqlookupd,nsqadmin to simply pass user actions to NSQLOOKUPD and show data from NSQLOOKUPD


Nsqd

Official quote: NSQD is a daemon that is responsible for receiving, queuing, and delivering messages to clients

Simply put, the real work is the service, it is mainly responsible for the message of the transceiver, queue maintenance. NSQD will listen to a TCP port (4150) and an HTTP port (4151) and an optional HTTPS port by default

In general, NSQD has the following features or features

    • For subscribers to the same topic, the same channel consumer uses a load balancing policy (not polling)

    • As long as the channel exists, even consumers without the channel will cache the producer's message in the queue (note the expiration of the message)

    • The message in the queue is guaranteed to be consumed at least once, even if NSQD exits, the messages in the queue are staged on the disk (except for unexpected cases such as ending the process)

    • Limited memory consumption, ability to configure the number of message caches in memory for each channel queue in NSQD, and once exceeded, message will be cached to disk

    • Topic,channel once established, will always exist, in a timely manner in the management station or in code to remove invalid topic and channel, to avoid waste of resources

This is the official figure, the first channel (meteics) because there are multiple consumers, so triggered the load balancing mechanism. After two channel because there is no consumer, all the message will be cached in the corresponding queue until the consumer appears


One problem here is that if a channel is only being delivered by a producer, will it cause server resources to be exhausted? Perhaps the NSQD internally did the corresponding treatment, but to avoid the occurrence of this situation

NSQ server-to-client relationship

Understand the relationship between NSQLOOKUPD,NSQD and consumers and producers in the client

Consumers

Consumers have two ways of connecting with NSQD

    • Consumers directly connected to the NSQD, this is the simplest way, the disadvantage is that the NSQD service can not achieve dynamic scaling (of course, to achieve one is also possible)

    • The consumer obtains the connection address of all NSQD on the NSQLOOKUPD via HTTP query nsqlookupd and then establishes a connection with the NSQD (the official recommended practice), but the client constantly queries the NSQLOOKUPD for the latest NSQD address directory ( Don't like polling this way with http ...)
      Or take a closer look at the chart, the official consumer model:


Producers

Producers must directly connect NSQD to deliver a message (online said, can connect to NSQLOOKUPD, let nsqlookupd automatically choose a nsqd to complete delivery, but I use producer TCP is not even nsqlookupd, I don't know if HTTP can ...),

One problem here is that if the producer is connected to the NSQD, then the message will fail, so the client must implement the corresponding fallback plan.

Installing NSQ

Method One

    • First build the Golang development environment, here is not detailed

      • Note that it is best to add the bin directory to the System environment (PATH) when building the Golang environment, eliminating the hassle of going to the bin directory every time

    • Install Package Manager GODEP



go get github.com/tools/godep

After the execution, check whether the GODEP is installed in the bin directory, the general will automatically install, if not, with Go install manual installation under

    • Install Dependency Pack assert



go get github.com/bmizerany/assert
    • Installing NSQ



godep get github.com/bitly/nsq/...

If the installation succeeds, a lot of nsq_ will appear in the Bin directory ... The beginning of the executable file

    • PS: If the installation fails

      • Like me there's a whole bunch of "use of the internal package not allowed" error, looking for half a day to find this sentence in a corner
        Note: NSQ maintains go get compatibility, but is not recommended because it is not guaranteed to still compile.

      At this time the method of two installation

Method Two

    • Go directly to https://github.com/nsqio/nsq/releases download the compiled execution file, copy the executable file inside the bin directory to use the

Run NSQ

Running a standalone NSQD service

NSQD is an independent service, start a NSQD can complete message transceiver, start a single-machine nsqd, very simple



nsqd

The client can use HTTP, or TCP, where I use the official GO-NSQ package as the client, using TCP to send and receive message

    • Send

    • Receive

Running the NSQ service cluster

    • Start Nsqlookud First



nsqlookupd
    • Start Nsqd and access the Nsqlookud that just started. Here, to facilitate the next test, two Nsqd are launched.

nsqd--lookupd-tcp-address=127.0.0.1:4160


nsqd --lookupd-tcp-address=127.0.0.1:4160 -tcp-address=0.0.0.0:4152 -http-address=0.0.0.0:4153
    • Start Nqsadmin



nsqd --lookupd-http-address=127.0.0.1:4161

GO-NSQ-based client implementation

A few notable places

    • Producer will not be re-connected after disconnection, you need to manually re-connect, consumer disconnection will automatically re-connect

    • Consumer's re-connect time configuration item has two functions (this design must be spit out, a bit better separately)

      • Consumer detects that a connection to the NSQD has been broken, and every x seconds to the NSQD request to reconnect

      • Consumer every x seconds, HTTP polling to Nsqlookud to update their NSQD address directory

      • The consumer time of the default is 60s (...). The dishes are cold), I changed to 1s

    • Consumer can receive the same name topic data from different NSQD node at the same time, in order to avoid confusion, it must be processed on the client

    • The interface callbacks set in Addconurrenthandlers and AddHandler are performed in a different goroutine

    • Producer cannot publish (Publish) empty message, otherwise it will cause panic

Go_nsq-send.go



//Nsq send test
Package main

Import (
 "bufio"
 "fmt"
 "github.com/nsqio/go-nsq"
 "os"
)

Var producer *nsq.Producer

// main function
Func main() {
 strIP1 := "127.0.0.1:4150"
 strIP2 := "127.0.0.1:4152"
 InitProducer(strIP1)

 Running := true

 / / Read the console input
 Reader := bufio.NewReader(os.Stdin)
 For running {
  Data, _, _ := reader.ReadLine()
  Command := string(data)
  If command == "stop" {
   Running = false
  }

  For err := Publish("test", command); err != nil; err = Publish("test", command) {
   / / Switch IP reconnection
   strIP1, strIP2 = strIP2, strIP1
   InitProducer(strIP1)
  }
 }
 //shut down
 producer.Stop()
}

// Initialize the producer
Func InitProducer(str string) {
 Var err error
 fmt.Println("address: ", str)
 Producer, err = nsq.NewProducer(str, nsq.NewConfig())
 If err != nil {
 Panic(err)
 }
}

//make an announcement
Func Publish(topic string, message string) error {
 Var err error
 If producer = nil {
  If message == "" { //Cannot post an empty string, otherwise it will cause error
   Return nil
  }
  Err = producer.Publish(topic, []byte(message)) // Post a message
  Return err
 }
 Return fmt.Errorf("producer is nil", err)
}

go _nsq-receive.go



//Nsq receiving test
Package main

Import (
 "fmt"
 "time"

 "github.com/nsqio/go-nsq"
)

// consumer
Type ConsumerT struct{}

// main function
Func main() {
 InitConsumer("test", "test-channel", "127.0.0.1:4161")
 For {
  time.Sleep(time.Second * 10)
 }
}

/ / Process the message
Func (*ConsumerT) HandleMessage(msg *nsq.Message) error {
 fmt.Println("receive", msg.NSQDAddress, "message:", string(msg.Body))
 Return nil
}

/ / Initialize the consumer
Func InitConsumer(topic string, channel string, address string) {
 Cfg := nsq.NewConfig()
 cfg.LookupdPollInterval = time.Second //Set the reconnection time
 c, err := nsq.NewConsumer(topic, channel, cfg) // Create a new consumer
 If err != nil {
 Panic(err)
 }
 c.SetLogger(nil, 0) //mask system logs
 c.AddHandler(&ConsumerT{}) // Add consumer interface

 / / Establish NSQLookupd connection
 If err := c.ConnectToNSQLookupd(address); err != nil {
 Panic(err)
 }

 / / Establish multiple nsqd connections
 // if err := c.ConnectToNSQDs([]string{"127.0.0.1:4150", "127.0.0.1:4152"}); err != nil {
 // panic(err)
 // }

 // Create a nsqd connection
 // if err := c.ConnectToNSQD("127.0.0.1:4150"); err != nil {
 // panic(err)
 // }
}
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.