lookup.go
package nsqd
import (
"bytes"
"encoding/json"
"net"
"os"
"strconv"
"time"
"github.com/nsqio/go-nsq"
"github.com/nsqio/nsq/internal/version"
)
func connectCallback(n *NSQD, hostname string, syncTopicChan chan *lookupPeer) func(*lookupPeer) {
return func(lp *lookupPeer) {
ci := make(map[string]interface{})
ci["version"] = version.Binary
ci["tcp_port"] = n.RealTCPAddr().Port
ci["http_port"] = n.RealHTTPAddr().Port
ci["hostname"] = hostname
ci["broadcast_address"] = n.getOpts().BroadcastAddress
cmd, err := nsq.Identify(ci)
if err != nil {
lp.Close()
return
}
resp, err := lp.Command(cmd)
if err != nil {
n.logf("LOOKUPD(%s): ERROR %s - %s", lp, cmd, err)
} else if bytes.Equal(resp, []byte("E_INVALID")) {
n.logf("LOOKUPD(%s): lookupd returned %s", lp, resp)
} else {
err = json.Unmarshal(resp, &lp.Info)
if err != nil {
n.logf("LOOKUPD(%s): ERROR parsing response - %s", lp, resp)
} else {
n.logf("LOOKUPD(%s): peer info %+v", lp, lp.Info)
}
}
go func() {
syncTopicChan <- lp
}()
}
}
func (n *NSQD) lookupLoop() {
var lookupPeers []*lookupPeer
var lookupAddrs []string
syncTopicChan := make(chan *lookupPeer)
connect := true
hostname, err := os.Hostname()
if err != nil {
n.logf("FATAL: failed to get hostname - %s", err)
os.Exit(1)
}
// for announcements, lookupd determines the host automatically
ticker := time.Tick(15 * time.Second)
for {
if connect {
for _, host := range n.getOpts().NSQLookupdTCPAddresses {
if in(host, lookupAddrs) {
continue
}
n.logf("LOOKUP(%s): adding peer", host)
lookupPeer := newLookupPeer(host, n.getOpts().MaxBodySize, n.getOpts().Logger,
connectCallback(n, hostname, syncTopicChan))
lookupPeer.Command(nil) // start the connection
lookupPeers = append(lookupPeers, lookupPeer)
lookupAddrs = append(lookupAddrs, host)
}
n.lookupPeers.Store(lookupPeers)
connect = false
}
select {
case <-ticker:
// send a heartbeat and read a response (read detects closed conns)
for _, lookupPeer := range lookupPeers {
n.logf("LOOKUPD(%s): sending heartbeat", lookupPeer)
cmd := nsq.Ping()
_, err := lookupPeer.Command(cmd)
if err != nil {
n.logf("LOOKUPD(%s): ERROR %s - %s", lookupPeer, cmd, err)
}
}
case val := <-n.notifyChan:
var cmd *nsq.Command
var branch string
switch val.(type) {
case *Channel:
// notify all nsqlookupds that a new channel exists, or that it's removed
branch = "channel"
channel := val.(*Channel)
if channel.Exiting() == true {
cmd = nsq.UnRegister(channel.topicName, channel.name)
} else {
cmd = nsq.Register(channel.topicName, channel.name)
}
case *Topic:
// notify all nsqlookupds that a new topic exists, or that it's removed
branch = "topic"
topic := val.(*Topic)
if topic.Exiting() == true {
cmd = nsq.UnRegister(topic.name, "")
} else {
cmd = nsq.Register(topic.name, "")
}
}
for _, lookupPeer := range lookupPeers {
n.logf("LOOKUPD(%s): %s %s", lookupPeer, branch, cmd)
_, err := lookupPeer.Command(cmd)
if err != nil {
n.logf("LOOKUPD(%s): ERROR %s - %s", lookupPeer, cmd, err)
}
}
case lookupPeer := <-syncTopicChan:
var commands []*nsq.Command
// build all the commands first so we exit the lock(s) as fast as possible
n.RLock()
for _, topic := range n.topicMap {
topic.RLock()
if len(topic.channelMap) == 0 {
commands = append(commands, nsq.Register(topic.name, ""))
} else {
for _, channel := range topic.channelMap {
commands = append(commands, nsq.Register(channel.topicName, channel.name))
}
}
topic.RUnlock()
}
n.RUnlock()
for _, cmd := range commands {
n.logf("LOOKUPD(%s): %s", lookupPeer, cmd)
_, err := lookupPeer.Command(cmd)
if err != nil {
n.logf("LOOKUPD(%s): ERROR %s - %s", lookupPeer, cmd, err)
break
}
}
case <-n.optsNotificationChan:
var tmpPeers []*lookupPeer
var tmpAddrs []string
for _, lp := range lookupPeers {
if in(lp.addr, n.getOpts().NSQLookupdTCPAddresses) {
tmpPeers = append(tmpPeers, lp)
tmpAddrs = append(tmpAddrs, lp.addr)
continue
}
n.logf("LOOKUP(%s): removing peer", lp)
lp.Close()
}
lookupPeers = tmpPeers
lookupAddrs = tmpAddrs
connect = true
case <-n.exitChan:
goto exit
}
}
exit:
n.logf("LOOKUP: closing")
}
func in(s string, lst []string) bool {
for _, v := range lst {
if s == v {
return true
}
}
return false
}
func (n *NSQD) lookupdHTTPAddrs() []string {
var lookupHTTPAddrs []string
lookupPeers := n.lookupPeers.Load()
if lookupPeers == nil {
return nil
}
for _, lp := range lookupPeers.([]*lookupPeer) {
if len(lp.Info.BroadcastAddress) <= 0 {
continue
}
addr := net.JoinHostPort(lp.Info.BroadcastAddress, strconv.Itoa(lp.Info.HTTPPort))
lookupHTTPAddrs = append(lookupHTTPAddrs, addr)
}
return lookupHTTPAddrs
}
lookup.go的更多相关文章
- SQL Server-聚焦移除Bookmark Lookup、RID Lookup、Key Lookup提高SQL查询性能(六)
前言 前面几节都是讲的基础内容,本节我们讲讲索引性能优化,当对大数据进行处理时首先想到的就是索引,一旦遇到这样的问题则手忙脚乱,各种查资料,为何平常不扎实基本功呢,我们由浅入深,简短的内容,深入的理解 ...
- Salesforce的sharing Rule 不支持Lookup型字段解决方案
Salesforce 中 sharing rule 并不支持Look up 字段 和 formula 字段.但在实际项目中,有时会需要在sharing rule中直接取Look up型字段的值,解决方 ...
- eclipse调试(debug)的时候,出现Source not found,Edit Source Lookup Path,一闪而过
问题描述 使用Eclipse调试代码的时候,打了断点,经常出现Source not found,网上找了半天,大部分提示点击Edit Source Lookup Path,添加被调试的工程,然而往往没 ...
- mongodb 3.x 之实用新功能窥看[2] ——使用$lookup做多表关联处理
这篇我们来看mongodb另一个非常有意思的东西,那就是$lookup,我们知道mongodb是一个文档型的数据库,而且它也是最像关系型数据库的 一种nosql,但是呢,既然mongodb是无模式的, ...
- Lookup component 用法
Lookup component 类似于Tsql的join子句, select a.* ,b.* from dbo.tis a left join dbo. tdes b on a.code=b.co ...
- [SharePoint]javascript client object model 获取lookup 类型的field的值,包括user类型(单人或者多人)的值。how to get the multiple user type/lookup type field value by Javascript client object model
1. how to get value var context = new SP.ClientContext.get_current(); var web = context.get_web(); v ...
- [SharePoint 2010] Modify lookup mapping with PowerShell
SharePoint支持将列表保存成列表模板,但当列表包含Lookup字段时,通过模板创建的列表会丢失Lookup字段的信息. 通过PowerShell,可以修改Lookup字段的xml内容. Fun ...
- Informatica Lookup Transformation组件的Connect 与Unconnected类型用法
Informatica Lookup Transformation组件的Connect 与Unconnected类型用法及区别:下面是通一个Lookup在不同Mapping中的使用: 1. Conne ...
- AX 2012 两种lookup 的显示方式
第一种:只能单选的lookup: 代码: public void BusinessUnitLookup(FormStringControl _formstrcontroll) { //OMOperat ...
- 创建一个List获取数据的lookup
第一步,在类:syslookup中新建方法 public static client void lookupList(FormStringControl _formStringControl, Lis ...
随机推荐
- 我应该跟libuv说声对不起,我错怪了libuv(转)
一开始,我得向Libuv库和Libuv库开发者以及相关粉丝们道一个歉,对不起,我错怪你们了.深深感到自己的无知,是多么羞愧的事情!! 事情的经过是这样的. 原先按照公司要求,我在开发Win ...
- Day15 jss整体结构梳理
JS DOM--- 两个步骤: 1 查找标签 (1)直接查找 document.getElementById("idname") // dom对象 document.getElem ...
- HBase最佳实践 - 集群规划
本文由 网易云发布. 作者:范欣欣 本篇文章仅限本站分享,如需转载,请联系网易获取授权. HBase自身具有极好的扩展性,也因此,构建扩展集群是它的天生强项之一.在实际线上应用中很多业务都运行在一个 ...
- Android Third Party Libraries and SDK's
http://javatechig.com/Android/android-third-party-libraries-sdks Over past few years, the age of mob ...
- require/exports 和 import/export 区别
零.区别 1.require/exports 是 CommonJS 的标准,适用范围如 Node.js 2.import/export 是 ES6 的标准,适用范围如 React 一.间接获取对象 ( ...
- (汇总)os模块以及shutil模块对文件的操作
''' # os 模块 os.sep 可以取代操作系统特定的路径分隔符.windows下为 '\\' os.name 字符串指示你正在使用的平台.比如对于Windows,它是'nt',而对于Linux ...
- java 字符串池【转】
java 字符串池 java运行环境有一个字符串池.比如String str="abc"时,会首先查看字符串池中是否存在字符串"abc",如果存在则直接将&qu ...
- CSS学习笔记六:写原生导航栏
因为刚开始学习CSS时,只了解了一些基本样式,然后就跑去学习bootstrap.bootstrap是个不错的东西,挺好玩,起码让你写界面写的轻轻松松,几行引入代码,再来个复制粘贴就解决了,而且boot ...
- HTTP协议、Ajax请求
今天这篇文章呢,主要讲的就是关于HTTP协议.Ajax请求以及一些相关的小知识点.虽然内容不算多,可是是很重点的东西~ HTTP协议 1. http:超文本传输协议.简单.快速.灵活.无状态.无连接. ...
- python 闯关之路三(面向对象与网络编程)
1,简述socket 通信原理 如上图,socket通信建立在应用层与TCP/IP协议组通信(运输层)的中间软件抽象层,它是一组接口,在设计模式中,socket其实就是一个门面模式,它把复杂的TCP/ ...