func (app *App) GetServerByID(id string) (*cluster.Server, error) {
	return app.serviceDiscovery.GetServer(id)
}
GetServerByID returns the server with the specified id
package pitaya
import (
	"context"
	"os"
	"os/signal"
	"reflect"
	"strings"
	"syscall"
	"time"
	"github.com/golang/protobuf/proto"
	opentracing "github.com/opentracing/opentracing-go"
	"github.com/topfreegames/pitaya/v2/acceptor"
	"github.com/topfreegames/pitaya/v2/cluster"
	"github.com/topfreegames/pitaya/v2/component"
	"github.com/topfreegames/pitaya/v2/config"
	"github.com/topfreegames/pitaya/v2/conn/message"
	"github.com/topfreegames/pitaya/v2/constants"
	pcontext "github.com/topfreegames/pitaya/v2/context"
	"github.com/topfreegames/pitaya/v2/docgenerator"
	"github.com/topfreegames/pitaya/v2/errors"
	"github.com/topfreegames/pitaya/v2/groups"
	"github.com/topfreegames/pitaya/v2/interfaces"
	"github.com/topfreegames/pitaya/v2/logger"
	logging "github.com/topfreegames/pitaya/v2/logger/interfaces"
	"github.com/topfreegames/pitaya/v2/metrics"
	mods "github.com/topfreegames/pitaya/v2/modules"
	"github.com/topfreegames/pitaya/v2/remote"
	"github.com/topfreegames/pitaya/v2/router"
	"github.com/topfreegames/pitaya/v2/serialize"
	"github.com/topfreegames/pitaya/v2/service"
	"github.com/topfreegames/pitaya/v2/session"
	"github.com/topfreegames/pitaya/v2/timer"
	"github.com/topfreegames/pitaya/v2/tracing"
	"github.com/topfreegames/pitaya/v2/worker"
)
type ServerMode byte
const (
	_ ServerMode = iota
	Cluster
	Standalone
)
type Pitaya interface {
	GetDieChan() chan bool
	SetDebug(debug bool)
	SetHeartbeatTime(interval time.Duration)
	GetServerID() string
	GetMetricsReporters() []metrics.Reporter
	GetServer() *cluster.Server
	GetServerByID(id string) (*cluster.Server, error)
	GetServersByType(t string) (map[string]*cluster.Server, error)
	GetServers() []*cluster.Server
	GetSessionFromCtx(ctx context.Context) session.Session
	Start()
	SetDictionary(dict map[string]uint16) error
	AddRoute(serverType string, routingFunction router.RoutingFunc) error
	Shutdown()
	StartWorker()
	RegisterRPCJob(rpcJob worker.RPCJob) error
	Documentation(getPtrNames bool) (map[string]interface{}, error)
	IsRunning() bool
	RPC(ctx context.Context, routeStr string, reply proto.Message, arg proto.Message) error
	RPCTo(ctx context.Context, serverID, routeStr string, reply proto.Message, arg proto.Message) error
	ReliableRPC(
		routeStr string,
		metadata map[string]interface{},
		reply, arg proto.Message,
	) (jid string, err error)
	ReliableRPCWithOptions(
		routeStr string,
		metadata map[string]interface{},
		reply, arg proto.Message,
		opts *config.EnqueueOpts,
	) (jid string, err error)
	SendPushToUsers(route string, v interface{}, uids []string, frontendType string) ([]string, error)
	SendKickToUsers(uids []string, frontendType string) ([]string, error)
	GroupCreate(ctx context.Context, groupName string) error
	GroupCreateWithTTL(ctx context.Context, groupName string, ttlTime time.Duration) error
	GroupMembers(ctx context.Context, groupName string) ([]string, error)
	GroupBroadcast(ctx context.Context, frontendType, groupName, route string, v interface{}) error
	GroupContainsMember(ctx context.Context, groupName, uid string) (bool, error)
	GroupAddMember(ctx context.Context, groupName, uid string) error
	GroupRemoveMember(ctx context.Context, groupName, uid string) error
	GroupRemoveAll(ctx context.Context, groupName string) error
	GroupCountMembers(ctx context.Context, groupName string) (int, error)
	GroupRenewTTL(ctx context.Context, groupName string) error
	GroupDelete(ctx context.Context, groupName string) error
	Register(c component.Component, options ...component.Option)
	RegisterRemote(c component.Component, options ...component.Option)
	RegisterModule(module interfaces.Module, name string) error
	RegisterModuleAfter(module interfaces.Module, name string) error
	RegisterModuleBefore(module interfaces.Module, name string) error
	GetModule(name string) (interfaces.Module, error)
}
type App struct {
	acceptors        []acceptor.Acceptor
	config           config.PitayaConfig
	debug            bool
	dieChan          chan bool
	heartbeat        time.Duration
	onSessionBind    func(session.Session)
	router           *router.Router
	rpcClient        cluster.RPCClient
	rpcServer        cluster.RPCServer
	metricsReporters []metrics.Reporter
	running          bool
	serializer       serialize.Serializer
	server           *cluster.Server
	serverMode       ServerMode
	serviceDiscovery cluster.ServiceDiscovery
	startAt          time.Time
	worker           *worker.Worker
	remoteService    *service.RemoteService
	handlerService   *service.HandlerService
	handlerComp      []regComp
	remoteComp       []regComp
	modulesMap       map[string]interfaces.Module
	modulesArr       []moduleWrapper
	groups           groups.GroupService
	sessionPool      session.SessionPool
}
func NewApp(
	serverMode ServerMode,
	serializer serialize.Serializer,
	acceptors []acceptor.Acceptor,
	dieChan chan bool,
	router *router.Router,
	server *cluster.Server,
	rpcClient cluster.RPCClient,
	rpcServer cluster.RPCServer,
	worker *worker.Worker,
	serviceDiscovery cluster.ServiceDiscovery,
	remoteService *service.RemoteService,
	handlerService *service.HandlerService,
	groups groups.GroupService,
	sessionPool session.SessionPool,
	metricsReporters []metrics.Reporter,
	config config.PitayaConfig,
) *App {
	app := &App{
		server:           server,
		config:           config,
		rpcClient:        rpcClient,
		rpcServer:        rpcServer,
		worker:           worker,
		serviceDiscovery: serviceDiscovery,
		remoteService:    remoteService,
		handlerService:   handlerService,
		groups:           groups,
		debug:            false,
		startAt:          time.Now(),
		dieChan:          dieChan,
		acceptors:        acceptors,
		metricsReporters: metricsReporters,
		serverMode:       serverMode,
		running:          false,
		serializer:       serializer,
		router:           router,
		handlerComp:      make([]regComp, 0),
		remoteComp:       make([]regComp, 0),
		modulesMap:       make(map[string]interfaces.Module),
		modulesArr:       []moduleWrapper{},
		sessionPool:      sessionPool,
	}
	if app.heartbeat == time.Duration(0) {
		app.heartbeat = config.Heartbeat.Interval
	}
	app.initSysRemotes()
	return app
}
func (app *App) GetDieChan() chan bool {
	return app.dieChan
}
func (app *App) SetDebug(debug bool) {
	app.debug = debug
}
func (app *App) SetHeartbeatTime(interval time.Duration) {
	app.heartbeat = interval
}
func (app *App) GetServerID() string {
	return app.server.ID
}
func (app *App) GetMetricsReporters() []metrics.Reporter {
	return app.metricsReporters
}
func (app *App) GetServer() *cluster.Server {
	return app.server
}