Leaf游戏服务器框架简介

leaf框架源码分析 leaf框架源码分析 近来阅读leaf框架的代码,有些感悟,特来记录一番。既是一个总结,又是对后来阅读者的一个启发。 个人看代码的一个习惯,喜欢有上下文,因此会各个代码文件之间相互乱窜。但多看几次也就能对框架要做什么和我们要做什么有一个清晰的了解了。 阅读本文之前,还是建议先看看作者写的Wiki,其中有关于框架整体的一个介绍和使用。至于项目地址,去github上搜索便是。 如何使用Leaf 首先需要搭建好一个使用的环境,leafserver就是一个很好的例子。本文将从leafserver开始探讨整个leaf 阅读详情

以下内容转载自 https://github.com/name5566/leaf/blob/master/TUTORIAL_ZH.md

Leaf 游戏服务器框架简介

Leaf 是一个由 Go 语言(golang)编写的开发效率和执行效率并重的开源游戏服务器框架。Leaf 适用于各类游戏服务器的开发,包括 H5(HTML5)游戏服务器。

Leaf 的关注点:

  • 良好的使用体验。Leaf 总是尽可能的提供简洁和易用的接口,尽可能的提升开发的效率
  • 稳定性。Leaf 总是尽可能的恢复运行过程中的错误,避免崩溃
  • 多核支持。Leaf 通过模块机制和 leaf/go 尽可能的利用多核资源,同时又尽量避免各种副作用
  • 模块机制。

Leaf 的模块机制

一个 Leaf 开发的游戏服务器由多个模块组成(例如 LeafServer),模块有以下特点:

  • 每个模块运行在一个单独的 goroutine 中
  • 模块间通过一套轻量的 RPC 机制通讯(leaf/chanrpc)

Leaf 不建议在游戏服务器中设计过多的模块。

游戏服务器在启动时进行模块的注册,例如:

leaf.Run(
	game.Module,
	gate.Module,
	login.Module,
)

这里按顺序注册了 game、gate、login 三个模块。每个模块都需要实现接口:

type Module interface {
	OnInit()
	OnDestroy()
	Run(closeSig chan bool)
}

Leaf 首先会在同一个 goroutine 中按模块注册顺序执行模块的 OnInit 方法,等到所有模块 OnInit 方法执行完成后则为每一个模块启动一个 goroutine 并执行模块的 Run 方法。最后,游戏服务器关闭时(Ctrl + C 关闭游戏服务器)将按模块注册相反顺序在同一个 goroutine 中执行模块的 OnDestroy 方法。

Leaf 源码概览

  • leaf/chanrpc 提供了一套基于 channel 的 RPC 机制,用于游戏服务器模块间通讯
  • leaf/db 数据库相关,目前支持 MongoDB
  • leaf/gate 网关模块,负责游戏客户端的接入
  • leaf/go 用于创建能够被 Leaf 管理的 goroutine
  • leaf/log 日志相关
  • leaf/network 网络相关,使用 TCP 和 WebSocket 协议,可自定义消息格式,默认 Leaf 提供了基于 protobuf 和 JSON 的消息格式
  • leaf/recordfile 用于管理游戏数据
  • leaf/timer 定时器相关
  • leaf/util 辅助库

使用 Leaf 开发游戏服务器

LeafServer 是一个基于 Leaf 开发的游戏服务器,我们以 LeafServer 作为起点。

获取 LeafServer:

git clone https://github.com/name5566/leafserver

设置 leafserver 目录到 GOPATH 环境变量后获取 Leaf:

go get github.com/name5566/leaf

编译 LeafServer:

go install server

如果一切顺利,运行 server 你可以获得以下输出:

2015/08/26 22:11:27 [release] Leaf 1.1.2 starting up

敲击 Ctrl + C 关闭游戏服务器,服务器正常关闭输出:

2015/08/26 22:12:30 [release] Leaf closing down (signal: interrupt)

Hello Leaf

现在,在 LeafServer 的基础上,我们来看看游戏服务器如何接收和处理网络消息。

首先定义一个 JSON 格式的消息(protobuf 类似)。打开 LeafServer msg/msg.go 文件可以看到如下代码:

package msg

import (
	"github.com/name5566/leaf/network"
)

var Processor network.Processor

func init() {

}

