This commit is contained in:
zhouyuyan
2017-08-25 16:55:49 +08:00
parent 0ea7da1dc0
commit 5c6e136c2b
6 changed files with 201 additions and 35 deletions

View File

@@ -1,4 +1,9 @@
{
"port": "1883",
"host": "0.0.0.0"
"host": "0.0.0.0",
"cluster": {
"host": "0.0.0.0",
"port": "1993",
"routes": []
}
}

View File

@@ -9,32 +9,49 @@ import (
)
type Broker struct {
id string
config *Config
remote map[string]*client
sl *Sublist
rl *RetainList
queues map[string]int
id string
config *Config
clients ClientMap
routes ClientMap
sl *Sublist
rl *RetainList
queues map[string]int
}
func NewBroker(config *Config) *Broker {
return &Broker{
config: config,
sl: NewSublist(),
rl: NewRetainList(),
queues: make(map[string]int),
remote: make(map[string]*client),
config: config,
sl: NewSublist(),
rl: NewRetainList(),
queues: make(map[string]int),
clients: NewClientMap(),
routes: NewClientMap(),
}
}
func (b *Broker) StartListening() {
hp := b.config.Host + ":" + b.config.Port
func (b *Broker) Start() {
go b.StartListening(CLIENT)
if b.config.Cluster.Port != "" {
go b.StartListening(ROUTER)
}
}
func (b *Broker) StartListening(typ int) {
var hp string
if typ == CLIENT {
hp = b.config.Host + ":" + b.config.Port
log.Info("Start Listening client on ", hp)
} else if typ == ROUTER {
hp = b.config.Cluster.Host + ":" + b.config.Cluster.Port
log.Info("Start Listening cluster on ", hp)
}
l, e := net.Listen("tcp", hp)
if e != nil {
log.Error("Error listening on ", e)
return
}
log.Info("Start Listening client on ", hp)
tmpDelay := 10 * ACCEPT_MIN_SLEEP
num := 0
for {
@@ -55,11 +72,11 @@ func (b *Broker) StartListening() {
}
tmpDelay = ACCEPT_MIN_SLEEP
num += 1
go b.handleConnection(conn, num)
go b.handleConnection(typ, conn, num)
}
}
func (b *Broker) handleConnection(conn net.Conn, idx int) {
func (b *Broker) handleConnection(typ int, conn net.Conn, idx int) {
//process connect packet
buf, err := ReadPacket(conn)
if err != nil {
@@ -105,5 +122,45 @@ func (b *Broker) handleConnection(conn net.Conn, idx int) {
info: info,
}
c.init()
var exist bool
var old *client
cid := string(c.info.clientID)
if typ == CLIENT {
old, exist = b.clients.Update(cid, c)
} else if typ == ROUTER {
old, exist = b.routes.Update(cid, c)
}
if exist {
log.Warn("client or routers exists, close old...")
old.Close()
}
c.readLoop(idx)
}
func (b *Broker) ConnectToRouters() {
for i := 0; i < len(b.config.Cluster.Routes); i++ {
url := b.config.Cluster.Routes[i]
go b.connectRouter(url, "")
}
}
func (b *Broker) connectRouter(url, remoteID string) {
for {
conn, err := net.Dial("tcp", url)
if err != nil {
log.Error("Error trying to connect to route: ", err)
select {
case <-time.After(DEFAULT_ROUTE_CONNECT):
log.Debug("Connect to route timeout ,retry...")
continue
}
}
route := &route{
remoteID: remoteID,
remoteUrl: url,
}
// s.createRemote(conn, route)
return
}
}

View File

@@ -10,14 +10,25 @@ import (
log "github.com/cihub/seelog"
)
const (
// special pub topic for cluster info BrokerInfoTopic
BrokerInfoTopic = "broker001info/brokerinfo"
// CLIENT is an end user.
CLIENT = 0
// ROUTER is another router in the cluster.
ROUTER = 1
//REMOTE is the router connect to other cluster
REMOTE = 2
)
type client struct {
mu sync.Mutex
broker *Broker
conn net.Conn
info info
localIP string
remoteIP string
subs map[string]*subscription
typ int
mu sync.Mutex
broker *Broker
conn net.Conn
info info
route *route
subs map[string]*subscription
}
type subscription struct {
@@ -33,12 +44,19 @@ type info struct {
password []byte
keepalive uint16
willMsg *message.PublishMessage
localIP string
remoteIP string
}
type route struct {
remoteID string
remoteUrl string
}
func (c *client) init() {
c.subs = make(map[string]*subscription, 10)
c.localIP = strings.Split(c.conn.LocalAddr().String(), ":")[0]
c.remoteIP = strings.Split(c.conn.RemoteAddr().String(), ":")[0]
c.info.localIP = strings.Split(c.conn.LocalAddr().String(), ":")[0]
c.info.remoteIP = strings.Split(c.conn.RemoteAddr().String(), ":")[0]
}
func (c *client) readLoop(idx int) {

73
broker/clientmap.go Normal file
View File

@@ -0,0 +1,73 @@
package broker
import "sync"
type ClientMap interface {
Set(key string, val *client)
Get(key string) (*client, bool)
Items() map[string]*client
Exist(key string) bool
Update(key string, val *client) (*client, bool)
Count() int
Remove(key string)
}
type clientMap struct {
items map[string]*client
mu sync.RWMutex
}
func NewClientMap() ClientMap {
smap := &clientMap{
items: make(map[string]*client),
}
return smap
}
func (s *clientMap) Set(key string, val *client) {
s.mu.Lock()
s.items[key] = val
s.mu.Unlock()
}
func (s *clientMap) Get(key string) (*client, bool) {
s.mu.RLock()
val, ok := s.items[key]
s.mu.RUnlock()
return val, ok
}
func (s *clientMap) Exist(key string) bool {
s.mu.RLock()
_, ok := s.items[key]
s.mu.RUnlock()
return ok
}
func (s *clientMap) Update(key string, val *client) (*client, bool) {
s.mu.Lock()
old, ok := s.items[key]
s.items[key] = val
s.mu.Unlock()
return old, ok
}
func (s *clientMap) Count() int {
s.mu.RLock()
len := len(s.items)
s.mu.RUnlock()
return len
}
func (s *clientMap) Remove(key string) {
s.mu.Lock()
delete(s.items, key)
s.mu.Unlock()
}
func (s *clientMap) Items() map[string]*client {
s.mu.RLock()
items := s.items
s.mu.RUnlock()
return items
}

View File

@@ -13,8 +13,15 @@ const (
)
type Config struct {
Host string `json:"host"`
Port string `json:"port"`
Host string `json:"host"`
Port string `json:"port"`
Cluster RouteInfo `json:"cluster"`
}
type RouteInfo struct {
Host string `json:"host"`
Port string `json:"port"`
Routes []string `json:"routes"`
}
func LoadConfig() (*Config, error) {
@@ -23,20 +30,26 @@ func LoadConfig() (*Config, error) {
log.Error("Read config file error: ", err)
return nil, err
}
var info Config
err = json.Unmarshal(content, &info)
var config Config
err = json.Unmarshal(content, &config)
if err != nil {
log.Error("Unmarshal config file error: ", err)
return nil, err
}
if info.Port != "" {
if info.Host == "" {
info.Host = "0.0.0.0"
if config.Port != "" {
if config.Host == "" {
config.Host = "0.0.0.0"
}
} else {
return nil, errors.New("Listen port nil")
}
return &info, nil
if config.Cluster.Port != "" {
if config.Cluster.Host == "" {
config.Cluster.Host = "0.0.0.0"
}
}
return &config, nil
}

View File

@@ -16,7 +16,7 @@ func main() {
}
broker := broker.NewBroker(config)
broker.StartListening()
broker.Start()
s := waitForSignal()
log.Infof("signal got: %v ,broker closed.", s)