cherry 笔记三(启动)

cherry启动很简单  app创建完  直接startup()就好了

func main() {app := cherry.Configure("./examples/config/profile-chat.json","chat-master",false,cherry.Cluster,)app.SetSerializer(cserializer.NewJSON())app.Startup()
}

Configure()--->NewApp()-->NewAppNode()  

app := &Application{INode:       node,serializer:  cserializer.NewProtobuf(),isFrontend:  isFrontend,nodeMode:    mode,startTime:   ctime.Now(),running:     0,dieChan:     make(chan bool),actorSystem: cactor.New(),}

默认的 serializer 是Protobuf()的

在Startup()之前除了可以SetSerializer() 还可以干其他很多事情 比如以下。。。

httpServer := cherryGin.NewHttp("web_1", app.Address())
httpServer.Use(cherryGin.Cors(), cherryGin.MaxConnect(2))
httpServer.Register(new(Test1Controller))
app.Register(httpServer)func (a *Application) Register(components ...cfacade.IComponent) {if a.Running() {return}for _, c := range components {if c == nil || c.Name() == "" {clog.Errorf("[component = %T] name is nil", c)return}result := a.Find(c.Name())if result != nil {clog.Errorf("[component name = %s] is duplicate.", c.Name())return}a.components = append(a.components, c)}
}

注册httpServer 这个component,也是暂存在AppBuilder的components中 

    // 创建pomelo网络数据包解析器,它同时也是一个actoragentActor := pomelo.NewActor("user")// 添加websocket连接器, 根据业务需要可添加多类型的connectoragentActor.AddConnector(cconnector.NewWS(":34590"))// 创建Agent时,关联onClose函数agentActor.SetOnNewAgent(func(newAgent *pomelo.Agent) {newAgent.AddOnClose(func(agent *pomelo.Agent) {session := agent.Session()if !session.IsBind() {return}// 发送玩家断开连接的消息给room actorreq := &protocol.Int64{Value: session.Uid,}agentActor.Call(".room", "exit", req)clog.Debugf("[sid = %s,uid = %d] session disconnected.",session.Sid,session.Uid,)})})// 设置数据路由函数agentActor.SetOnDataRoute(onDataRoute)// 设置网络包解析器app.SetNetParser(agentActor)

设置NetParser

app.AddActors(&ActorLog{})func (p *AppBuilder) AddActors(actors ...cfacade.IActorHandler) {p.actorSystem.Add(actors...)
}

添加一些actors,这些actor都放在actorSystem中维护

设置一些东西之后,最后一步就是Startup()了

func (p *AppBuilder) Startup() {app := p.Applicationif app.NodeMode() == Cluster {cluster := ccluster.New()app.SetCluster(cluster)app.Register(cluster)discovery := cdiscovery.New()app.SetDiscovery(discovery)app.Register(discovery)}// Register custom componentsapp.Register(p.components...)// startupapp.Startup()
}

如果是Cluster模式,那么会自动注册 cluster、discovery这2个component

然后把 之前Register 暂存在AppBuilder的components里边的component(像httpServer)也注册到Application的components

由此可见,暂存到AppBuilder.components里边的component 最终都会汇总到Application.components 里边去。。。

最后调用app.Startup()

