Through the service discovery and registry, it is easy to manage the dynamic service instance information in the system. At the same time, it may also become the bottleneck and failure point of the system. Because the information for invocations between services comes from the service registry and discovery center, invocations between services may not work properly when it is unavailable. Therefore, service discovery and registries tend to be multi-instance deployments, providing high availability and stability.

We will implement service registration and discovery for Golang Web based on Consul. We will first interact with Consul via HTTP in a native way. We will then interact with Consul through the Consul Client interface provided by the Go Kit framework and compare the differences between them.

In the previous two articles, we learned about the complete microservice architecture and wrote an implementation of the core ConsulClient interface to complete the simple registration and discovery process between Consul and microservice. This article covers the implementation of service logout and service discovery. The service registration and discovery component, after each service instance is registered on it, provides service instance information to the service caller for the required request invocation.

The functions of service logout and service discovery will be implemented below.

Service cancellation

Following where we left off, we implement the DeRegister service logout method to actively send Consul a logout request before shutting down, as shown in the following code:

func (consulClient *ConsulClient) DeRegister(instanceId string, logger *log.Logger) bool { // 1. Req, err := http.NewRequest("PUT", "http://" + consulClient.Host + ":" + strconv.Itoa(consulClient.Port) + "/v1/agent/service/deregister/" +instanceId, nil) client := http.Client{} resp, err := client.Do(req) if err ! = nil { log.Println("Deregister Service Error!" ) }else { resp.Body.Close() if resp.StatusCode == 200{ log.Println("Unregister Service Success!" ) return true }else { log.Println("Deregister Service Error!" ) } } return false }Copy the code

Offline service logic is quite simple, just need to submit the service instance ID to/v1 / agent/service/deregister/directory. In the main function we monitor the system signal of CTRL + C and call the closeServer method to log out of the service and close the Web service before the service is shut down. After observing the registered SayHello service in Consul, we send CTRL + C to disable the service and you can see the following command line output:

^C2021/07/08 21:25:40 Deregister Service Success!
2021/07/08 21:25:40 Service is going to close...
2021/07/08 21:25:40 Closed the Server!
Copy the code

The above output tells us that the service instance was logged out successfully. Back in Consul, you can see that SayHello’s service instance does indeed no longer exist, as shown in the figure below:

Service discovery

The key to service discovery is to obtain the service instance list of the corresponding service and then select the specific service instance to invoke based on a certain load balancing policy. The DiscoverServices method obtains the service instance information list of the corresponding service from Consul, as shown in the following code:

func (consulClient *ConsulClient) DiscoverServices(serviceName string) []interface{} {

	Obtain the service instance list from Consul
	req, err := http.NewRequest("GET"."http://" + consulClient.Host + ":" + strconv.Itoa(consulClient.Port) + "/v1/health/service/" + serviceName, nil)

	client := http.Client{}
	resp, err := client.Do(req)

	iferr ! =nil {
		log.Println("Discover Service Error!")}else if resp.StatusCode == 200 {

		var serviceList [] struct {
			Service InstanceInfo `json:"Service"`
		}
		err = json.NewDecoder(resp.Body).Decode(&serviceList)
		resp.Body.Close()
		if err == nil {
			instances := make([]interface{}, len(serviceList))
			for i := 0; i < len(instances); i++ {
				instances[i] = serviceList[i].Service
			}
			return instances
		}
	}
	return nil
Copy the code

In the DiscoverServices method, submit the service name to the /v1/health/service/ path on Consul to obtain the list of service instances. We parse the JSON data of the service instance information list with the previously defined InstanceInfo structure, and then we can get the key metadata such as Host and Port of the corresponding service instance for service invocation.

In the main function, we define the/Discovery endpoint for obtaining a list of service instance information, accessed via the native IP and Port, such as my IP 10.93.246.254(available on Consul’s services page), Query service called SayHello, then request path to http://10.93.246.254:10086/discovery? ServiceName =SayHello, you can obtain information about all service instances where the SayHello service is registered with Consul:

[ { "ID": "71370f60-a76d-4ca8-9631-fb6ec49648ec", "Service": "SayHello", "Name": "", "Address": "10.93.246.254", "Port" : 10086, "EnableTagOverride" : false, "Check" : {" DeregisterCriticalServiceAfter ":" ", "HTTP: "" }, "Weights": { "Passing": 10, "Warning": 1 } } ]Copy the code

summary

This paper mainly implements the interaction process between Consul and microservice instance, including logout of service instance and service discovery.

In three articles, I introduced service registration and discovery based on Consul’s custom implementation of Go. This part of the code implementation, you can package into a package to call, add their own custom functionality and usage.

The full code, from my Github,Github.com/longjoy/mic…

Phase to recommend

  1. # Do-it-yourself service registration and discovery for Go (middle)
  2. How to learn ETCD? | I’m book

Read the latest article, pay attention to the public number: AOHO Qiusuo