Processor 为消息的处理器(可由用户自定义),这里我们使用 Leaf 默认提供的 JSON 消息处理器并尝试添加一个名字为 Hello 的消息:

package msg

import (
	"github.com/name5566/leaf/network/json"
)

// 使用默认的 JSON 消息处理器(默认还提供了 protobuf 消息处理器)
var Processor = json.NewProcessor()

func init() {
	// 这里我们注册了一个 JSON 消息 Hello
	Processor.Register(&Hello{})
}

// 一个结构体定义了一个 JSON 消息的格式
// 消息名为 Hello
type Hello struct {
	Name string
}

客户端发送到游戏服务器的消息需要通过 gate 模块路由,简而言之,gate 模块决定了某个消息具体交给内部的哪个模块来处理。这里,我们将 Hello 消息路由到 game 模块中。打开 LeafServer gate/router.go,敲入如下代码:

package gate

import (
	"server/game"
	"server/msg"
)

func init() {
	// 这里指定消息 Hello 路由到 game 模块
	// 模块间使用 ChanRPC 通讯,消息路由也不例外
	msg.Processor.SetRouter(&msg.Hello{}, game.ChanRPC)
}

一切就绪,我们现在可以在 game 模块中处理 Hello 消息了。打开 LeafServer game/internal/handler.go,敲入如下代码:

package internal

import (
	"github.com/name5566/leaf/log"
	"github.com/name5566/leaf/gate"
	"reflect"
	"server/msg"
)

func init() {
	// 向当前模块(game 模块)注册 Hello 消息的消息处理函数 handleHello
	handler(&msg.Hello{}, handleHello)
}

func handler(m interface{}, h interface{}) {
	skeleton.RegisterChanRPC(reflect.TypeOf(m), h)
}

func handleHello(args []interface{}) {
	// 收到的 Hello 消息
	m := args[0].(*msg.Hello)
	// 消息的发送者
	a := args[1].(gate.Agent)

	// 输出收到的消息的内容
	log.Debug("hello %v", m.Name)

	// 给发送者回应一个 Hello 消息
	a.WriteMsg(&msg.Hello{
		Name: "client",
	})
}

到这里,一个简单的范例就完成了。为了更加清楚的了解消息的格式,我们从 0 编写一个最简单的测试客户端。

Leaf 中,当选择使用 TCP 协议时,在网络中传输的消息都会使用以下格式:

--------------
| len | data |
--------------

其中:

  1. len 表示了 data 部分的长度(字节数)。len 本身也有长度,默认为 2 字节(可配置),len 本身的长度决定了单个消息的最大大小
  2. data 部分使用 JSON 或者 protobuf 编码(也可自定义其他编码方式)

测试客户端同样使用 Go 语言编写:

package main

import (
	"encoding/binary"
	"net"
)

func main() {
	conn, err := net.Dial("tcp", "127.0.0.1:3563")
	if err != nil {
		panic(err)
	}

	// Hello 消息(JSON 格式)
	// 对应游戏服务器 Hello 消息结构体
	data := []byte(`{
		"Hello": {
			"Name": "leaf"
		}
	}`)

	// len + data
	m := make([]byte, 2+len(data))

	// 默认使用大端序
	binary.BigEndian.PutUint16(m, uint16(len(data)))

	copy(m[2:], data)

	// 发送消息
	conn.Write(m)
}

执行此测试客户端,游戏服务器输出:

2015/09/25 07:41:03 [debug  ] hello leaf
2015/09/25 07:41:03 [debug  ] read message: read tcp 127.0.0.1:3563->127.0.0.1:54599: wsarecv: An existing connection was forcibly closed by the remote host.

测试客户端发送完消息以后就退出了,此时和游戏服务器的连接断开,相应的,游戏服务器输出连接断开的提示日志(第二条日志,日志的具体内容和 Go 语言版本有关)。

除了使用 TCP 协议外,还可以选择使用 WebSocket 协议(例如开发 H5 游戏)。Leaf 可以单独使用 TCP 协议或 WebSocket 协议,也可以同时使用两者,换而言之,服务器可以同时接受 TCP 连接和 WebSocket 连接,对开发者而言消息来自 TCP 还是 WebSocket 是完全透明的。现在,我们来编写一个对应上例的使用 WebSocket 协议的客户端:

<script type="text/javascript">
var ws = new WebSocket('ws://127.0.0.1:3653')

ws.onopen = function() {
    // 发送 Hello 消息
    ws.send(JSON.stringify({Hello: {
        Name: 'leaf'
    }}))
}
</script>

保存上述代码到某 HTML 文件中并使用(任意支持 WebSocket 协议的)浏览器打开。在打开此 HTML 文件前,首先需要配置一下 LeafServer 的 bin/conf/server.json 文件,增加 WebSocket 监听地址(WSAddr):

{
    "LogLevel": "debug",
    "LogPath": "",
    "TCPAddr": "127.0.0.1:3563",
    "WSAddr": "127.0.0.1:3653",
    "MaxConnNum": 20000
}

重启游戏服务器后,方可接受 WebSocket 消息:

2015/09/25 07:50:03 [debug  ] hello leaf

在 Leaf 中使用 WebSocket 需要注意的一点是:Leaf 总是发送二进制消息而非文本消息。

Leaf 模块详解

LeafServer 中包含了 3 个模块,它们分别是:

  • gate 模块,负责游戏客户端的接入
  • login 模块,负责登录流程
  • game 模块,负责游戏主逻辑

一般来说(而非强制规定),从代码结构上,一个 Leaf 模块:

  1. 放置于一个目录中(例如 game 模块放置于 game 目录中)
  2. 模块的具体实现放置于 internal 包中(例如 game 模块的具体实现放置于 game/internal 包中)

每个模块下一般有一个 external.go 的文件,顾名思义表示模块对外暴露的接口,这里以 game 模块的 external.go 文件为例:

package game

import (
	"server/game/internal"
)

var (
	// 实例化 game 模块
	Module  = new(internal.Module)
	// 暴露 ChanRPC
	ChanRPC = internal.ChanRPC
)

首先,模块会被实例化,这样才能注册到 Leaf 框架中(详见 LeafServer main.go),另外,模块暴露的 ChanRPC 被用于模块间通讯。

进入 game 模块的内部(LeafServer game/internal/module.go):

package internal

import (
	"github.com/name5566/leaf/module"
	"server/base"
)

var (
	skeleton = base.NewSkeleton()
	ChanRPC  = skeleton.ChanRPCServer
)

type Module struct {
	*module.Skeleton
}

func (m *Module) OnInit() {
	m.Skeleton = skeleton
}

func (m *Module) OnDestroy() {

}

模块中最关键的就是 skeleton(骨架),skeleton 实现了 Module 接口的 Run 方法并提供了:

  • ChanRPC
  • goroutine
  • 定时器

Leaf ChanRPC

由于 Leaf 中,每个模块跑在独立的 goroutine 上,为了模块间方便的相互调用就有了基于 channel 的 RPC 机制。一个 ChanRPC 需要在游戏服务器初始化的时候进行注册(注册过程不是 goroutine 安全的),例如 LeafServer 中 game 模块注册了 NewAgent 和 CloseAgent 两个 ChanRPC:

package internal

import (
	"github.com/name5566/leaf/gate"
)

func init() {
	skeleton.RegisterChanRPC("NewAgent", rpcNewAgent)
	skeleton.RegisterChanRPC("CloseAgent", rpcCloseAgent)
}

func rpcNewAgent(args []interface{}) {

}

func rpcCloseAgent(args []interface{}) {

}

使用 skeleton 来注册 ChanRPC。RegisterChanRPC 的第一个参数是 ChanRPC 的名字,第二个参数是 ChanRPC 的实现。这里的 NewAgent 和 CloseAgent 会被 LeafServer 的 gate 模块在连接建立和连接中断时调用。ChanRPC 的调用方有 3 种调用模式:

  1. 同步模式,调用并等待 ChanRPC 返回
  2. 异步模式,调用并提供回调函数,回调函数会在 ChanRPC 返回后被调用
  3. Go 模式,调用并立即返回,忽略任何返回值和错误

gate 模块这样调用 game 模块的 NewAgent ChanRPC(这仅仅是一个示例,实际的代码细节复杂的多):

game.ChanRPC.Go("NewAgent", a)

这里调用 NewAgent 并传递参数 a,我们在 rpcNewAgent 的参数 args[0] 中可以取到 a(args[1] 表示第二个参数,以此类推)。