func (a *Application) Startup() {defer func() {if r := recover(); r != nil {clog.Error(r)}}()if a.Running() {clog.Error("Application has running.")return}defer func() {clog.Flush()}()// register actor systema.Register(a.actorSystem)// add connector componentif a.netParser != nil {for _, connector := range a.netParser.Connectors() {a.Register(connector)}}clog.Info("-------------------------------------------------")clog.Infof("[nodeId      = %s] application is starting...", a.NodeId())clog.Infof("[nodeType    = %s]", a.NodeType())clog.Infof("[pid         = %d]", os.Getpid())clog.Infof("[startTime   = %s]", a.StartTime())clog.Infof("[profilePath = %s]", cprofile.Path())clog.Infof("[profileName = %s]", cprofile.Name())clog.Infof("[env         = %s]", cprofile.Env())clog.Infof("[debug       = %v]", cprofile.Debug())clog.Infof("[printLevel  = %s]", cprofile.PrintLevel())clog.Infof("[logLevel    = %s]", clog.DefaultLogger.LogLevel)clog.Infof("[stackLevel  = %s]", clog.DefaultLogger.StackLevel)clog.Infof("[writeFile   = %v]", clog.DefaultLogger.EnableWriteFile)clog.Infof("[serializer  = %s]", a.serializer.Name())clog.Info("-------------------------------------------------")// component listfor _, c := range a.components {c.Set(a)clog.Infof("[component = %s] is added.", c.Name())}clog.Info("-------------------------------------------------")// execute Init()for _, c := range a.components {clog.Infof("[component = %s] -> OnInit().", c.Name())c.Init()}clog.Info("-------------------------------------------------")// execute OnAfterInit()for _, c := range a.components {clog.Infof("[component = %s] -> OnAfterInit().", c.Name())c.OnAfterInit()}// load net packet parserif a.isFrontend {if a.netParser == nil {clog.Panic("net packet parser is nil.")}a.netParser.Load(a)}clog.Info("-------------------------------------------------")spendTime := a.startTime.DiffInMillisecond(ctime.Now())clog.Infof("[spend time = %dms] application is running.", spendTime)clog.Info("-------------------------------------------------")// set application is runningatomic.AddInt32(&a.running, 1)sg := make(chan os.Signal, 1)signal.Notify(sg, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM)select {case <-a.dieChan:clog.Info("invoke shutdown().")case s := <-sg:clog.Infof("receive shutdown signal = %v.", s)}// stop statusatomic.StoreInt32(&a.running, 0)clog.Info("------- application will shutdown -------")if a.onShutdownFn != nil {for _, f := range a.onShutdownFn {cutils.Try(func() {f()}, func(errString string) {clog.Warnf("[onShutdownFn] error = %s", errString)})}}//all components in reverse orderfor i := len(a.components) - 1; i >= 0; i-- {cutils.Try(func() {clog.Infof("[component = %s] -> OnBeforeStop().", a.components[i].Name())a.components[i].OnBeforeStop()}, func(errString string) {clog.Warnf("[component = %s] -> OnBeforeStop(). error = %s", a.components[i].Name(), errString)})}for i := len(a.components) - 1; i >= 0; i-- {cutils.Try(func() {clog.Infof("[component = %s] -> OnStop().", a.components[i].Name())a.components[i].OnStop()}, func(errString string) {clog.Warnf("[component = %s] -> OnStop(). error = %s", a.components[i].Name(), errString)})}clog.Info("------- application has been shutdown... -------")
}

维护着所有actor的 actorSystem 也当做一个component  Register到Application.components

netParser管理的所有Connector 也都被当做compenent Register到Application.components

func (a *Application) Register(components ...cfacade.IComponent) {if a.Running() {return}for _, c := range components {if c == nil || c.Name() == "" {clog.Errorf("[component = %T] name is nil", c)return}result := a.Find(c.Name())if result != nil {clog.Errorf("[component name = %s] is duplicate.", c.Name())return}a.components = append(a.components, c)}
}

所有Register的component 都是暂存在 Application.components

逐步遍历components 执行 c.Set(a)  c.Init()  c.OnAfterInit() 

来看看component 接口和 基类 都长什么样? 

type (IComponent interface {Name() stringApp() IApplicationIComponentLifecycle}IComponentLifecycle interface {Set(app IApplication)Init()OnAfterInit()OnBeforeStop()OnStop()}
)// Component base component
type Component struct {app IApplication
}func (*Component) Name() string {return ""
}func (p *Component) App() IApplication {return p.app
}func (p *Component) Set(app IApplication) {p.app = app
}func (*Component) Init() {
}func (*Component) OnAfterInit() {
}func (*Component) OnBeforeStop() {
}func (*Component) OnStop() {
}

紧接着 如果当前application isFrontend是true的话,就对netParser 执行 Load()操作

func (p *actor) Load(app cfacade.IApplication) {if len(p.connectors) < 1 {panic("connectors is nil. Please call the AddConnector(...) method add IConnector.")}cmd.init(app)//  Create agent actorif _, err := app.ActorSystem().CreateActor(p.agentActorID, p); err != nil {clog.Panicf("Create agent actor fail. err = %+v", err)}for _, connector := range p.connectors {connector.OnConnect(p.defaultOnConnectFunc)go connector.Start() // start connector!}
}

init()这个里边会去初始化 一些常用的数据 比如说心跳、DataDic、序列化的名称、握手数据、心跳数据、握手回调、握手确认回调、心跳回调、收到数据包的回调。。。。这部分逻辑 跟pitaya是一样的

紧接着就是启动连接器,以便客户端来连接,类似pitaya的Acceptor 和Twisted的ClientFactory

OnConnect 是设置 当有客户端来连接时的回调函数。。。框架统一由defaultOnConnectFunc

