当前位置: 首页 > 工具软件 > go-xorm > 使用案例 >

github.com/go-xorm/xorm. XORM-Engine Group

冯皓
2023-12-01

https://www.bookstack.cn/read/go-xorm-0.6.5/README.md

https://www.bookstack.cn/read/go-xorm-0.6.5/chapter-01-2.engine_group.md

创建 ORM 引擎

所有操作均需要事先创建并配置 ORM 引擎才可以进行。XORM支持两种 ORM 引擎,即 Engine 引擎和 Engine Group 引擎。
一个 Engine 引擎用于对单个数据库进行操作,
一个 Engine Group 引擎用于对读写分离的数据库或者负载均衡的数据库进行操作。
Engine 引擎和 EngineGroup 引擎的API基本相同,所有适用于 Engine 的API基本上都适用于 EngineGroup,并且可以比较容易的从 Engine 引擎迁移到 EngineGroup引擎。

单库引擎 创建 Engine 引擎

单个ORM引擎,也称为Engine。一个APP可以同时存在多个Engine引擎,一个Engine一般只对应一个数据库。Engine通过调用xorm.NewEngine生成,如:

import (
    _ "github.com/go-sql-driver/mysql"
    "github.com/go-xorm/xorm"
)
var engine *xorm.Engine
func main() {
    var err error
    engine, err = xorm.NewEngine("mysql", "root:123@/test?charset=utf8")
}

or

import (
    _ "github.com/mattn/go-sqlite3"
    "github.com/go-xorm/xorm"
)
var engine *xorm.Engine
func main() {
    var err error
    engine, err = xorm.NewEngine("sqlite3", "./test.db")
}

一般情况下如果只操作一个数据库,只需要创建一个engine即可。engine是GoRoutine安全的。

创建完成engine之后,并没有立即连接数据库,此时可以通过engine.Ping()来进行数据库的连接测试是否可以连接到数据库。另外对于某些数据库有连接超时设置的,可以通过起一个定期Ping的Go程来保持连接鲜活。

对于有大量数据并且需要分区的应用,也可以根据规则来创建多个Engine,比如:

var err error
for i:=0;i<5;i++ {
    engines[i], err = xorm.NewEngine("sqlite3", fmt.Sprintf("./test%d.db", i))
}

engine可以通过engine.Close来手动关闭,但是一般情况下可以不用关闭,在程序退出时会自动关闭。

NewEngine传入的参数和sql.Open传入的参数完全相同,因此,在使用某个驱动前,请查看此驱动中关于传入参数的说明文档。以下为各个驱动的连接符对应的文档链接:

sqlite3

mysql dsn

mymysql

postgres

在engine创建完成后可以进行一些设置,如:

日志
日志是一个接口,通过设置日志,可以显示SQL,警告以及错误等,默认的显示级别为INFO。

engine.ShowSQL(true),则会在控制台打印出生成的SQL语句;
engine.Logger().SetLevel(core.LOG_DEBUG),则会在控制台打印调试及以上的信息;
如果希望将信息不仅打印到控制台,而是保存为文件,那么可以通过类似如下的代码实现,NewSimpleLogger(w io.Writer)接收一个io.Writer接口来将数据写入到对应的设施中。

f, err := os.Create("sql.log")
if err != nil {
    println(err.Error())
    return
}
engine.SetLogger(xorm.NewSimpleLogger(f))

当然,如果希望将日志记录到syslog中,也可以如下:

logWriter, err := syslog.New(syslog.LOG_DEBUG, "rest-xorm-example")
if err != nil {
    log.Fatalf("Fail to create xorm system logger: %v\n", err)
}
logger := xorm.NewSimpleLogger(logWriter)
logger.ShowSQL(true)
engine.SetLogger(logger)

连接池
engine内部支持连接池接口和对应的函数。

  • 如果需要设置连接池的空闲数大小,可以使用engine.SetMaxIdleConns()来实现。
  • 如果需要设置最大打开连接数,则可以使用engine.SetMaxOpenConns()来实现。

创建 Engine Group 引擎

通过创建引擎组EngineGroup来实现对从数据库(Master/Slave)读写分离的支持。在创建引擎章节中,我们已经介绍过了,在xorm里面,可以同时存在多个Orm引擎,一个Orm引擎称为Engine,一个Engine一般只对应一个数据库,而EngineGroup一般则对应一组数据库。EngineGroup通过调用xorm.NewEngineGroup生成,如:

import (
    _ "github.com/lib/pq"
    "github.com/xormplus/xorm"
)
var eg *xorm.EngineGroup
func main() {
    conns := []string{
        "postgres://postgres:root@localhost:5432/test?sslmode=disable;", // 第一个默认是master
        "postgres://postgres:root@localhost:5432/test1?sslmode=disable;", // 第二个开始都是slave
        "postgres://postgres:root@localhost:5432/test2?sslmode=disable",
    }
    var err error
    eg, err = xorm.NewEngineGroup("postgres", conns)
}

或者

import (
    _ "github.com/lib/pq"
    "github.com/xormplus/xorm"
)
var eg *xorm.EngineGroup
func main() {
    var err error
    master, err := xorm.NewEngine("postgres", "postgres://postgres:root@localhost:5432/test?sslmode=disable")
    if err != nil {
        return
    }
    slave1, err := xorm.NewEngine("postgres", "postgres://postgres:root@localhost:5432/test1?sslmode=disable")
    if err != nil {
        return
    }
    slave2, err := xorm.NewEngine("postgres", "postgres://postgres:root@localhost:5432/test2?sslmode=disable")
    if err != nil {
        return
    }
       slaves := []*xorm.Engine{slave1, slave2}
    eg, err = xorm.NewEngineGroup(master, slaves)
}