更加详细的用法可以参考 leaf/chanrpc。需要注意的是,无论封装多么精巧,跨 goroutine 的调用总不能像直接的函数调用那样简单直接,因此除非必要我们不要构建太多的模块,模块间不要太频繁的交互。模块在 Leaf 中被设计出来最主要是用于划分功能而非利用多核,Leaf 认为在模块内按需使用 goroutine 才是多核利用率问题的解决之道。

Leaf Go

善用 goroutine 能够充分利用多核资源,Leaf 提供的 Go 机制解决了原生 goroutine 存在的一些问题:

  • 能够恢复 goroutine 运行过程中的错误
  • 游戏服务器会等待所有 goroutine 执行结束后才关闭
  • 非常方便的获取 goroutine 执行的结果数据
  • 在一些特殊场合保证 goroutine 按创建顺序执行

我们来看一个例子(可以在 LeafServer 的模块的 OnInit 方法中测试):

log.Debug("1")

// 定义变量 res 接收结果
var res string

skeleton.Go(func() {
	// 这里使用 Sleep 来模拟一个很慢的操作
	time.Sleep(1 * time.Second)

	// 假定得到结果
	res = "3"
}, func() {
	log.Debug(res)
})

log.Debug("2")

上面代码执行结果如下:

2015/08/27 20:37:17 [debug  ] 1
2015/08/27 20:37:17 [debug  ] 2
2015/08/27 20:37:18 [debug  ] 3

这里的 Go 方法接收 2 个函数作为参数,第一个函数会被放置在一个新创建的 goroutine 中执行,在其执行完成之后,第二个函数会在当前 goroutine 中被执行。由此,我们可以看到变量 res 同一时刻总是只被一个 goroutine 访问,这就避免了同步机制的使用。Go 的设计使得 CPU 得到充分利用,避免操作阻塞当前 goroutine,同时又无需为共享资源同步而忧心。

更加详细的用法可以参考 leaf/go。

Leaf timer

Go 语言标准库提供了定时器的支持:

func AfterFunc(d Duration, f func()) *Timer

AfterFunc 会等待 d 时长后调用 f 函数,这里的 f 函数将在另外一个 goroutine 中执行。Leaf 提供了一个相同的 AfterFunc 函数,相比之下,f 函数在 AfterFunc 的调用 goroutine 中执行,这样就避免了同步机制的使用:

skeleton.AfterFunc(5 * time.Second, func() {
	// ...
})

另外,Leaf timer 还支持 cron 表达式,用于实现诸如“每天 9 点执行”、“每周末 6 点执行”的逻辑。

更加详细的用法可以参考 leaf/timer。

Leaf log

Leaf 的 log 系统支持多种日志级别:

  1. Debug 日志,非关键日志
  2. Release 日志,关键日志
  3. Error 日志,错误日志
  4. Fatal 日志,致命错误日志

Debug < Release < Error < Fatal(日志级别高低)

在 LeafServer 中,bin/conf/server.json 可以配置日志级别,低于配置的日志级别的日志将不会输出。Fatal 日志比较特殊,每次输出 Fatal 日志之后游戏服务器进程就会结束,通常来说,只在游戏服务器初始化失败时使用 Fatal 日志。

我们还可以通过配置 LeafServer conf/conf.go 的 LogFlag 来在日志中输出文件名和行号:

LogFlag = log.Lshortfile

可用的 LogFlag 见:https://golang.org/pkg/log/#pkg-constants

更加详细的用法可以参考 leaf/log。

Leaf recordfile

Leaf 的 recordfile 是基于 CSV 格式(范例见这里)。recordfile 用于管理游戏配置数据。在 LeafServer 中使用 recordfile 非常简单:

  1. 将 CSV 文件放置于 bin/gamedata 目录中
  2. 在 gamedata 模块中调用函数 readRf 读取 CSV 文件

范例:

// 确保 bin/gamedata 目录中存在 Test.txt 文件
// 文件名必须和此结构体名称相同(大小写敏感)
// 结构体的一个实例映射 recordfile 中的一行
type Test struct {
	// 将第一列按 int 类型解析
	// "index" 表明在此列上建立唯一索引
	Id  int "index"
	// 将第二列解析为长度为 4 的整型数组
	Arr [4]int
	// 将第三列解析为字符串
	Str string
}

