mirror of
https://github.com/fhmq/hmq.git
synced 2026-04-24 10:38:34 +00:00
cluster
This commit is contained in:
@@ -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": []
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
73
broker/clientmap.go
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user