🎉 Initial Commit

This commit is contained in:
2025-12-13 13:47:10 +08:00
commit 08d19913dc
8 changed files with 424 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
# Registrar
The Registrar is the service discovery system of the DysonNetwork.
Here are a port to the Golang in order to support other Golang services.
To use the system, try build with these API:
```go
package main
import (
"log"
"os"
"os/signal"
"syscall"
"yourmodule/registry"
)
func main() {
endpoints := []string{"localhost:2379"}
registrar, err := registry.NewServiceRegistrar(endpoints)
if err != nil {
log.Fatalf("Error creating registrar: %v", err)
}
serviceName := "orders"
host := "10.0.0.5"
port := 5000
ttl := int64(30)
err = registrar.Register(serviceName, host, port, ttl)
if err != nil {
log.Fatalf("Register error: %v", err)
}
log.Println("Service registered")
// Wait for termination
stop := make(chan os.Signal, 1)
signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM)
<-stop
err = registrar.Deregister()
if err != nil {
log.Printf("Deregister error: %v", err)
} else {
log.Println("Service deregistered")
}
}
```

View File

@@ -0,0 +1,84 @@
// Package registrar is for the service discovery system
package registrar
import (
"context"
"fmt"
"time"
clientv3 "go.etcd.io/etcd/client/v3"
)
type ServiceRegistrar struct {
client *clientv3.Client
leaseID clientv3.LeaseID
ttl int64
key string
cancel context.CancelFunc
}
// NewServiceRegistrar creates a registrar with the given etcd client
func NewServiceRegistrar(endpoints []string) (*ServiceRegistrar, error) {
cfg := clientv3.Config{
Endpoints: endpoints,
DialTimeout: 5 * time.Second,
}
cli, err := clientv3.New(cfg)
if err != nil {
return nil, err
}
return &ServiceRegistrar{client: cli}, nil
}
// Register service with etcd using TTL lease
func (r *ServiceRegistrar) Register(serviceName string, servicePart string, instanceID string, host string, port int, ttlSeconds int64) error {
r.ttl = ttlSeconds
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
defer cancel()
r.key = fmt.Sprintf("/services/%s/%s/%s", serviceName, servicePart, instanceID)
// Create lease
leaseResp, err := r.client.Grant(ctx, r.ttl)
if err != nil {
return err
}
r.leaseID = leaseResp.ID
// Put key with lease
_, err = r.client.Put(ctx, r.key, fmt.Sprintf("%s:%d", host, port), clientv3.WithLease(r.leaseID))
if err != nil {
return err
}
// Keep alive context
kaCtx, kaCancel := context.WithCancel(context.Background())
r.cancel = kaCancel
// Keep lease alive
go func() {
ch, err := r.client.KeepAlive(kaCtx, r.leaseID)
if err != nil {
fmt.Printf("KeepAlive error: %v\n", err)
return
}
for range ch {
// optionally inspect TTL updates here
}
}()
return nil
}
// Deregister removes the registered key and stops keep-alive
func (r *ServiceRegistrar) Deregister() error {
if r.cancel != nil {
r.cancel()
}
_, err := r.client.Delete(context.Background(), r.key)
return err
}

View File

@@ -0,0 +1,21 @@
package registrar
import (
"context"
"fmt"
clientv3 "go.etcd.io/etcd/client/v3"
)
func (r *ServiceRegistrar) ListInstance(serviceName string, servicePart string) ([]string, error) {
keyPrefix := fmt.Sprintf("/services/%s/%s", serviceName, servicePart)
resp, err := r.client.Get(context.Background(), keyPrefix, clientv3.WithPrefix())
if err != nil {
return nil, err
}
var result []string
for _, kv := range resp.Kvs {
result = append(result, string(kv.Value))
}
return result, nil
}