// 读取 recordfile Test.txt 到内存中
// RfTest 即为 Test.txt 的内存镜像
var RfTest = readRf(Test{})

func init() {
	// 按索引查找
	// 获取 Test.txt 中 Id 为 1 的那一行
	r := RfTest.Index(1)

	if r != nil {
		row := r.(*Test)

		// 输出此行的所有列的数据
		log.Debug("%v %v %v", row.Id, row.Arr, row.Str)
	}
}

更加详细的用法可以参考 leaf/recordfile。

了解更多

阅读 Wiki 获取更多的帮助:https://github.com/name5566/leaf/wiki

Leaf-Server官方教程: Leaf 服务器的设计 (一) Leaf 服务器的设计 Leaf专注于游戏服务器,因此与一些Web服务器开发的设计和考虑有所不同。在一些游戏服务器中,采用的是分布式架构,即服务器整体被划分为不同的模块,各个模块承担不同的功能,而模块之间通过TCP进行交互。这样的架构能够保证服务器能够在多台机器上部署,单点故障不至于让服务整体崩溃。但是这种服务器有其自身的开发难度,而且有时候做好模块划分并不容易。Leaf是一体式的框架,连最外围的接入服务器也被整合在一起。虽然Leaf中间也划分了不同模块,但是他们是通过InnerRpc进行通讯的。介于现在 阅读详情

相关推荐

Golang 游戏开发——leaf系列详解与示例

在上述示例中,我们首先引入了leaf框架的必要组件。总结起来,leaf系列是一个强大而高效的Golang游戏开发框架,它提供了丰富的功能组件和简洁的接口,极大地简化了游戏服务器的开发过程。通过本文的示例代码,相信读者对leaf框架已经有了初步的了解,并能够开始使用它进行游戏开发。leaf是一款基于Golang的游戏服务器框架,它提供了高效的网络模型和丰富的功能组件,可以帮助开发者快速构建可靠、高性能的游戏服务器。通过以上示例,我们可以看到leaf框架提供了简洁易用的接口,使得游戏服务器开发变得非常便捷。

syntax_bug609的博客 1418

[Go实战]游戏开源服务器Leaf 初次试用[开箱可用]

看了很多文章,还是准备自己先试试 参考项目Leaf https://github.com/name5566/leaf 中文文档也有 https://github.com/name5566/leaf/blob/master/TUTORIAL_ZH.md 使用 Leaf 开发游戏服务器 LeafServer是一个基于 Leaf 开发的游戏服务器,我们以 LeafServer 作为起点。 获取 LeafServer: git clone https://github.com/...

学生董格 1470

Leaf服务器框架从入门到放弃(一)认识Leaf和安装Leaf环境

首先我简单介绍下Leaf服务器,下面这段描述是我摘自github官方README说明: Leaf 游戏服务器框架简介 Leaf 是一个由 Go 语言(golang)编写的开发效率和执行效率并重的开源游戏服务器框架。Leaf 适用于各类游戏服务器的开发,包括 H5(HTML5)游戏服务器。 Leaf 的关注点: 良好的使用体验。Leaf 总是尽可能的提供简洁和易用的接口,尽可能的提升开发的效...

yolo模型训练找我,AI游戏合作找我 5371

探索游戏服务器新境界:基于Leaf框架的Leaf Server

探索游戏服务器新境界:基于Leaf框架的Leaf Server 在这个充满无限可能的游戏开发领域,一款高效、灵活的游戏服务器引擎显得尤为重要。今天,我们为您带来了一颗璀璨的新星——Leaf Server,它依托于强大的Leaf框架,正等待着每一位游戏开发者去发掘它的光芒。 项目介绍 Leaf Server,正如其名,是一片承载游戏梦想的绿叶,轻盈而坚韧。作为一款专为游戏设计的服务器端解决方案,它巧...

gitblog_00948的博客 895

Go语言游戏服务器框架【Leaf Server】

Go语言游戏服务器框架【Leaf Server】 亲测可用,可以支持MySql数据库读取

zinx —— golang —— MMO游戏服务器开发对应客户端

zinx —— golang —— MMO游戏服务器开发对应客户端

Leaf 游戏服务器框架简介

Leaf 游戏服务器框架简介 Leaf 的模块机制 Leaf 源码概览 使用 Leaf 开发游戏服务器 Hello Leaf Leaf 模块详解 Leaf ChanRPC Leaf Go Leaf timer Leaf log Leaf recordfile 了解更多 Leaf 游戏服务器框架简介 Leaf 是一个由 Go 语...

嘿嘿 2340

Go-golang开发的h5小游戏服务端domo

golang开发的h5小游戏服务端domo

leaf游戏服务器开发系列,Leaf 游戏服务器框架简介

Leaf 是一个由 Go 语言(golang)编写的开发效率和执行效率并重的开源游戏服务器框架。Leaf 适用于各类游戏服务器的开发,包括 H5(HTML5)游戏服务器。Leaf 的关注点:·良好的使用体验。Leaf 总是尽可能的提供简洁和易用的接口,尽可能的提升开发的效率·稳定性。Leaf 总是尽可能的恢复运行过程中的错误,避免崩溃·多核支持。Leaf 通过模块机制和 leaf/go 尽可能的利...

weixin_42347750的博客 1287

手把手教你用BQ Studio给BQ40Z50电量计“做体检”:从Golden Learning到精度验证的全流程实操

本文详细介绍了如何使用BQ Studio对BQ40Z50电量计进行全流程调试,从Golden Learning到精度验证。通过硬件连接、参数配置和优化技巧,帮助工程师提升电池管理系统的精度和性能,适用于BMS开发和电量计校准的实际应用场景。

weixin_30824599的博客 450

DDR3性能优化实战:如何用Xilinx MIG控制器实现800MHz稳定读写(7系列FPGA版)

本文深入探讨了在Xilinx 7系列FPGA上使用MIG控制器实现DDR3存储器800MHz稳定高速读写的实战优化技巧。文章聚焦于高级时序调优、Bank Machine调度策略、用户接口设计优化以及利用ILA进行信号完整性调试,旨在帮助工程师突破性能瓶颈,实现接近理论峰值的稳定带宽,并为进一步冲刺更高频率提供进阶调参指南。

seed的博客 777

golang Leaf 游戏服务器框架简介

Leaf 是一个由 Go 语言(golang)编写的开发效率和执行效率并重的开源游戏服务器框架。Leaf 适用于各类游戏服务器的开发,包括 H5(HTML5)游戏服务器。Leaf 的关注点:良好的使用体验。Leaf 总是尽可能的提供简洁和易用的接口,尽可能的提升开发的效率稳定性。Leaf 总是尽可能的恢...

神棍之路 7256

【QEMU系统分析之TPM篇(一)】

本文以 QEMU 8.2.2 为例,分析其 TPM-emulator 模块的实现,并为 QEMU 添加 Windows 平台的TPM 模拟器的支持。

David唐辉的博客 1191

Leaf框架学习

简洁的模块化设计,Leaf 提供简洁和易用的接口。提供稳定的运行环境,在 Go 包内写了 recover 机制,尽可能避免程序崩溃。实现多核运行,使用 Go 语言的 channel 和 goroutine 实现,每个功能模块都单独起一个 goroutine ,模块间基于 channel 的 RPC 机制进行通信。

2401_85789254的博客 1747

win2012 r2 + IIS8.5 伪静态设置脚本映射

win2012 r2 + IIS8.5 伪静态设置脚本映射,网站用的.net fromwork 2.0 ,应用程序池设置了32位支持

xueking87的专栏 3240

用HFSS复现经典论文:从零搭建带孔缝屏蔽箱体模型(附完整建模步骤与避坑指南)

本文详细介绍了如何使用HFSS电磁仿真软件复现经典论文中的带孔缝屏蔽箱体模型,包括从零搭建模型、设置激励与边界条件、求解优化及结果验证的全过程。特别提供了建模中的布尔运算陷阱、激励设置技巧等实操难点的避坑指南,帮助工程师和学生深入理解电磁屏蔽效能研究。

weixin_30530339的博客 158

游戏服务器框架:Leaf/go

Leaf 是一个使用 Go 语言开发的开源游戏服务器框架,注重运行效率并追求极致的开发效率。Leaf 适用于几乎所有的游戏类型。其主要的特性: 良好的使用体验。Leaf 总是尽可能的提供简洁和易用的接口,尽可能的提升开发的效率 稳定性。Leaf 总是尽可能的恢复运行过程中的错误,避免崩溃 多核支持。Leaf 通过模块机制和leaf/go尽可能的利用多核资...

angzhan5306的博客 527

电流模架构Bandgap设计与仿真

带隙基准作为集成电路中一个重要模块,被广泛应用在低压差线性稳压(LDO)、充电电池保护芯片和通信电路、射频收发器、flash存储器等多种模拟及数模混合集成电路中,并且是片上集成系统(SOC)芯片中不可或缺的部分,为整个芯片提供精确的电压参考点............

qq_50968231的博客 5万+

Leaf游戏服务器框架入门指南

Leaf是一款基于Go语言开发的开源游戏服务器框架,其设计目标是提升游戏服务器的开发效率和运行时性能。Leaf框架遵循三个核心设计理念: 1. **简洁API**:提供简单易用的接口设计 2. **自我修复**:能够从运行时错误中恢复而非直接崩溃 3. **多核支持**:充分利用多核CPU资源,同时避免潜在的副作用问题 ## 核心架构 ### 模块化设计 Leaf采用模块化架构,每个模块运...

gitblog_00153的博客 660

SPSS实战:5步搞定多指标联合诊断的ROC曲线分析(附Logistic回归教程)

本文详细介绍了如何使用SPSS软件进行多指标联合诊断的ROC曲线分析。通过5个实战步骤,从数据准备、二元Logistic回归建模生成综合预测概率,到绘制并比较单指标与联合模型的ROC曲线,帮助临床研究者有效整合多个诊断指标,提升模型判别能力(AUC),实现诊断效能的优化。

mqtt6iot的博客 1422

基于FPGA的64点fft变换verilog开发

这精度的损失在10bits看来对最后的误差的影响是存在是不可忽略的。此后,在这思想基础上又开发了高基和分裂基等快速算法,随着数字技术的高速发展,1976年出现建立在数论和多项式理论基础上的维诺格勒傅里叶变换算法(WFTA)和素因子傅里叶变换算法。采用这种算法能使计算机计算离散傅里叶变换所需要的乘法次数大为减少,特别是被变换的抽样点数N越多,FFT算法计算量的节省就越显著。采用这种算法能使计算机计算离散傅里叶变换所需要的乘法次数大为减少,特别是被变换的抽样点数N越多,FFT算法计算量的节省就越显著。

FPGA/MATLAB学习教程/源码/项目合作开发 1977

Leaf - 一个由 Go 语言编写的开发效率和执行效率并重的开源游戏服务器框架

转自:https://toutiao.io/posts/0l7l7n/preview Leaf 游戏服务器框架简介 Leaf 是一个由 Go 语言(golang)编写的开发效率和执行效率并重的开源游戏服务器框架。Leaf 适用于各类游戏服务器的开发,包括 H5(HTML5)游戏服务器。 Leaf 的关注点: 良好的使用体验。Leaf 总是尽可能的提供简洁和易用的接口,尽可能的...

angzhan5306的博客 2409

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

组件分享之后端组件——基于Golang语言的游戏服务器框架leaf

组件分享之后端组件——基于Golang语言的游戏服务器框架leaf 背景 近期正在探索前端、后端、系统端各类常用组件与工具,对其一些常见的组件进行再次整理一下,形成标准化组件专题,后续该专题将包含各类语言中的一些常用组件。欢迎大家进行持续关注。 组件基本信息 组件:leaf 开源协议:Apache-2.0 License 内容 本节我们分享的是基于Golang语言的游戏服务器框架leaf。...

CN華少的博客 3742

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

golang leaf开源游戏服务器搭建

    Leaf是一个由Go语言(golang)编写的开发效率和执行效率并重的开源游戏服务器框架。Leaf适用于各类游戏服务器的开发 ,包括H5游戏服务器。     Leaf的关注点:     ·良好的使用体验。Leaf总是尽可能的提供简洁和易用的接口,尽可能的提升开发的效率     ·稳定性。Leaf总是尽可能的恢复运行过程中的错误,避免崩溃     ·多核支持。Leaf通过模块机制和l...

冷月醉雪的博客 5289

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

上一篇: 奔跑的微信,失控的张小龙
下一篇: 今日总结-做事要有全局思维,要心静,说话要放松。
shankusu2017
博客等级 码龄15年 155粉丝 155原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值