github.com/polarismesh/polaris@v1.17.8/store/mysql/default.go (about)

     1  /**
     2   * Tencent is pleased to support the open source community by making Polaris available.
     3   *
     4   * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
     5   *
     6   * Licensed under the BSD 3-Clause License (the "License");
     7   * you may not use this file except in compliance with the License.
     8   * You may obtain a copy of the License at
     9   *
    10   * https://opensource.org/licenses/BSD-3-Clause
    11   *
    12   * Unless required by applicable law or agreed to in writing, software distributed
    13   * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
    14   * CONDITIONS OF ANY KIND, either express or implied. See the License for the
    15   * specific language governing permissions and limitations under the License.
    16   */
    17  
    18  package sqldb
    19  
    20  import (
    21  	"errors"
    22  	"fmt"
    23  
    24  	_ "github.com/go-sql-driver/mysql"
    25  
    26  	"github.com/polarismesh/polaris/plugin"
    27  	"github.com/polarismesh/polaris/store"
    28  )
    29  
    30  const (
    31  	// SystemNamespace system namespace
    32  	SystemNamespace = "Polaris"
    33  	// STORENAME database storage name
    34  	STORENAME = "defaultStore"
    35  	// DefaultConnMaxLifetime default maximum connection lifetime
    36  	DefaultConnMaxLifetime = 60 * 30 // 默认是30分钟
    37  	// emptyEnableTime 规则禁用时启用时间的默认值
    38  	emptyEnableTime = "STR_TO_DATE('1980-01-01 00:00:01', '%Y-%m-%d %H:%i:%s')"
    39  )
    40  
    41  // init 自动引入包初始化函数
    42  func init() {
    43  	s := &stableStore{}
    44  	_ = store.RegisterStore(s)
    45  }
    46  
    47  // stableStore 实现了Store接口
    48  type stableStore struct {
    49  	*namespaceStore
    50  	*serviceStore
    51  	*instanceStore
    52  	*routingConfigStore
    53  	*l5Store
    54  	*rateLimitStore
    55  	*circuitBreakerStore
    56  	*toolStore
    57  	*userStore
    58  	*groupStore
    59  	*strategyStore
    60  	*faultDetectRuleStore
    61  
    62  	// 配置中心stores
    63  	*configFileGroupStore
    64  	*configFileStore
    65  	*configFileReleaseStore
    66  	*configFileReleaseHistoryStore
    67  	*configFileTemplateStore
    68  
    69  	// client info stores
    70  	*clientStore
    71  
    72  	// v2 存储
    73  	*routingConfigStoreV2
    74  
    75  	// maintain store
    76  	*adminStore
    77  
    78  	// 主数据库,可以进行读写
    79  	master *BaseDB
    80  	// 对主数据库的事务操作,可读写
    81  	masterTx *BaseDB
    82  	// 备数据库,提供只读
    83  	slave *BaseDB
    84  	start bool
    85  }
    86  
    87  // Name 实现Name函数
    88  func (s *stableStore) Name() string {
    89  	return STORENAME
    90  }
    91  
    92  // Initialize 初始化函数
    93  func (s *stableStore) Initialize(conf *store.Config) error {
    94  	if s.start {
    95  		return nil
    96  	}
    97  
    98  	masterConfig, slaveConfig, err := parseDatabaseConf(conf.Option)
    99  	if err != nil {
   100  		return err
   101  	}
   102  	master, err := NewBaseDB(masterConfig, plugin.GetParsePassword())
   103  	if err != nil {
   104  		return err
   105  	}
   106  	s.master = master
   107  
   108  	masterTx, err := NewBaseDB(masterConfig, plugin.GetParsePassword())
   109  	if err != nil {
   110  		return err
   111  	}
   112  	s.masterTx = masterTx
   113  
   114  	if slaveConfig != nil {
   115  		log.Infof("[Store][database] use slave database config: %+v", slaveConfig)
   116  		slave, err := NewBaseDB(slaveConfig, plugin.GetParsePassword())
   117  		if err != nil {
   118  			return err
   119  		}
   120  		s.slave = slave
   121  	}
   122  	// 如果slave为空,意味着slaveConfig为空,用master数据库替代
   123  	if s.slave == nil {
   124  		s.slave = s.master
   125  	}
   126  
   127  	log.Infof("[Store][database] connect the database successfully")
   128  
   129  	s.start = true
   130  	s.newStore()
   131  	return nil
   132  }
   133  
   134  // parseDatabaseConf return slave, master, error
   135  func parseDatabaseConf(opt map[string]interface{}) (*dbConfig, *dbConfig, error) {
   136  	// 必填
   137  	masterEnter, ok := opt["master"]
   138  	if !ok || masterEnter == nil {
   139  		return nil, nil, errors.New("database master db config is missing")
   140  	}
   141  	masterConfig, err := parseStoreConfig(masterEnter)
   142  	if err != nil {
   143  		return nil, nil, err
   144  	}
   145  
   146  	// 只读数据库可选
   147  	slaveEntry, ok := opt["slave"]
   148  	if !ok || slaveEntry == nil {
   149  		return masterConfig, nil, nil
   150  	}
   151  	slaveConfig, err := parseStoreConfig(slaveEntry)
   152  	if err != nil {
   153  		return nil, nil, err
   154  	}
   155  
   156  	return masterConfig, slaveConfig, nil
   157  }
   158  
   159  // parseStoreConfig 解析store的配置
   160  func parseStoreConfig(opts interface{}) (*dbConfig, error) {
   161  	obj, _ := opts.(map[interface{}]interface{})
   162  
   163  	needCheckFields := map[string]string{"dbType": "", "dbUser": "", "dbPwd": "", "dbAddr": "", "dbName": ""}
   164  
   165  	for key := range needCheckFields {
   166  		val, ok := obj[key]
   167  		if !ok {
   168  			return nil, fmt.Errorf("config Plugin %s:%s type must be string", STORENAME, key)
   169  		}
   170  
   171  		needCheckFields[key] = fmt.Sprintf("%v", val)
   172  	}
   173  
   174  	c := &dbConfig{
   175  		dbType: needCheckFields["dbType"],
   176  		dbUser: needCheckFields["dbUser"],
   177  		dbPwd:  needCheckFields["dbPwd"],
   178  		dbAddr: needCheckFields["dbAddr"],
   179  		dbName: needCheckFields["dbName"],
   180  	}
   181  	if maxOpenConns, _ := obj["maxOpenConns"].(int); maxOpenConns > 0 {
   182  		c.maxOpenConns = maxOpenConns
   183  	}
   184  	if maxIdleConns, _ := obj["maxIdleConns"].(int); maxIdleConns > 0 {
   185  		c.maxIdleConns = maxIdleConns
   186  	}
   187  	c.connMaxLifetime = DefaultConnMaxLifetime
   188  	if connMaxLifetime, _ := obj["connMaxLifetime"].(int); connMaxLifetime > 0 {
   189  		c.connMaxLifetime = connMaxLifetime
   190  	}
   191  
   192  	if isolationLevel, _ := obj["txIsolationLevel"].(int); isolationLevel > 0 {
   193  		c.txIsolationLevel = isolationLevel
   194  	}
   195  	return c, nil
   196  }
   197  
   198  // Destroy 退出函数
   199  func (s *stableStore) Destroy() error {
   200  	s.start = false
   201  	if s.master != nil {
   202  		_ = s.master.Close()
   203  	}
   204  	if s.masterTx != nil {
   205  		_ = s.masterTx.Close()
   206  	}
   207  	if s.slave != nil {
   208  		_ = s.slave.Close()
   209  	}
   210  
   211  	if s.adminStore != nil {
   212  		s.adminStore.StopLeaderElections()
   213  	}
   214  
   215  	s.master = nil
   216  	s.masterTx = nil
   217  	s.slave = nil
   218  
   219  	return nil
   220  }
   221  
   222  // CreateTransaction 创建一个事务
   223  func (s *stableStore) CreateTransaction() (store.Transaction, error) {
   224  	// 每次创建事务前,还是需要ping一下
   225  	_ = s.masterTx.Ping()
   226  
   227  	nt := &transaction{}
   228  	tx, err := s.masterTx.Begin()
   229  	if err != nil {
   230  		log.Errorf("[Store][database] database begin err: %s", err.Error())
   231  		return nil, err
   232  	}
   233  
   234  	nt.tx = tx
   235  	return nt, nil
   236  }
   237  
   238  func (s *stableStore) StartTx() (store.Tx, error) {
   239  	tx, err := s.masterTx.Begin()
   240  	if err != nil {
   241  		return nil, err
   242  	}
   243  	return NewSqlDBTx(tx), nil
   244  }
   245  
   246  func (s *stableStore) StartReadTx() (store.Tx, error) {
   247  	tx, err := s.slave.Begin()
   248  	if err != nil {
   249  		return nil, err
   250  	}
   251  	return NewSqlDBTx(tx), nil
   252  }
   253  
   254  // newStore 初始化子类
   255  func (s *stableStore) newStore() {
   256  	s.namespaceStore = &namespaceStore{master: s.master, slave: s.slave}
   257  
   258  	s.serviceStore = &serviceStore{master: s.master, slave: s.slave}
   259  
   260  	s.instanceStore = &instanceStore{master: s.master, slave: s.slave}
   261  
   262  	s.routingConfigStore = &routingConfigStore{master: s.master, slave: s.slave}
   263  
   264  	s.l5Store = &l5Store{master: s.master, slave: s.slave}
   265  
   266  	s.rateLimitStore = &rateLimitStore{master: s.master, slave: s.slave}
   267  
   268  	s.circuitBreakerStore = &circuitBreakerStore{master: s.master, slave: s.slave}
   269  
   270  	s.toolStore = &toolStore{db: s.master}
   271  
   272  	s.userStore = &userStore{master: s.master, slave: s.slave}
   273  
   274  	s.groupStore = &groupStore{master: s.master, slave: s.slave}
   275  
   276  	s.strategyStore = &strategyStore{master: s.master, slave: s.slave}
   277  
   278  	s.faultDetectRuleStore = &faultDetectRuleStore{master: s.master, slave: s.slave}
   279  
   280  	s.configFileGroupStore = &configFileGroupStore{master: s.master, slave: s.slave}
   281  
   282  	s.configFileStore = &configFileStore{master: s.master, slave: s.slave}
   283  
   284  	s.configFileReleaseStore = &configFileReleaseStore{master: s.master, slave: s.slave}
   285  
   286  	s.configFileReleaseHistoryStore = &configFileReleaseHistoryStore{master: s.master, slave: s.slave}
   287  
   288  	s.configFileTemplateStore = &configFileTemplateStore{master: s.master, slave: s.slave}
   289  
   290  	s.clientStore = &clientStore{master: s.master, slave: s.slave}
   291  
   292  	s.routingConfigStoreV2 = &routingConfigStoreV2{master: s.master, slave: s.slave}
   293  
   294  	s.adminStore = newAdminStore(s.master)
   295  }
   296  
   297  func buildEtimeStr(enable bool) string {
   298  	etimeStr := "sysdate()"
   299  	if !enable {
   300  		etimeStr = emptyEnableTime
   301  	}
   302  	return etimeStr
   303  }