Better Programming

Advice for programmers.

Follow publication

Service Discovery With Go

Implementing service discovery with the avahi toolset

Cheikh seck
Better Programming
Published in
4 min readAug 14, 2022
Image by Thomas Jensen via unsplash

“Microservices service discovery is a way for applications and microservices to locate each other on a network.” This can be performed by having a central server with a list of addresses and service names, or a client that connects to a central server to retrieve and update addresses. When I first saw service discovery, my optimistic self thought it was something that operated via the “mDNS/DNS-SD protocol suite.” mDNS is the protocol used for AirPlay. It is a ZeroConfig interface, where consumers only need to connect the devices to the same network to interface with it. ZeroConfig, as the name implies, is a plug and play solution. What if this technology can be used for Microservices service discovery? It would certainly eliminate the need for a central server. “Avahi is a system which facilitates service discovery on a local network via the mDNS/DNS-SD protocol suite.” In this post, I’ll try to implement a web server that is discoverable via mDNS .

The Server

I’ll start by implementing a basic web server in Go. Here is the code for it :

func main() {  fmt.Println("listenning")
log.Fatal(http.ListenAndServe(":8080", nil))
}

Next, I’ll write a function that will broadcast my service via mDNS . This will be performed with command avahi-publish . The great thing about this command is once it exits, the service will stop broadcasting. I’ll invoke the command with Go’s exec package. Here is the code for the function :

func BroadCastMe(port, service string) {  cmd := exec.Command(
"avahi-publish",
"-s",
service,
"_http._tcp", // publish as http service
port,
)
if err := cmd.Run(); err != nil {
// close program if broadcast fails
log.Fatal(err)
}
}

Function BroadCastMe will be invoked as a Goroutine. Here is the final version of function main :

func main() {  fmt.Println("listening")  // broadcast will stop
// on program shutdown
go BroadCastMe("8080", "service-one")
log.Fatal(http.ListenAndServe(":8080", nil))
}

This server will broadcast itself on another thread while the actual server is running on the main thread. Now to discover the service.

Discovery

Discovering services will follow the same approach as publishing a service. A command from the avahi toolset will be ran to list available services. I’ll start by declaring a custom type to define a service, it’ll be called Service . Here is the definition of said struct :

type Service struct {
Name string
Address string
Port string
AddressType string
}

Next, I’ll implement a function to run command avahi-browse , this will look for http services. The command will be supplied with flag p to return parseable date. Flag t will ensure the program closes after the search is done. Once the command returns the list of services, I’ll employ some hacky method to extract the data needed to populate the struct type defined above. An array of Service is returned. Here is the code for this function :

func GetServices() ([]Service, error) { cmd := exec.Command(
"avahi-browse",
"-t", // type of protocol to look for
"_http._tcp", // http protocol
"-v",
"-r",
"-p", // prints parseable format
)
stdout, err := cmd.Output()
if err != nil {
return nil, err
}
strOutput := string(stdout)
rows := strings.Split(strOutput, "=")
result := []Service{} for i,v := range rows { if i == 0 {
continue
}
row := strings.Split(v, ";")
service := Service{
AddressType : row[2],
Name : row[3],
Address : row[7],
Port : row[8],
}

result = append(result, service)
} return result, nil}

Here is a basic implementation of the discovery code defined above :

func main() { services, err := GetServices() if err != nil {
log.Fatal(err)
}
fmt.Println(services)}

Here is this theory in action :

Conclusion

mDNS was intended to enable consumers “to plug your laptop or computer into a network and instantly be able to view other people who you can chat with, find printers to print to or find files being shared.” In my opinion, this technology should be part of the cloud native stack. I incorrectly assumed the Microservices service discovery operated in this fashion, but maybe it should operate in this manner. I don’t see a flaw with how service discovery is currently implemented ( central server). But my approach to this would mean one less microservice to manage, as the services can publish themself on the network. I’ve only tested this on my computer, so the behavior of this theory in other environments is unknown. It is also important to consider that this works with the avahi toolchain present. When deploying this, it may result in a larger payload size due to the avahi toolchain present with the app’s image. But maybe I’m wrong and it has no significant increase.

Before I sound like an idiot in public, How is “avahi” pronounced? is it “ava-Hee” or “ava-Hi”?

Additional Sources

What is Service Discovery? Definition and Related FAQs | Avi Networks

GitHub Repository

avahi-browse(1) — Linux man page

avahi — mDNS/DNS-SD

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Cheikh seck
Cheikh seck

Written by Cheikh seck

[Beta] Checkout my AI agents: https://zeroaigency.web.app/ Available for hire as a technical writer or software developer: cheeikhseck@gmail.com

Responses (5)

Write a response