golang 创建一个简单的连接池,减少频繁的创建与关闭
2017-07-25 17:12
253 查看
一、连接池的描述图片如下:
二、连接池代码如下:
三、8080服务端代码如下:
测试结果如下:
二、连接池代码如下:
package main; import ( "time" "sync" "errors" "net" "fmt" ) //频繁的创建和关闭连接,对系统会造成很大负担 //所以我们需要一个池子,里面事先创建好固定数量的连接资源,需要时就取,不需要就放回池中。 //但是连接资源有一个特点,我们无法保证连接长时间会有效。 //比如,网络原因,人为原因等都会导致连接失效。 //所以我们设置一个超时时间,如果连接时间与当前时间相差超过超时时间,那么就关闭连接。 //只要类型实现了ConnRes接口中的方法,就认为是一个连接资源类型 type ConnRes interface { Close() error; } //工厂方法,用于创建连接资源 type Factory func() (ConnRes, error) //连接 type Conn struct { conn ConnRes; //连接时间 time time.Time; } //连接池 type ConnPool struct { //互斥锁,保证资源安全 mu sync.Mutex; //通道,保存所有连接资源 conns chan *Conn; //工厂方法,创建连接资源 factory Factory; //判断池是否关闭 closed bool; //连接超时时间 connTimeOut time.Duration; } //创建一个连接资源池 func NewConnPool(factory Factory, cap int, connTimeOut time.Duration) (*ConnPool, error) { if cap <= 0 { return nil, errors.New("cap不能小于0"); } if connTimeOut <= 0 { return nil, errors.New("connTimeOut不能小于0"); } cp := &ConnPool{ mu: sync.Mutex{}, conns: make(chan *Conn, cap), factory: factory, closed: false, connTimeOut: connTimeOut, }; for i := 0; i < cap; i++ { //通过工厂方法创建连接资源 connRes, err := cp.factory(); if err != nil { cp.Close(); return nil, errors.New("factory出错"); } //将连接资源插入通道中 cp.conns <- &Conn{conn: connRes, time: time.Now()}; } return cp, nil; } //获取连接资源 func (cp *ConnPool) Get() (ConnRes, error) { if cp.closed { return nil, errors.New("连接池已关闭"); } for { select { //从通道中获取连接资源 case connRes, ok := <-cp.conns: { if !ok { return nil, errors.New("连接池已关闭"); } //判断连接中的时间,如果超时,则关闭 //继续获取 if time.Now().Sub(connRes.time) > cp.connTimeOut { connRes.conn.Close(); continue; } return connRes.conn, nil; } default: { //如果无法从通道中获取资源,则重新创建一个资源返回 connRes, err := cp.factory(); if err != nil { return nil, err; } return connRes, nil; } } } } //连接资源放回池中 func (cp *ConnPool) Put(conn ConnRes) error { if cp.closed { return errors.New("连接池已关闭"); } select { //向通道中加入连接资源 case cp.conns <- &Conn{conn: conn, time: time.Now()}: { return nil; } default: { //如果无法加入,则关闭连接 conn.Close(); return errors.New("连接池已满"); } } } //关闭连接池 func (cp *ConnPool) Close() { if cp.closed { return; } cp.mu.Lock(); cp.closed = true; //关闭通道 close(cp.conns); //循环关闭通道中的连接 for conn := range cp.conns { conn.conn.Close(); } cp.mu.Unlock(); } //返回池中通道的长度 func (cp *ConnPool) len() int { return len(cp.conns); } func main() { cp, _ := NewConnPool(func() (ConnRes, error) { return net.Dial("tcp", ":8080"); }, 10, time.Second*10); //获取资源 conn1, _ := cp.Get(); conn2, _ := cp.Get(); //这里连接池中资源大小为8 fmt.Println("cp len : ", cp.len()); conn1.(net.Conn).Write([]byte("hello")); conn2.(net.Conn).Write([]byte("world")); buf := make([]byte, 1024); n, _ := conn1.(net.Conn).Read(buf); fmt.Println("conn1 read : ", string(buf[:n])); n, _ = conn2.(net.Conn).Read(buf); fmt.Println("conn2 read : ", string(buf[:n])); //等待15秒 time.Sleep(time.Second * 15); //我们再从池中获取资源 conn3, _ := cp.Get(); //这里显示为0,因为池中的连接资源都超时了 fmt.Println("cp len : ", cp.len()); conn3.(net.Conn).Write([]byte("test")); n, _ = conn3.(net.Conn).Read(buf); fmt.Println("conn3 read : ", string(buf[:n])); //把三个连接资源放回池中 cp.Put(conn1); cp.Put(conn2); cp.Put(conn3); //这里显示为3 fmt.Println("cp len : ", cp.len()); cp.Close(); }
三、8080服务端代码如下:
package main; import ( "net" "io" "log" ) func handler(conn net.Conn) { for { io.Copy(conn, conn); } } func main() { lis, err := net.Listen("tcp", ":8080"); if err != nil { log.Fatal(err); } for { conn, err := lis.Accept(); if err != nil { continue; } go handler(conn); } }
测试结果如下:
相关文章推荐
- golang 创建一个简单的连接池,减少频繁的创建与关闭
- golang 创建一个简单的资源池,重用资源,减少GC负担
- 浅谈Golang中创建一个简单的服务器的方法
- 剖析一个WIFI搜索、创建、关闭、连接及一些简单的动画==============
- golang 创建一个简单的广播echo服务器
- 手动创建一个简单的连接池
- 创建一个简单的WCF程序2——手动开启/关闭WCF服务与动态调用WCF地址
- 以一个简单的数据库表为例来展示创建全局/局部数据源和连接池的配置与测试
- JDBC创建一个数据连接连接池的实例
- .net创建一个ActiveX控件并使用的简单例子
- 实现一个简单的HttpClient连接池(转自博客园)
- android开发系列之一—创建一个简单的webapp
- 使用Spring来创建一个简单的工作流引擎
- 使用nRF51822/nRF51422创建一个简单的BLE应用 ---入门实例手册(中文)之四
- 如何使用 CoreText 创建一个简单的杂志应用
- mysql 自定义函数(1)创建一个简单函数
- 一起谈.NET技术,Visual Studio DSL 入门 3---创建一个简单的DSL模型
- IntelliJ IDEA 15 部署Tomcat及创建一个简单的Web工程
- python中简单创建一个类
- android学习:service的创建,打开、关闭一个service