Simple Service Discovery in Go
Service discovery is a crucial component of microservice architectures, allowing services to dynamically locate and communicate with each other. This challenge asks you to implement a basic service discovery system in Go, enabling services to register themselves and other services to query for available instances. This is a simplified version, focusing on core functionality rather than production-ready features like health checks or load balancing.
Problem Description
You are tasked with building a simple service discovery system. The system should allow services to register themselves with a central registry, providing a service name and an address (IP:Port). Other services can then query the registry to find the addresses of instances providing a specific service.
What needs to be achieved:
- Implement a
ServiceRegistrystruct to store registered services. - Implement a
RegisterServicefunction that adds a service to the registry. The function should accept a service name (string) and an address (string, e.g., "127.0.0.1:8080"). - Implement a
DiscoverServicesfunction that retrieves a list of addresses for a given service name. - The registry should be in-memory.
Key Requirements:
- The registry should handle duplicate registrations gracefully (e.g., ignore them).
- The
DiscoverServicesfunction should return an empty list if no services are registered for the given name. - Error handling should be minimal for this exercise; focus on the core logic.
Expected Behavior:
- A service registers with the name "my-service" and the address "127.0.0.1:8080".
- Another service queries for "my-service".
- The query should return a list containing "127.0.0.1:8080".
- If no service is registered with the name "unknown-service", the query should return an empty list.
Edge Cases to Consider:
- Empty service name or address during registration. (For simplicity, you can ignore these and just not register the service.)
- Multiple services registering with the same name and address. (Ignore duplicates.)
Examples
Example 1:
Input:
- Register: ServiceName="my-service", Address="127.0.0.1:8080"
- Register: ServiceName="my-service", Address="127.0.0.1:8081"
- Discover: ServiceName="my-service"
Output: ["127.0.0.1:8080", "127.0.0.1:8081"]
Explanation: Two services with the name "my-service" were registered, so the discovery function returns both addresses.
Example 2:
Input:
- Register: ServiceName="my-service", Address="127.0.0.1:8080"
- Discover: ServiceName="unknown-service"
Output: []
Explanation: No services are registered with the name "unknown-service", so an empty list is returned.
Example 3: (Duplicate Registration)
Input:
- Register: ServiceName="my-service", Address="127.0.0.1:8080"
- Register: ServiceName="my-service", Address="127.0.0.1:8080"
- Discover: ServiceName="my-service"
Output: ["127.0.0.1:8080"]
Explanation: The second registration with the same name and address is ignored, and only one entry is returned.
Constraints
- Service names and addresses are strings.
- The registry is in-memory and will be lost when the program exits.
- The number of registered services is expected to be relatively small (less than 100).
- Performance is not a primary concern for this exercise.
Notes
- Consider using a
mapin Go to store the service registry. The key could be the service name, and the value could be a list of addresses. - Focus on the core functionality of registration and discovery. Error handling and more advanced features (like health checks) are beyond the scope of this challenge.
- Think about how to represent the service registry data structure effectively.
- This is a simplified model; real-world service discovery systems are significantly more complex.