func (p *actor) defaultOnConnectFunc(conn net.Conn) {session := &cproto.Session{Sid:       nuid.Next(),AgentPath: p.Path().String(),Data:      map[string]string{},}agent := NewAgent(p.App(), conn, session)if p.onNewAgentFunc != nil {p.onNewAgentFunc(&agent)}BindSID(&agent)agent.Run()
}

创建session,然后创建agent,onNewAgentFunc 是应用层 对于有连接过来了 设置的回调,比如聊天示例中,要设置这个连接关闭时 触发的api。。。

agentActor.SetOnNewAgent(func(newAgent *pomelo.Agent) {newAgent.AddOnClose(func(agent *pomelo.Agent) {session := agent.Session()if !session.IsBind() {return}// 发送玩家断开连接的消息给room actorreq := &protocol.Int64{Value: session.Uid,}agentActor.Call(".room", "exit", req)clog.Debugf("[sid = %s,uid = %d] session disconnected.",session.Sid,session.Uid,)})})

BindSID 主要是建立关联。。。 

sidAgentMap = make(map[cfacade.SID]*Agent)
func BindSID(agent *Agent) {lock.Lock()defer lock.Unlock()sidAgentMap[agent.SID()] = agent
}

agent.Run()就是 启动2个协程 分别读写 

func (a *Agent) Run() {go a.writeChan()go a.readChan()
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/32468.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c++使用std::function/std::bind

1&#xff09;C入门级小知识&#xff0c;分享给将要学习或者正在学习C开发的同学。 2&#xff09;内容属于原创&#xff0c;若转载&#xff0c;请说明出处。 3&#xff09;提供相关问题有偿答疑和支持。 std::function对象是对C中现有的可调用实体的一种类型安全的包裹&…

多路h265监控录放开发-(9)通过拖拽到窗口完成渲染

xcamera_widget.h class XCameraWidget :public QWidget {Q_OBJECTpublic:XCameraWidget(QWidget* p nullptr);//渲染视频void Draw();//123//清理资源,再一个窗口被覆盖后 清理之前窗口生成的资源1~XCameraWidget();//123 private:XDecodeTask* decode_ nullptr;//123XDemu…

Linux平台I2C多字节数据、按页连续读写E2PROM Demo(AT24C16)

1&#xff09;Linux 平台I2C多字节数据按页连续读写E2PROM之AT24C16小知识&#xff0c;分享给将要学习或者正在学习Linux平台I2C多字节按页连续读写E2PROM开发的同学。 2&#xff09;内容属于原创&#xff0c;若转载&#xff0c;请说明出处。 3&#xff09;提供相关问题有偿答…

class中的溢出滑动效果

效果图&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title></head><style>*{margin: 0;padding: 0;}.frame-pages{width: 30%;height: 60px;display: flex;justify…

网络安全-如何设计一个安全的API(安全角度)

目录 API安全概述设计一个安全的API一个基本的API主要代码调用API的一些问题 BasicAuth认证流程主要代码问题 API Key流程主要代码问题 Bearer auth/Token auth流程 Digest Auth流程主要代码问题 JWT Token流程代码问题 Hmac流程主要代码问题 OAuth比较自定义请求签名身份认证&…

测试工程师常见的面试问题及回答建议

说起软件测试近几年的发展&#xff0c;其实已悄无声息地发生了巨大的变化。前几年随着互联网行业的迅猛发展&#xff0c;软件测试人才稀缺&#xff0c;低门槛高薪资促使大批毕业生和转行人员一窝蜂地涌入。而现在&#xff0c;软件测试发展太快&#xff0c;纵观各大招聘网站&…

本科生大厂算法岗实习经验复盘:从投递到面试的底层思维!

目录 投递渠道boss直聘官网邮箱内推 面试准备leetcode八股深挖项目自我介绍mock面试技巧答不出来怎么办coding反问 复盘技术交流群用通俗易懂方式讲解系列 节前&#xff0c;我们星球组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面…

猫头虎分享已解决Bug || Null Pointer Exception: `java.lang.NullPointerException`

猫头虎分享已解决Bug || Null Pointer Exception: java.lang.NullPointerException &#x1f63a;&#x1f42f; 关于猫头虎 大家好&#xff0c;我是猫头虎&#xff0c;别名猫头虎博主&#xff0c;擅长的技术领域包括云原生、前端、后端、运维和AI。我的博客主要分享技术教程…

嵌入式学习——数据结构(双向无头有环链表、内核链表、栈)——day48

1. 约瑟夫环问题——双向无头回环链表 1.1 问题描述 给定 ( n ) 个人&#xff08;编号为 ( 1, 2, \ldots, n )&#xff09;&#xff0c;他们围成一个圈。从第一个人开始报数&#xff0c;每报到第 ( k ) 个人时&#xff0c;杀掉这个人&#xff0c;然后从下一个人重新开始报数。…

【Git】 -- Part1 -- 基础操作

1. Git简介 Git 是一个开源的分布式版本控制系统&#xff0c;由 Linus Torvalds 于 2005 年开发&#xff0c;主要用于源代码管理。Git 允许多名开发者共同合作处理同一个项目&#xff0c;跟踪每个文件的修改&#xff0c;并且在必要时回滚到之前的版本。 Linus Torvalds是Linux…

面试突击:深入理解 Java 中的异常

本文已收录于&#xff1a;https://github.com/danmuking/all-in-one&#xff08;持续更新&#xff09; 前言 哈喽&#xff0c;大家好&#xff0c;我是 DanMu。今天想和大家聊聊 Java 中的异常。异常处理是一种重要的概念&#xff0c;因为程序总是会出现各种意料之外的问题&…

通过xml配置实现数据动态导入导出Excel

spring-dj-excel-common.jar 一个可以通过动态配置 xml 建立 Excel 与数据关系现实数据导入导出的 spring 组件包&#xff0c;在 xml 配置文件里&#xff0c;你可以很方便的定义 Excel - sheet 表列头文本与数据表、数据实体属性的对应关系&#xff0c;对于创建 Excel 文件&…

尽管担任社长 宫崎英高95%时间还是在做游戏

宫崎英高表示&#xff0c;虽然他是 FromSoftware 工作室的社长&#xff0c;但他日常工作的绝大部分时间都是在指导游戏开发。因魂系列大获成功而成为 FromSoftware 社长的宫崎英高在接受《卫报》采访时表示&#xff0c;企业高管生活并不是他的兴趣所在。 “我喜欢帮助年轻的监督…

cesium for unity 打包webgl失败,提示不支持

platform webgl is not supported with HDRP use the Vulkan graphics AR instead.

Linux-PXE批量安装

一、部署 PXE 远程安装服务 在大规模的 Linux 应用环境中&#xff0c;如 Web 群集、分布式计算等&#xff0c;服务器往往并不配备光驱设备&#xff0c;在这种情况下&#xff0c;如何为数十乃至上百台服务器裸机快速安装系统呢&#xff1f;传统的 USB光驱、移动硬盘等安装方法显…

双向滑动选择器

插件地址:https://ext.dcloud.net.cn/plugin?id3940 注意: 当改变值是,让滑块自动滑动需要调用: this.$refs.powerSlider.updateValue(that.tempPowerValue[0], that.tempPowerValue[1], false); <view style"width: 90%;margin: 15px"><cj-slider ref…

CAS Apereo 5.3.16 实现单点登录

1.CAS部署 服务端下载地址&#xff1a;cas5.3 1.下载好打开后&#xff0c;复制target/cas/WEB-INF/classes/META-INF/spring.factories target/cas/WEB-INF/classes/services下的Apereo-10000002.json和HTTPSandIMAPS-10000001.json target/cas/WEB-INF/classes下的applicati…

挑战Midjourney,融合近百个SD大模型的通用模型AlbedoBase XL

在SDXL的通用模型中&#xff0c;DreamShaperXL和juggernautXL这2款大模型一直都深受广大AI绘画者的喜爱&#xff0c;不可否认&#xff0c;这2款通用模型在很多方面表现都相当出色。 今天再给大家介绍一款基于SDXL的通用大模型&#xff1a;AlbedoBase XL&#xff0c;作者的目标…

iTextSharp 绘制pdf

一、新建项目&#xff1a;pdfdemo <ItemGroup><PackageReference Include"iTextSharp.LGPLv2.Core" Version"3.4.20" /> </ItemGroup>二、HomeController.cs using iTextSharp.text; using iTextSharp.text.pdf; using Microsoft.AspN…

UWA发布 | Unity手游性能年度蓝皮书

UWA本次发布的《2023-2024年度Unity手游性能蓝皮书》将汇总游戏行业使用Unity引擎进行手游开发过程中及游戏上线后的性能表现&#xff0c;从测试机型分布、引擎各模块开销、内存占用等方面剖析定位Unity手游性能瓶颈和趋势&#xff0c;反映了Unity手游行业的现状&#xff0c;帮…