RegistrationDB保存集群中nsqd的拓扑信息及注册和心跳信息
nsqlookupd参考资料
RegistrationDB是一个map类型 map[Registration]Producers ,在读写操作过程中使用读写锁来保证数据一致性
nsqlookupd/registration_db.go
type RegistrationDB struct {
sync.RWMutex
registrationMap map[Registration]Producers
}
// nsqd的注册信息
type Registration struct {
Category string // 类别,client、topic、channel。其中client则表示nsqd在第一次连接nsqlookup的IDENTITY验证信息
Key string // topic名称
SubKey string // channel名称
}
type Registrations []Registration
// nsqd主机相关信息
type PeerInfo struct {
lastUpdate int64 // nsqd的心跳更新时间
id string // nsqd的ip地址作为唯一标识
RemoteAddress string `json:"remote_address"` // ip地址
Hostname string `json:"hostname"` // 主机名
BroadcastAddress string `json:"broadcast_address"` // 广播地址
TCPPort int `json:"tcp_port"` // tcp端口
HTTPPort int `json:"http_port"` // http端口
Version string `json:"version"` // nsqd版本
}
// nsqd相关信息
type Producer struct {
peerInfo *PeerInfo // nsqd主机相关信息
tombstoned bool // nsqd是否被逻辑删除
tombstonedAt time.Time // 被标识为tombstoned的时间戳
}
/*
逻辑删除:让某一个topic不在集群中的某个nsqd上生产
在TombstoneLifetime时间周期内(默认45s),生产者不会在/lookup查询中列出该nsqd节点,并阻止consumer重新发现这个nsqd节点
*/
// add a registration key
// 当nsqd创建topic或channel时注册到nsqlookup
func (r *RegistrationDB) AddRegistration(k Registration) {
r.Lock()
defer r.Unlock()
_, ok := r.registrationMap[k]
if !ok {
r.registrationMap[k] = Producers{}
}
}
// remove a Registration and all it's producers
// 当nsqd删除topic或channel时从nsqlookup中删除
func (r *RegistrationDB) RemoveRegistration(k Registration) {
r.Lock()
defer r.Unlock()
delete(r.registrationMap, k)
}
// 查找注册信息
func (r *RegistrationDB) FindRegistrations(category string, key string, subkey string) Registrations {
r.RLock()
defer r.RUnlock()
if !r.needFilter(key, subkey) {
k := Registration{category, key, subkey}
if _, ok := r.registrationMap[k]; ok {
return Registrations{k}
}
return Registrations{}
}
results := Registrations{}
for k := range r.registrationMap {
if !k.IsMatch(category, key, subkey) {
continue
}
results = append(results, k)
}
return results
}
// add a producer to a registration
// 添加Producer
func (r *RegistrationDB) AddProducer(k Registration, p *Producer) bool {
r.Lock()
defer r.Unlock()
producers := r.registrationMap[k]
found := false
for _, producer := range producers {
if producer.peerInfo.id == p.peerInfo.id {
found = true
}
}
if found == false {
r.registrationMap[k] = append(producers, p)
}
return !found
}
// remove a producer from a registration
// 删除Producer
func (r *RegistrationDB) RemoveProducer(k Registration, id string) (bool, int) {
r.Lock()
defer r.Unlock()
producers, ok := r.registrationMap[k]
if !ok {
return false, 0
}
removed := false
cleaned := Producers{}
for _, producer := range producers {
if producer.peerInfo.id != id {
cleaned = append(cleaned, producer)
} else {
removed = true
}
}
// Note: this leaves keys in the DB even if they have empty lists
r.registrationMap[k] = cleaned
return removed, len(cleaned)
}
// 查找Producers信息
func (r *RegistrationDB) FindProducers(category string, key string, subkey string) Producers {
r.RLock()
defer r.RUnlock()
if !r.needFilter(key, subkey) {
k := Registration{category, key, subkey}
return r.registrationMap[k]
}
results := Producers{}
for k, producers := range r.registrationMap {
if !k.IsMatch(category, key, subkey) {
continue
}
for _, producer := range producers {
found := false
for _, p := range results {
if producer.peerInfo.id == p.peerInfo.id {
found = true
}
}
if found == false {
results = append(results, producer)
}
}
}
return results
}
// 通过id查找注册信息
func (r *RegistrationDB) LookupRegistrations(id string) Registrations {
r.RLock()
defer r.RUnlock()
results := Registrations{}
for k, producers := range r.registrationMap {
for _, p := range producers {
if p.peerInfo.id == id {
results = append(results, k)
break
}
}
}
return results
}