func (s *Server) RegisteAsLocalService(recv interface{}) { t := reflect.TypeOf(recv) v := reflect.ValueOf(recv) numMethod := t.NumMethod() sName := v.Type().Name() for index := 0; index < numMethod; index++ { methodName := t.Method(index).Name if handler, ok := v.Method(index).Interface().(func(*sessionService.SimpleSession, map[string]interface{}) map[string]interface{}); ok == true { s.handlers[sName+"."+methodName] = handler seelog.Infof("<%v> Registe local service<%v>'s method<%v>", context.GetContext().GetServerID(), v.Type().Name(), methodName) } else { seelog.Warnf("<%v> Registe local service <%v>'s method<%v> error", context.GetContext().GetServerID(), v.Type().Name(), methodName) } } }
func main() { if len(os.Args) < 3 { fmt.Fprintf(os.Stderr, "too few args,args form: <host port>\n") os.Exit(1) } host := os.Args[1] port, err := strconv.Atoi(os.Args[2]) if err != nil { fmt.Fprintf(os.Stderr, "invalid port,need integer type,your input port: <port>\n", os.Args[2]) os.Exit(1) } ctx := context.GetContext() currentServer := make(map[string]interface{}) currentServer["id"] = "connector-1" currentServer["serverType"] = "connector" currentServer["host"] = "127.0.0.1" currentServer["port"] = 8888 ctx.CurrentServer = currentServer defer seelog.Flush() tcp_cnct := tcp_connector.NewTcpConnector(host, port, nil) tcp_cnct.RegistNewConnCB(NewConnCB) tcp_cnct.RegistNewMsgCB(NewMsgCB) tcp_cnct.Start() ch := make(chan int) <-ch }
func (ts *TcpSocket) Disconnect() { seelog.Debugf("<%v> Disconnect sid<%v>", context.GetContext().GetServerID(), ts.id) if ts.status == connector.ST_CLOSED { return } ts.status = connector.ST_CLOSED ts.socket.Close() }
func NewChannelRpcServer() *ChannelRpcServer { ctx := context.GetContext() coCnct, ok := ctx.GetComponent("coconnector").(*coconnector.CoConnector) if ok == false { coCnct = coconnector.NewCoConnector(ctx) } return &ChannelRpcServer{coCnct} }
func (crs *ChannelRpcServer) PushMessage(args map[string]interface{}, reply interface{}) error { route, _ := args["route"].(string) msg, ok1 := args["msg"].(map[string]interface{}) if ok1 == false { seelog.Error("Invalid or empty message") return errors.New("Invalid or empty message") } coSess, ok2 := context.GetContext().GetComponent("cosession").(*cosession.CoSession) if ok2 == false { seelog.Critical("Failed to get component<cosession>") os.Exit(1) } uids, ok3 := args["uids"].([]string) if ok3 == false { seelog.Error("Failed to get uids") return errors.New("Failed to get uids") } sids := make([]uint32, 0, 16) for _, uid := range uids { sessions := coSess.GetSessionsByUID(uid) if sessions == nil { seelog.Warnf("Failed to push message to uid<%v> because of nil sessions", uid) continue } for _, session := range sessions { sids = append(sids, session.Id) } } seelog.Debugf("<%v> push messages<%v> to uids<%v> with sessions<%v>", context.GetContext().GetServerID(), msg, uids, sids) //XXX:调用coconnector的send方法发送. crs.coCnct.Send("", route, msg, sids) return nil }
func NewCoServer() *CoServer { ctx := context.GetContext() coServ, ok := ctx.GetComponent("coserver").(*CoServer) if ok == true { return coServ } serv := server.NewServer() coServ = &CoServer{serv} seelog.Infof("<%v> component server created", ctx.GetServerID()) return coServ }
func NewSessionRpcServer() *SessionRpcServer { ctx := context.GetContext() sessionService, ok := ctx.GetComponent("cosession").(*cosession.CoSession) if ok == false || sessionService == nil { sessionService = cosession.NewCoSession() } return &SessionRpcServer{sessionService} }
func (srs *SessionRpcServer) Start() { ctx := context.GetContext() coRpcS, ok := ctx.GetComponent("corpcserver").(*corpcserver.CoRpcServer) if ok == false { coRpcS = corpcserver.NewCoRpcServer() } seelog.Infof("frontendserver<%v> SessionRpcServer start,registe service to rpc server", ctx.GetServerID()) // srs := NewSessionRpcServer() coRpcS.RegisteService(srs) }
/// 创建新的ChannelService,ChannelService管理用户创建的所有Channel,并代理用户对Channel的操作, /// 用户发送给一个Channel里所有session的消息会通过rpc调用发送给对应的前端服务器,并通过前端服务 /// 器推送给客户端. func NewChannelService() *ChannelService { ctx := context.GetContext() coRpcClient, ok := ctx.GetComponent("corpcclient").(*corpcclient.CoRpcClient) if ok == false { coRpcClient = corpcclient.NewCoRpcClient() } channels := make(map[string]*Channel) return &ChannelService{ctx, coRpcClient, channels} }
func (crs *ChannelRpcServer) Start() { ctx := context.GetContext() coRpcS, ok := ctx.GetComponent("corpcserver").(*corpcserver.CoRpcServer) if ok == false { coRpcS = corpcserver.NewCoRpcServer() } seelog.Info("ChannelRpcServer start,registe service to rpcserver") // srs := NewSessionRpcServer() coRpcS.RegisteService(crs) }
func NewCoMonitor() *CoMonitor { ctx := context.GetContext() coMonitor, ok := ctx.GetComponent("comonitor").(*CoMonitor) if ok == true { return coMonitor } mcs := pomelo_admin.NewMonitorConsoleService(ctx) coMonitor = &CoMonitor{mcs} seelog.Infof("<%v> component CoMonitor created...", ctx.GetServerID()) ctx.RegisteComponent("comonitor", coMonitor) return coMonitor }
/// 通过session id从前端服务器踢除用户连接,通过rpc调用前端服务器的同样操作. /// /// @param frontendid 前端服务器id /// @param sid session id /// @reason 作为踢除用户连接时发送给用户端的提示信息. /// @return 无返回值 func (bss *BackendSessionService) KickBySID(frontendid string, sid uint32, reason string) { seelog.Tracef("frontendid<%v>,sid<%v>", frontendid, sid) method := "SessionRpcServer.KickBySID" args := make([]interface{}, 2) args[0] = sid args[1] = reason if err := bss.rpcCient.RpcCall(frontendid, method, args, nil); err != nil { seelog.Errorf("<%v> KickBySID error<%v>", context.GetContext().GetServerID(), err.Error()) } }
/// 创建新的SessionService. /// /// @param opts 指定创建SessionService的选项,选项是name:value的形式 /// @return *SessionService func NewSessionService(opts map[string]interface{}) *SessionService { if nil == opts { opts = make(map[string]interface{}) } sessions := make(map[uint32]*Session) uidmap := make(map[string][]*Session) multibind := opts["multiBind"] != nil && (opts["multiBind"].(string) != "") rwMutexS := new(sync.RWMutex) rwMutexUM := new(sync.RWMutex) seelog.Infof("frontendserver<%v> create sessionservice with opts<%v>", context.GetContext().GetServerID(), opts) return &SessionService{sessions, uidmap, multibind, opts, rwMutexS, rwMutexUM} }
/// 发送消息到groups中的所有用户. /// /// @route 路由 /// @param msg 发送的消息 /// @param groups frontendID-> uids的映射 func (cs *ChannelService) sendMsgByGroup(route string, msg map[string]interface{}, groups map[string][]string) { seelog.Debugf("<%v> channelService sendMsgByGroup with route<%v> msg<%v> groups<%v>", cs.ctx.GetServerID(), route, msg, groups) args := make(map[string]interface{}) args["route"] = route args["msg"] = msg coChanRpcS, ok := context.GetContext().GetComponent("cochannelrpcserver").(*cochannelrpcserver.CoChannelRpcServer) if ok == false { seelog.Error("Fail to get CoChannelRpcServer") return } sendMsg := func(serverid string) { if cs.ctx.GetServerID() == serverid { //TODO:直接调用channelRpcServer相关方法,无需rpc if err := coChanRpcS.PushMessage(args, nil); err != nil { seelog.Errorf("Fail to invoke PushMessage to send msg,error<%v>", err.Error()) return } } else { //TODO:发起rpc调用. if err := cs.coRpcClient.RpcCall(serverid, "ChannelRpcServer.PushMessage", args, nil); err != nil { seelog.Errorf("<%v> fail to invoke rpc PushMessage error<%v>", context.GetContext().GetServerID(), err.Error()) return } } } for frontendID, uids := range groups { //TODO:逐个发送msg. seelog.Infof("<%v> PushMessage to uids<%v> connected to frontend<%v>", context.GetContext().GetServerID(), uids, frontendID) args["uid"] = uids sendMsg(frontendID) } }
func (bss *BackendSessionService) PushAllOpts(frontendid string, sid uint32, settings map[string]interface{}) { seelog.Tracef("Push all opts to <%v> with sid<%v>", frontendid, sid) args := make(map[string]interface{}) args["sid"] = sid args["settings"] = settings method := "SessionRpcServer.PushAllOpts" if err := bss.rpcCient.RpcCall(frontendid, method, &args, nil); err != nil { seelog.Errorf("<%v> PushAllOpts with sid<%v> to frontend<%v> error<%v>", context.GetContext().GetServerID(), sid, frontendid, err.Error()) } }
func NewCoChannel() *CoChannel { ctx := context.GetContext() coChan, ok := ctx.GetComponent("cochannel").(*CoChannel) if ok == true { return coChan } chanS := channelService.NewChannelService() coChan = &CoChannel{chanS} ctx.RegisteComponent("cochannel", coChan) seelog.Info("CoChannel create successfully") return coChan }
func NewCoBackendSession() *CoBackendSession { ctx := context.GetContext() coBS, ok := ctx.GetComponent("cobackendsession").(*CoBackendSession) if ok == true { return coBS } bss := backendSessionService.NewBackendSessionService(ctx) coBS = &CoBackendSession{bss} ctx.RegisteComponent("cobackendsession", coBS) return coBS }
func NewCoConnection() *CoConnection { ctx := context.GetContext() coconn, ok := ctx.GetComponent("coconnection").(*CoConnection) if ok == true { return coconn } cs := connectionService.NewConnectionService(ctx.GetServerID()) coconn = &CoConnection{cs, ctx} ctx.RegisteComponent("coconnection", coconn) seelog.Infof("CoConnetion create successfully") return coconn }
func NewCoChannelRpcServer() *CoChannelRpcServer { ctx := context.GetContext() coChanRS, ok := ctx.GetComponent("cochannelrpcserver").(*CoChannelRpcServer) if ok == false { seelog.Infof("CoChannelRpcServer not found,create new...") chanRpcS := channelRpcServer.NewChannelRpcServer() coChanRS = &CoChannelRpcServer{chanRpcS} ctx.RegisteComponent("cochannelrpcserver", coChanRS) } seelog.Infof("CoChannelRpcServer create successfully") return coChanRS }
/// 创建CoSession. func NewCoSession() *CoSession { ctx := context.GetContext() cosess, ok := ctx.GetComponent("cosession").(*CoSession) if ok == true { return cosess } ss := sessionService.NewSessionService(ctx.AllOpts["cosession"]) cosess = &CoSession{ss} ctx.RegisteComponent("cosession", cosess) seelog.Info("CoSession create successufully") return cosess }
func NewServer() *Server { ctx := context.GetContext() coRpcS, ok1 := ctx.GetComponent("corpcserver").(*corpcserver.CoRpcServer) if ok1 == false { coRpcS = corpcserver.NewCoRpcServer() } coRpcC, ok2 := ctx.GetComponent("corpcclient").(*corpcclient.CoRpcClient) if ok2 == false { coRpcC = corpcclient.NewCoRpcClient() } handlers := make(map[string]func(*sessionService.SimpleSession, map[string]interface{}) map[string]interface{}) return &Server{ctx, coRpcS, coRpcC, handlers} }
/// 创建CoSessionRpcServer组建. func NewCoSessionRpcServer() *CoSessionRpcServer { ctx := context.GetContext() coSRS, ok := ctx.GetComponent("cosessionrpcserver").(*CoSessionRpcServer) if ok == true { return coSRS } srs := sessionRpcServer.NewSessionRpcServer() coSRS = &CoSessionRpcServer{srs} ctx.RegisteComponent("cosessionrpcserver", coSRS) return coSRS }
/// 解除用户id到session id的绑定,该操作会通过rpc调用影响前端服务器. /// /// @param frontendid 前端服务器id /// @param sid session id /// @param uid 用户id func (bss *BackendSessionService) UnbindUID(frontendid string, sid uint32, uid string) { seelog.Tracef("Unbind uid<%v> with session id<%v>", uid, sid) args := make([]interface{}, 2) args[0] = sid args[1] = uid method := "SessionRpcServer.UnbindUID" if err := bss.rpcCient.RpcCall(frontendid, method, &args, nil); err != nil { seelog.Errorf("<%v> UnbindUID uid<%v> with sid<%v> error<%v>", context.GetContext().GetServerID(), uid, sid, err.Error()) } }
func NewCoRpcServer() *CoRpcServer { ctx := context.GetContext() coRpcS, ok := ctx.GetComponent("corpcserver").(*CoRpcServer) if ok == true { return coRpcS } host, _ := ctx.CurrentServer["host"].(string) port, _ := ctx.CurrentServer["port"].(int) rpcS := rpcserver.NewRpcServer(host, port) coRpcS = &CoRpcServer{rpcS} ctx.RegisteComponent("corpcserver", coRpcS) seelog.Info("CoRpcServer create successfully") return coRpcS }
/// 将设置sid标识的session的属性同步到前端服务器. /// /// @param frontendid 前端服务器id /// @param sid session id /// @param key 属性名 /// @param value 属性值 func (bss *BackendSessionService) PushOpt(frontendid string, sid uint32, key string, value interface{}) { seelog.Tracef("Push opt to <%v> with sid<%v>,key<%v>,value<%v>", frontendid, sid, key, value) args := make(map[string]interface{}) args["sid"] = sid args["key"] = key args["value"] = value method := "SessionRpcServer.PushOpt" if err := bss.rpcCient.RpcCall(frontendid, method, &args, nil); err != nil { seelog.Errorf("<%v> PushOpt with sid<%v> to frontend<%v> error<%v>", context.GetContext().GetServerID(), sid, frontendid, err.Error()) } }
func main() { ctx := context.GetContext() allOpts := make(map[string]map[string]interface{}) cosessOpts := make(map[string]interface{}) //指定同一个uid可以绑定多个session cosessOpts["multiBind"] = "yes" allOpts["cosession"] = cosessOpts ctx.AllOpts = allOpts defer seelog.Flush() currentServer := make(map[string]interface{}) currentServer["id"] = "connector-1" currentServer["serverType"] = "connector" currentServer["host"] = "127.0.0.1" currentServer["port"] = 8888 ctx.CurrentServer = currentServer cosess := cosession.NewCoSession() cosessRS := cosessionrpcserver.NewCoSessionRpcServer() corpcS := corpcserver.NewCoRpcServer() // 启动cosession,cosessionrpcserver,corpcserver cosess.Start() cosessRS.Start() corpcS.Start() cosess.CreateSession(1, "connector-1", nil) cosess.BindUID("Zhang San", 1) cosess.CreateSession(2, "connector-1", nil) cosess.BindUID("Li Si", 2) cosess.CreateSession(3, "connector-1", nil) cosess.BindUID("Li Si", 3) cosess.CreateSession(4, "connector-1", nil) cosess.BindUID("Wang Wu", 4) ch := make(chan int) <-ch }
func (s *Server) GlobalHandler(msg map[string]interface{}, session *sessionService.SimpleSession, sendCB func(string, string, map[string]interface{}, []uint32)) { frontendID := s.ctx.GetServerID() route, _ := msg["route"].(string) record := parseRoute(route) if record == nil { seelog.Errorf("receive invalid route<%v>, route format must be<serverType.handler.method>", route) return } handlerMethodName := record.handler + "." + record.method if context.GetContext().GetServerType() == record.serverType { ///调用本地方法处理. seelog.Infof("<%v> receive local handler<%v> request", frontendID, handlerMethodName) if handlerMethod, ok := s.handlers[handlerMethodName]; ok == true { replyMsg := handlerMethod(session, msg) seelog.Debugf("<%v> local handler<%v> reply msg<%v>", frontendID, handlerMethodName, replyMsg) sids := make([]uint32, 1) sids[0] = session.Id reqID, _ := replyMsg["reqID"].(string) rroute, _ := replyMsg["route"].(string) msgBody, _ := replyMsg["msg"].(map[string]interface{}) sendCB(reqID, rroute, msgBody, sids) } else { seelog.Errorf("<%v> request local handler<%v> error", frontendID, handlerMethodName) } } else { ///rpc调用远端方法 servID := s.ctx.GetServerIDByType(record.serverType) seelog.Infof("<%v> invoke remote handler<%v> request of <%v>", frontendID, handlerMethodName, servID) reply := make(map[string]interface{}) if err := s.coRpcC.RpcCall(servID, handlerMethodName, msg, &reply); err != nil { seelog.Errorf("<%v> rpc call<%v> error<%v>", frontendID, handlerMethodName, err.Error()) } } }
func (bss *BackendSessionService) Start() { seelog.Infof("server<%v> start BackendSessionService", context.GetContext().GetServerID()) }
func (cs *CoSession) Start() { ctx := context.GetContext() seelog.Infof("frontendserver<%v> cosession start", ctx.GetServerID()) }
/// 创建新的TcpConnector func NewTcpConnector(host string, port string, opts map[string]string) *TcpConnector { regE := make(map[string]func(args ...interface{})) return &TcpConnector{host, port, opts, regE, context.GetContext()} }