mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-11-03 16:00:25 +08:00
@@ -54,8 +54,8 @@ func (r *Req) Header(name, value string) *Req {
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *Req) Timeout(timeout int) *Req {
|
||||
r.timeout = timeout
|
||||
func (r *Req) Timeout(second int) *Req {
|
||||
r.timeout = second
|
||||
return r
|
||||
}
|
||||
|
||||
@@ -107,6 +107,25 @@ func (r *Req) PostForm(params string) *Resp {
|
||||
return sendRequest(r)
|
||||
}
|
||||
|
||||
func (r *Req) PutJson(body string) *Resp {
|
||||
buf := bytes.NewBufferString(body)
|
||||
r.method = "PUT"
|
||||
r.body = buf
|
||||
if r.header == nil {
|
||||
r.header = make(map[string]string)
|
||||
}
|
||||
r.header["Content-type"] = "application/json"
|
||||
return sendRequest(r)
|
||||
}
|
||||
|
||||
func (r *Req) PutObj(body any) *Resp {
|
||||
marshal, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
return &Resp{err: errors.New("解析json obj错误")}
|
||||
}
|
||||
return r.PutJson(string(marshal))
|
||||
}
|
||||
|
||||
func (r *Req) PostMulipart(files []MultipartFile, reqParams collx.M) *Resp {
|
||||
buf := &bytes.Buffer{}
|
||||
// 文件写入 buf
|
||||
|
||||
216
server/pkg/pool/channel.go
Normal file
216
server/pkg/pool/channel.go
Normal file
@@ -0,0 +1,216 @@
|
||||
package pool
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"mayfly-go/pkg/logx"
|
||||
"sync"
|
||||
"time"
|
||||
//"reflect"
|
||||
)
|
||||
|
||||
var (
|
||||
//ErrMaxActiveConnReached 连接池超限
|
||||
ErrMaxActiveConnReached = errors.New("MaxActiveConnReached")
|
||||
)
|
||||
|
||||
// Config 连接池相关配置
|
||||
type Config struct {
|
||||
//连接池中拥有的最小连接数
|
||||
InitialCap int
|
||||
//最大并发存活连接数
|
||||
MaxCap int
|
||||
//最大空闲连接
|
||||
MaxIdle int
|
||||
//生成连接的方法
|
||||
Factory func() (interface{}, error)
|
||||
//关闭连接的方法
|
||||
Close func(interface{}) error
|
||||
//检查连接是否有效的方法
|
||||
Ping func(interface{}) error
|
||||
//连接最大空闲时间,超过该事件则将失效
|
||||
IdleTimeout time.Duration
|
||||
}
|
||||
|
||||
// channelPool 存放连接信息
|
||||
type channelPool struct {
|
||||
mu sync.RWMutex
|
||||
conns chan *idleConn
|
||||
factory func() (interface{}, error)
|
||||
close func(interface{}) error
|
||||
ping func(interface{}) error
|
||||
idleTimeout, waitTimeOut time.Duration
|
||||
maxActive int
|
||||
openingConns int
|
||||
}
|
||||
|
||||
type idleConn struct {
|
||||
conn interface{}
|
||||
t time.Time
|
||||
}
|
||||
|
||||
// NewChannelPool 初始化连接
|
||||
func NewChannelPool(poolConfig *Config) (Pool, error) {
|
||||
if !(poolConfig.InitialCap <= poolConfig.MaxIdle && poolConfig.MaxCap >= poolConfig.MaxIdle && poolConfig.InitialCap >= 0) {
|
||||
return nil, errors.New("invalid capacity settings")
|
||||
}
|
||||
if poolConfig.Factory == nil {
|
||||
return nil, errors.New("invalid factory func settings")
|
||||
}
|
||||
if poolConfig.Close == nil {
|
||||
return nil, errors.New("invalid close func settings")
|
||||
}
|
||||
|
||||
c := &channelPool{
|
||||
conns: make(chan *idleConn, poolConfig.MaxIdle),
|
||||
factory: poolConfig.Factory,
|
||||
close: poolConfig.Close,
|
||||
idleTimeout: poolConfig.IdleTimeout,
|
||||
maxActive: poolConfig.MaxCap,
|
||||
openingConns: poolConfig.InitialCap,
|
||||
}
|
||||
|
||||
if poolConfig.Ping != nil {
|
||||
c.ping = poolConfig.Ping
|
||||
}
|
||||
|
||||
for i := 0; i < poolConfig.InitialCap; i++ {
|
||||
conn, err := c.factory()
|
||||
if err != nil {
|
||||
c.Release()
|
||||
return nil, fmt.Errorf("factory is not able to fill the pool: %s", err)
|
||||
}
|
||||
c.conns <- &idleConn{conn: conn, t: time.Now()}
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// getConns 获取所有连接
|
||||
func (c *channelPool) getConns() chan *idleConn {
|
||||
c.mu.Lock()
|
||||
conns := c.conns
|
||||
c.mu.Unlock()
|
||||
return conns
|
||||
}
|
||||
|
||||
// Get 从pool中取一个连接
|
||||
func (c *channelPool) Get() (interface{}, error) {
|
||||
conns := c.getConns()
|
||||
if conns == nil {
|
||||
return nil, ErrClosed
|
||||
}
|
||||
for {
|
||||
select {
|
||||
case wrapConn := <-conns:
|
||||
if wrapConn == nil {
|
||||
return nil, ErrClosed
|
||||
}
|
||||
//判断是否超时,超时则丢弃
|
||||
if timeout := c.idleTimeout; timeout > 0 {
|
||||
if wrapConn.t.Add(timeout).Before(time.Now()) {
|
||||
//丢弃并关闭该连接
|
||||
c.Close(wrapConn.conn)
|
||||
continue
|
||||
}
|
||||
}
|
||||
//判断是否失效,失效则丢弃,如果用户没有设定 ping 方法,就不检查
|
||||
if c.ping != nil {
|
||||
if err := c.Ping(wrapConn.conn); err != nil {
|
||||
c.Close(wrapConn.conn)
|
||||
continue
|
||||
}
|
||||
}
|
||||
return wrapConn.conn, nil
|
||||
default:
|
||||
c.mu.Lock()
|
||||
logx.Debugf("openConn %v %v", c.openingConns, c.maxActive)
|
||||
defer c.mu.Unlock()
|
||||
if c.openingConns >= c.maxActive {
|
||||
return nil, ErrMaxActiveConnReached
|
||||
}
|
||||
if c.factory == nil {
|
||||
return nil, ErrClosed
|
||||
}
|
||||
conn, err := c.factory()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.openingConns++
|
||||
return conn, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Put 将连接放回pool中
|
||||
func (c *channelPool) Put(conn interface{}) error {
|
||||
if conn == nil {
|
||||
return errors.New("connection is nil. rejecting")
|
||||
}
|
||||
|
||||
c.mu.Lock()
|
||||
|
||||
if c.conns == nil {
|
||||
c.mu.Unlock()
|
||||
return c.Close(conn)
|
||||
}
|
||||
|
||||
select {
|
||||
case c.conns <- &idleConn{conn: conn, t: time.Now()}:
|
||||
c.mu.Unlock()
|
||||
return nil
|
||||
default:
|
||||
c.mu.Unlock()
|
||||
//连接池已满,直接关闭该连接
|
||||
return c.Close(conn)
|
||||
}
|
||||
}
|
||||
|
||||
// Close 关闭单条连接
|
||||
func (c *channelPool) Close(conn interface{}) error {
|
||||
if conn == nil {
|
||||
return errors.New("connection is nil. rejecting")
|
||||
}
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
if c.close == nil {
|
||||
return nil
|
||||
}
|
||||
c.openingConns--
|
||||
return c.close(conn)
|
||||
}
|
||||
|
||||
// Ping 检查单条连接是否有效
|
||||
func (c *channelPool) Ping(conn interface{}) error {
|
||||
if conn == nil {
|
||||
return errors.New("connection is nil. rejecting")
|
||||
}
|
||||
return c.ping(conn)
|
||||
}
|
||||
|
||||
// Release 释放连接池中所有连接
|
||||
func (c *channelPool) Release() {
|
||||
c.mu.Lock()
|
||||
conns := c.conns
|
||||
c.conns = nil
|
||||
c.factory = nil
|
||||
c.ping = nil
|
||||
closeFun := c.close
|
||||
c.close = nil
|
||||
c.mu.Unlock()
|
||||
|
||||
if conns == nil {
|
||||
return
|
||||
}
|
||||
|
||||
close(conns)
|
||||
for wrapConn := range conns {
|
||||
//log.Printf("Type %v\n",reflect.TypeOf(wrapConn.conn))
|
||||
_ = closeFun(wrapConn.conn)
|
||||
}
|
||||
}
|
||||
|
||||
// Len 连接池中已有的连接
|
||||
func (c *channelPool) Len() int {
|
||||
return len(c.getConns())
|
||||
}
|
||||
21
server/pkg/pool/pool.go
Normal file
21
server/pkg/pool/pool.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package pool
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
//ErrClosed 连接池已经关闭Error
|
||||
ErrClosed = errors.New("pool is closed")
|
||||
)
|
||||
|
||||
// Pool 基本方法
|
||||
type Pool interface {
|
||||
Get() (interface{}, error)
|
||||
|
||||
Put(interface{}) error
|
||||
|
||||
Close(interface{}) error
|
||||
|
||||
Release()
|
||||
|
||||
Len() int
|
||||
}
|
||||
@@ -43,6 +43,9 @@ func NewPut(path string, handler HandlerFunc) *Conf {
|
||||
func NewDelete(path string, handler HandlerFunc) *Conf {
|
||||
return New("DELETE", path, handler)
|
||||
}
|
||||
func NewAny(path string, handler HandlerFunc) *Conf {
|
||||
return New("any", path, handler)
|
||||
}
|
||||
|
||||
func (r *Conf) ToGinHFunc() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
@@ -82,7 +85,11 @@ func (r *Conf) NoRes() *Conf {
|
||||
|
||||
// 注册至group
|
||||
func (r *Conf) Group(gr *gin.RouterGroup) *Conf {
|
||||
gr.Handle(r.method, r.path, r.ToGinHFunc())
|
||||
if r.method == "any" {
|
||||
gr.Any(r.path, r.ToGinHFunc())
|
||||
} else {
|
||||
gr.Handle(r.method, r.path, r.ToGinHFunc())
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user