最近工作总结(一)

2017/01/10 Work
ES 慢查询优化

对搜索客户手机号码的ES慢查询进行优化。由于表的记录已经达到一定数量级,对手机号码进行char_split 的分词方法, 会产生性能问题,因为该分词方法会把手机号码进行拆分组合,这里很耗时。 优化方法:用正则表达式检验出传的参数是手机号码,不使用char_split分词查询,而是使用完全匹配的方式进行过滤

gorm 的连接池方案

Go项目中使用了gorm,打算使用连接池。定义了一个全局变量:

var MyDB *gorm.DB

func init() {
    var err error
    dsn := fmt.Sprintf(
      "%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local",
      config.DBUser(),
      config.DBPassword(),
      config.DBHost(),
      config.DBPort(),
      config.DBName(),
    )

    MyDB, err = gorm.Open("mysql", dsn)
    // 连接池
     if err == nil {
       MyDB.DB().SetMaxIdleConns(20)
       MyDB.DB().SetMaxOpenConns(50)
       MyDB.DB().Ping()
       MyDB.LogMode(true)
     } else {
       log.Panic("Gorm Open Error")
     }

需要使用到数据库的地方,则导入该包,然后直接使用这个全局变量就可以了。这样就只初始化了一个数据库实例,可以给需要用的地方使用。 不用每次都新建数据库实例的连接 使用的地方,不要使用Close()。 因为这样会把这个唯一的数据库实例给关了。 关于数据库连接池,配置好后,sql查询会自动的使用这个连接池。对产生rows的sql查询需要手动rows.Close(),其他查询不需要。 使用show processlist 命令观察,明白了Go MySQL包连接池的原理。 首先,会创建一个连接池,并且其中创建一个连接。如果这个连接足够应对服务器,则不会有新的连接被创建,当服务器负载或并发变大, 连接池会创建新的连接,一直可以创建到最大连接数量,这里是500.当这一轮访问过去了,服务器负载变小了。数据库的连接会被关闭, 但不是全部关闭,而是保留连接池配置的连接数量,这里是200.也就是连接池中有200个连接提供服务。要注意的是,gorm最大连接数配置不能超过 MySQL中设置的最大连接数,当超过时,会以MySQL中的设置为准。 也就是 实际的最大连接数 <= gorm配置的最大连接数 <= MySQL配置的最大连接数

使用Go context
 body, err := ioutil.ReadAll(r.Body)
 CheckErr(err, w)
 params := string(body)
 url := r.URL.String()
 log.Println("URL Info: ", r.Method, r.URL.Scheme, url, " from: ", r.RemoteAddr)
 if params != "" {
    ctx := context.WithValue(r.Context(), "params", body) // Use context to pass params to action
   log.Println("Request Params: ", params)
   next.ServeHTTP(w, r.WithContext(ctx))
 } else {
   next.ServeHTTP(w, r)
 }

 body := req.Context().Value("params").([]byte)

ioutil.ReadAll(r.Body) 只能读取一次,这一次读完了,相同的请求再读就是空的了(比如在下一个middleware中读取时)

所以,用context的方法,将这个值进行临时保存和传递

Magic Number

避免代码中出现Magic Number。定义合理的常量来代替Magic Number 的出现

Don’t use DateTime.parse
T = "2017-01-20 12:00:00"
DateTime.parse(T)  #=> Fri, 20 Jan 2017 12:00:00 +0000
Time.parse(T)      #=> 2017-01-20 12:00:00 +0800

DateTime.parse 解析的结果没有时区,存到数据库的话,会多加8个小时(在中国),这样在数据库的值就变为了“2017-01-20 20:00:00” 并不是我们想要的结果,如果用Time.parse 的话,就会帮你自动转时区了

Search

    Table of Contents