github.com/astaxie/beego@v1.12.3/session/redis_cluster/redis_cluster.go (about)

     1  // Copyright 2014 beego Author. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package redis for session provider
    16  //
    17  // depend on github.com/go-redis/redis
    18  //
    19  // go install github.com/go-redis/redis
    20  //
    21  // Usage:
    22  // import(
    23  //   _ "github.com/astaxie/beego/session/redis_cluster"
    24  //   "github.com/astaxie/beego/session"
    25  // )
    26  //
    27  //	func init() {
    28  //		globalSessions, _ = session.NewManager("redis_cluster", ``{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"127.0.0.1:7070;127.0.0.1:7071"}``)
    29  //		go globalSessions.GC()
    30  //	}
    31  //
    32  // more docs: http://beego.me/docs/module/session.md
    33  package redis_cluster
    34  
    35  import (
    36  	"net/http"
    37  	"strconv"
    38  	"strings"
    39  	"sync"
    40  	"time"
    41  
    42  	"github.com/astaxie/beego/session"
    43  	rediss "github.com/go-redis/redis"
    44  )
    45  
    46  var redispder = &Provider{}
    47  
    48  // MaxPoolSize redis_cluster max pool size
    49  var MaxPoolSize = 1000
    50  
    51  // SessionStore redis_cluster session store
    52  type SessionStore struct {
    53  	p           *rediss.ClusterClient
    54  	sid         string
    55  	lock        sync.RWMutex
    56  	values      map[interface{}]interface{}
    57  	maxlifetime int64
    58  }
    59  
    60  // Set value in redis_cluster session
    61  func (rs *SessionStore) Set(key, value interface{}) error {
    62  	rs.lock.Lock()
    63  	defer rs.lock.Unlock()
    64  	rs.values[key] = value
    65  	return nil
    66  }
    67  
    68  // Get value in redis_cluster session
    69  func (rs *SessionStore) Get(key interface{}) interface{} {
    70  	rs.lock.RLock()
    71  	defer rs.lock.RUnlock()
    72  	if v, ok := rs.values[key]; ok {
    73  		return v
    74  	}
    75  	return nil
    76  }
    77  
    78  // Delete value in redis_cluster session
    79  func (rs *SessionStore) Delete(key interface{}) error {
    80  	rs.lock.Lock()
    81  	defer rs.lock.Unlock()
    82  	delete(rs.values, key)
    83  	return nil
    84  }
    85  
    86  // Flush clear all values in redis_cluster session
    87  func (rs *SessionStore) Flush() error {
    88  	rs.lock.Lock()
    89  	defer rs.lock.Unlock()
    90  	rs.values = make(map[interface{}]interface{})
    91  	return nil
    92  }
    93  
    94  // SessionID get redis_cluster session id
    95  func (rs *SessionStore) SessionID() string {
    96  	return rs.sid
    97  }
    98  
    99  // SessionRelease save session values to redis_cluster
   100  func (rs *SessionStore) SessionRelease(w http.ResponseWriter) {
   101  	b, err := session.EncodeGob(rs.values)
   102  	if err != nil {
   103  		return
   104  	}
   105  	c := rs.p
   106  	c.Set(rs.sid, string(b), time.Duration(rs.maxlifetime)*time.Second)
   107  }
   108  
   109  // Provider redis_cluster session provider
   110  type Provider struct {
   111  	maxlifetime int64
   112  	savePath    string
   113  	poolsize    int
   114  	password    string
   115  	dbNum       int
   116  	poollist    *rediss.ClusterClient
   117  }
   118  
   119  // SessionInit init redis_cluster session
   120  // savepath like redis server addr,pool size,password,dbnum
   121  // e.g. 127.0.0.1:6379;127.0.0.1:6380,100,test,0
   122  func (rp *Provider) SessionInit(maxlifetime int64, savePath string) error {
   123  	rp.maxlifetime = maxlifetime
   124  	configs := strings.Split(savePath, ",")
   125  	if len(configs) > 0 {
   126  		rp.savePath = configs[0]
   127  	}
   128  	if len(configs) > 1 {
   129  		poolsize, err := strconv.Atoi(configs[1])
   130  		if err != nil || poolsize < 0 {
   131  			rp.poolsize = MaxPoolSize
   132  		} else {
   133  			rp.poolsize = poolsize
   134  		}
   135  	} else {
   136  		rp.poolsize = MaxPoolSize
   137  	}
   138  	if len(configs) > 2 {
   139  		rp.password = configs[2]
   140  	}
   141  	if len(configs) > 3 {
   142  		dbnum, err := strconv.Atoi(configs[3])
   143  		if err != nil || dbnum < 0 {
   144  			rp.dbNum = 0
   145  		} else {
   146  			rp.dbNum = dbnum
   147  		}
   148  	} else {
   149  		rp.dbNum = 0
   150  	}
   151  
   152  	rp.poollist = rediss.NewClusterClient(&rediss.ClusterOptions{
   153  		Addrs:    strings.Split(rp.savePath, ";"),
   154  		Password: rp.password,
   155  		PoolSize: rp.poolsize,
   156  	})
   157  	return rp.poollist.Ping().Err()
   158  }
   159  
   160  // SessionRead read redis_cluster session by sid
   161  func (rp *Provider) SessionRead(sid string) (session.Store, error) {
   162  	var kv map[interface{}]interface{}
   163  	kvs, err := rp.poollist.Get(sid).Result()
   164  	if err != nil && err != rediss.Nil {
   165  		return nil, err
   166  	}
   167  	if len(kvs) == 0 {
   168  		kv = make(map[interface{}]interface{})
   169  	} else {
   170  		if kv, err = session.DecodeGob([]byte(kvs)); err != nil {
   171  			return nil, err
   172  		}
   173  	}
   174  
   175  	rs := &SessionStore{p: rp.poollist, sid: sid, values: kv, maxlifetime: rp.maxlifetime}
   176  	return rs, nil
   177  }
   178  
   179  // SessionExist check redis_cluster session exist by sid
   180  func (rp *Provider) SessionExist(sid string) bool {
   181  	c := rp.poollist
   182  	if existed, err := c.Exists(sid).Result(); err != nil || existed == 0 {
   183  		return false
   184  	}
   185  	return true
   186  }
   187  
   188  // SessionRegenerate generate new sid for redis_cluster session
   189  func (rp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) {
   190  	c := rp.poollist
   191  
   192  	if existed, err := c.Exists(oldsid).Result(); err != nil || existed == 0 {
   193  		// oldsid doesn't exists, set the new sid directly
   194  		// ignore error here, since if it return error
   195  		// the existed value will be 0
   196  		c.Set(sid, "", time.Duration(rp.maxlifetime)*time.Second)
   197  	} else {
   198  		c.Rename(oldsid, sid)
   199  		c.Expire(sid, time.Duration(rp.maxlifetime)*time.Second)
   200  	}
   201  	return rp.SessionRead(sid)
   202  }
   203  
   204  // SessionDestroy delete redis session by id
   205  func (rp *Provider) SessionDestroy(sid string) error {
   206  	c := rp.poollist
   207  	c.Del(sid)
   208  	return nil
   209  }
   210  
   211  // SessionGC Impelment method, no used.
   212  func (rp *Provider) SessionGC() {
   213  }
   214  
   215  // SessionAll return all activeSession
   216  func (rp *Provider) SessionAll() int {
   217  	return 0
   218  }
   219  
   220  func init() {
   221  	session.Register("redis_cluster", redispder)
   222  }