创建完成EngineGroup之后,并没有立即连接数据库,此时可以通过eg.Ping()来进行数据库的连接测试是否可以连接到数据库,该方法会依次调用引擎组中每个Engine的Ping方法。另外对于某些数据库有连接超时设置的,可以通过起一个定期Ping的Go程来保持连接鲜活。EngineGroup可以通过eg.Close()来手动关闭,但是一般情况下可以不用关闭,在程序退出时会自动关闭。

NewEngineGroup方法

func NewEngineGroup(args1 interface{}, args2 interface{}, policies ...GroupPolicy) (*EngineGroup, error)

前两个参数的使用示例如上,有两种模式。
模式一:通过给定DriverName,DataSourceName来创建引擎组,每个引擎使用相同的Driver。每个引擎的DataSourceNames是[]string类型,第一个元素是Master的DataSourceName,之后的元素是Slave的DataSourceName。
模式二:通过给定xorm.Engine,[]xorm.Engine来创建引擎组,每个引擎可以使用不同的Driver。第一个参数为Master的xorm.Engine,第二个参数为Slave的[]xorm.Engine。NewEngineGroup方法,第三个参数为policies,为Slave给定负载策略,该参数将在负载策略章节详细介绍,如示例中未指定,则默认为轮询负载策略。

Master方法

func (eg *EngineGroup) Master() *Engine

返回Master数据库引擎

Slave方法

func (eg *EngineGroup) Slave() *Engine

依据给定的负载策略返回一个Slave数据库引擎

Slaves方法

func (eg *EngineGroup) Slaves() []*Engine

返回所有Slave数据库引擎

GetSlave方法

func (eg *EngineGroup) GetSlave(i int) *Engine

依据一组Slave数据库引擎[]*xorm.Engine下标返回指定Slave数据库引擎。通过给定DriverName,DataSourceName来创建引擎组,则DataSourceName的第二个元素的数据库为下标0的Slave数据库引擎。

SetPolicy方法

func (eg *EngineGroup) SetPolicy(policy GroupPolicy) *EngineGroup

设置引擎组负载策略

引擎组策略 负载策略

通过xorm.NewEngineGroup创建EngineGroup时,第三个参数为policies,我们可以通过该参数来指定Slave访问的负载策略。如创建EngineGroup时未指定,则默认使用轮询的负载策略。

xorm中内置五种负载策略,分别为随机访问负载策略,权重随机访问负载策略,轮询访问负载策略,权重轮询访问负载策略和最小连接数访问负载策略。开发者也可以通过实现GroupPolicy接口,来实现自定义负载策略。

随机访问负载策略

import (
    _ "github.com/lib/pq"
    "github.com/xormplus/xorm"
)
var eg *xorm.EngineGroup
func main() {
    conns := []string{
        "postgres://postgres:root@localhost:5432/test?sslmode=disable;",
        "postgres://postgres:root@localhost:5432/test1?sslmode=disable;",
        "postgres://postgres:root@localhost:5432/test2?sslmode=disable",
    }
    var err error
    eg, err = xorm.NewEngineGroup("postgres", conns, xorm.RandomPolicy())
}

权重随机访问负载策略

import (
    _ "github.com/lib/pq"
    "github.com/xormplus/xorm"
)
var eg *xorm.EngineGroup
func main() {
    conns := []string{
        "postgres://postgres:root@localhost:5432/test?sslmode=disable;",
        "postgres://postgres:root@localhost:5432/test1?sslmode=disable;",
        "postgres://postgres:root@localhost:5432/test2?sslmode=disable",
    }
    var err error
    //此时设置的test1数据库和test2数据库的随机访问权重为2和3
    eg, err = xorm.NewEngineGroup("postgres", conns, xorm.WeightRandomPolicy([]int{2, 3}))
}

轮询访问负载策略

import (
    _ "github.com/lib/pq"
    "github.com/xormplus/xorm"
)
var eg *xorm.EngineGroup
func main() {
    conns := []string{
        "postgres://postgres:root@localhost:5432/test?sslmode=disable;",
        "postgres://postgres:root@localhost:5432/test1?sslmode=disable;",
        "postgres://postgres:root@localhost:5432/test2?sslmode=disable",
    }
    var err error
    eg, err = xorm.NewEngineGroup("postgres", conns, xorm.RoundRobinPolicy())
}

权重轮询访问负载策略

import (
    _ "github.com/lib/pq"
    "github.com/xormplus/xorm"
)
var eg *xorm.EngineGroup
func main() {
    conns := []string{
        "postgres://postgres:root@localhost:5432/test?sslmode=disable;",
        "postgres://postgres:root@localhost:5432/test1?sslmode=disable;",
        "postgres://postgres:root@localhost:5432/test2?sslmode=disable",
    }
    var err error
    //此时设置的test1数据库和test2数据库的轮询访问权重为2和3
    eg, err = xorm.NewEngineGroup("postgres", conns, xorm.WeightRoundRobinPolicy([]int{2, 3}))
}

最小连接数访问负载策略

import (
    _ "github.com/lib/pq"
    "github.com/xormplus/xorm"
)
var eg *xorm.EngineGroup
func main() {
    conns := []string{
        "postgres://postgres:root@localhost:5432/test?sslmode=disable;",
        "postgres://postgres:root@localhost:5432/test1?sslmode=disable;",
        "postgres://postgres:root@localhost:5432/test2?sslmode=disable",
    }
    var err error
    eg, err = xorm.NewEngineGroup("postgres", conns, xorm.LeastConnPolicy())
}

自定义负载策略
你也可以通过实现 GroupPolicy 接口来实现自定义负载策略。

type GroupPolicy interface {
    Slave(*EngineGroup) *Engine
}
 类似资料: