mirror of
https://gitee.com/rainbond/Rainbond.git
synced 2024-12-01 03:07:51 +08:00
170 lines
4.5 KiB
Go
170 lines
4.5 KiB
Go
// Copyright (C) 2014-2018 Goodrain Co., Ltd.
|
|
// RAINBOND, Application Management Platform
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
|
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
|
// must be obtained first.
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
package appruntimesync
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net"
|
|
"sync"
|
|
|
|
"github.com/goodrain/rainbond/util"
|
|
|
|
"github.com/Sirupsen/logrus"
|
|
client "github.com/coreos/etcd/clientv3"
|
|
"github.com/goodrain/rainbond/cmd/worker/option"
|
|
"github.com/goodrain/rainbond/appruntimesync/pb"
|
|
"github.com/goodrain/rainbond/appruntimesync/server"
|
|
discover "github.com/goodrain/rainbond/discover.v2"
|
|
"github.com/goodrain/rainbond/util/etcd/etcdlock"
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/reflection"
|
|
)
|
|
|
|
//AppRuntimeSync app runtime sync modle
|
|
// handle app status and event
|
|
type AppRuntimeSync struct {
|
|
conf option.Config
|
|
server *grpc.Server
|
|
etcdCli *client.Client
|
|
ctx context.Context
|
|
cancel context.CancelFunc
|
|
srss *server.AppRuntimeSyncServer
|
|
keepalive *discover.KeepAlive
|
|
master etcdlock.MasterInterface
|
|
hostIP string
|
|
masterRun bool
|
|
once sync.Once
|
|
}
|
|
|
|
//Start start if have master right
|
|
//start grpc server
|
|
func (a *AppRuntimeSync) Start(errchan chan error) {
|
|
if a.hostIP == "" {
|
|
ip, err := util.LocalIP()
|
|
if err != nil {
|
|
logrus.Errorf("get ip failed,details %s", err.Error())
|
|
errchan <- err
|
|
}
|
|
a.hostIP = ip.String()
|
|
}
|
|
util.Exec(a.ctx, func() error {
|
|
a.selectMaster(errchan)
|
|
return nil
|
|
}, 1)
|
|
}
|
|
func (a *AppRuntimeSync) selectMaster(errchan chan error) {
|
|
master, err := etcdlock.CreateMasterLock(a.conf.EtcdEndPoints, "/rainbond/workermaster", fmt.Sprintf("%s:%d", a.hostIP, 6535), 10)
|
|
if err != nil {
|
|
errchan <- err
|
|
return
|
|
}
|
|
a.master = master
|
|
master.Start()
|
|
defer master.Stop()
|
|
for {
|
|
select {
|
|
case event := <-master.EventsChan():
|
|
if event.Type == etcdlock.MasterAdded {
|
|
if err := a.srss.Start(); err != nil {
|
|
errchan <- err
|
|
return
|
|
}
|
|
go a.startAppRuntimeSync()
|
|
if err := a.registServer(); err != nil {
|
|
errchan <- err
|
|
return
|
|
}
|
|
a.masterRun = true
|
|
}
|
|
if event.Type == etcdlock.MasterDeleted {
|
|
if a.masterRun {
|
|
errchan <- fmt.Errorf("master node delete")
|
|
}
|
|
return
|
|
}
|
|
if event.Type == etcdlock.MasterError {
|
|
if event.Error.Error() == "elect: session expired" {
|
|
//TODO:if etcd error. worker restart
|
|
}
|
|
//if this is master node, exit
|
|
if a.masterRun {
|
|
errchan <- event.Error
|
|
}
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//Stop stop app runtime sync server
|
|
func (a *AppRuntimeSync) Stop() error {
|
|
a.once.Do(func() {
|
|
a.cancel()
|
|
a.srss.Stop()
|
|
if a.master != nil {
|
|
a.master.Stop()
|
|
}
|
|
if a.keepalive != nil {
|
|
a.keepalive.Stop()
|
|
}
|
|
})
|
|
return nil
|
|
}
|
|
|
|
//registServer
|
|
//regist sync server to etcd
|
|
func (a *AppRuntimeSync) registServer() error {
|
|
if a.keepalive == nil {
|
|
keepalive, err := discover.CreateKeepAlive(a.conf.EtcdEndPoints, "app_sync_runtime_server", "", a.conf.HostIP, 6535)
|
|
if err != nil {
|
|
return fmt.Errorf("create app sync server keepalive error,%s", err.Error())
|
|
}
|
|
a.keepalive = keepalive
|
|
}
|
|
return a.keepalive.Start()
|
|
}
|
|
|
|
//CreateAppRuntimeSync create app runtime sync model
|
|
func CreateAppRuntimeSync(conf option.Config) *AppRuntimeSync {
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
ars := &AppRuntimeSync{
|
|
conf: conf,
|
|
ctx: ctx,
|
|
cancel: cancel,
|
|
server: grpc.NewServer(),
|
|
srss: server.NewAppRuntimeSyncServer(conf),
|
|
hostIP: conf.HostIP,
|
|
}
|
|
pb.RegisterAppRuntimeSyncServer(ars.server, ars.srss)
|
|
// Register reflection service on gRPC server.
|
|
reflection.Register(ars.server)
|
|
return ars
|
|
}
|
|
|
|
//StartAppRuntimeSync start grpc server and regist to etcd
|
|
func (a *AppRuntimeSync) startAppRuntimeSync() error {
|
|
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", 6535))
|
|
if err != nil {
|
|
logrus.Errorf("failed to listen: %v", err)
|
|
return err
|
|
}
|
|
return a.server.Serve(lis)
|
|
}
|