deal uncached prepare qps

This commit is contained in:
hebo 2019-09-24 22:40:17 +08:00
parent 92e592ed73
commit a9f0ee309e
6 changed files with 159 additions and 89 deletions

View File

@ -1 +1,3 @@
package capture package capture
const checkCount = 30

View File

@ -106,20 +106,22 @@ func (nc *networkCard) Listen() (receiver chan model.QueryPiece) {
// Listen get a connection. // Listen get a connection.
func (nc *networkCard) listenNormal() { func (nc *networkCard) listenNormal() {
go func() { go func() {
aliveCounter := 0
handler := initEthernetHandlerFromPacpgo() handler := initEthernetHandlerFromPacpgo()
for { for {
var data []byte var data []byte
data, ci, err := handler.ZeroCopyReadPacketData() var ci gopacket.CaptureInfo
if err != nil { var err error
log.Error(err.Error())
time.Sleep(time.Second*3)
continue
}
// capture packets according to a certain probability // capture packets according to a certain probability
capturePacketRate := communicator.GetTCPCapturePacketRate() capturePacketRate := communicator.GetTCPCapturePacketRate()
if capturePacketRate <= 0 { if capturePacketRate <= 0 {
time.Sleep(time.Second*3) time.Sleep(time.Second*1)
aliveCounter += 1
if aliveCounter >= checkCount {
aliveCounter = 0
nc.receiver <- model.NewBaseQueryPiece(localIPAddr, nc.listenPort, capturePacketRate)
}
continue continue
} else if 0 < capturePacketRate && capturePacketRate < 1.0 { } else if 0 < capturePacketRate && capturePacketRate < 1.0 {
@ -130,6 +132,14 @@ func (nc *networkCard) listenNormal() {
} }
} }
aliveCounter = 0
data, ci, err = handler.ZeroCopyReadPacketData()
if err != nil {
log.Error(err.Error())
time.Sleep(time.Second*3)
continue
}
packet := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.NoCopy) packet := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.NoCopy)
m := packet.Metadata() m := packet.Metadata()
m.CaptureInfo = ci m.CaptureInfo = ci

View File

@ -0,0 +1,77 @@
package model
import (
"github.com/pingcap/tidb/util/hack"
"time"
)
// MysqlQueryPiece 查询信息
type MysqlQueryPiece struct {
BaseQueryPiece
SessionID *string `json:"cid"`
ClientHost *string `json:"-"`
ClientPort int `json:"-"`
VisitUser *string `json:"user"`
VisitDB *string `json:"db"`
QuerySQL *string `json:"sql"`
CostTimeInMS int64 `json:"cms"`
}
type PooledMysqlQueryPiece struct {
MysqlQueryPiece
recoverPool *mysqlQueryPiecePool
sliceBufferPool *sliceBufferPool
}
func NewPooledMysqlQueryPiece(
sessionID, clientIP, visitUser, visitDB, clientHost, serverIP *string,
clientPort, serverPort int, throwPacketRate float64, stmtBeginTime int64) (
mqp *PooledMysqlQueryPiece) {
mqp = mqpp.Dequeue()
nowInMS := time.Now().UnixNano() / millSecondUnit
mqp.SessionID = sessionID
mqp.ClientHost = clientIP
mqp.ClientPort = clientPort
mqp.ClientHost = clientHost
mqp.ServerIP = serverIP
mqp.ServerPort = serverPort
mqp.VisitUser = visitUser
mqp.VisitDB = visitDB
mqp.SyncSend = false
mqp.ThrowPacketRate = throwPacketRate
mqp.BeginTime = stmtBeginTime
mqp.CostTimeInMS = nowInMS - stmtBeginTime
mqp.recoverPool = mqpp
mqp.sliceBufferPool = localSliceBufferPool
return
}
func (mqp *MysqlQueryPiece) String() (*string) {
content := mqp.Bytes()
contentStr := hack.String(content)
return &contentStr
}
func (mqp *MysqlQueryPiece) Bytes() (content []byte) {
// content, err := json.Marshal(mqp)
if len(mqp.jsonContent) > 0 {
return mqp.jsonContent
}
mqp.jsonContent = marsharQueryPiece(mqp)
return mqp.jsonContent
}
func (mqp *MysqlQueryPiece) GetSQL() (str *string) {
return mqp.QuerySQL
}
func (pmqp *PooledMysqlQueryPiece) Recovery() {
pmqp.recoverPool.Enqueue(pmqp)
pmqp.sliceBufferPool.Enqueue(pmqp.jsonContent[:0])
pmqp.jsonContent = nil
}

View File

@ -1,13 +1,11 @@
package model package model
import ( import (
"bytes"
"encoding/json"
// "github.com/json-iterator/go" // "github.com/json-iterator/go"
"time" "bytes"
"encoding/json"
"github.com/pingcap/tidb/util/hack" "github.com/pingcap/tidb/util/hack"
"time"
) )
type QueryPiece interface { type QueryPiece interface {
@ -18,28 +16,14 @@ type QueryPiece interface {
Recovery() Recovery()
} }
// MysqlQueryPiece 查询信息 // BaseQueryPiece 查询信息
type MysqlQueryPiece struct { type BaseQueryPiece struct {
SessionID *string `json:"cid"` SyncSend bool `json:"-"`
ClientHost *string `json:"-"` ServerIP *string `json:"sip"`
ClientPort int `json:"-"` ServerPort int `json:"sport"`
SyncSend bool `json:"-"` ThrowPacketRate float64 `json:"tpr"`
ServerIP *string `json:"sip"` BeginTime int64 `json:"bt"`
ServerPort int `json:"sport"` jsonContent []byte `json:"-"`
VisitUser *string `json:"user"`
VisitDB *string `json:"db"`
QuerySQL *string `json:"sql"`
ThrowPacketRate float64 `json:"tpr"`
BeginTime int64 `json:"bt"`
CostTimeInMS int64 `json:"cms"`
jsonContent []byte `json:"-"`
}
type PooledMysqlQueryPiece struct {
MysqlQueryPiece
recoverPool *mysqlQueryPiecePool
sliceBufferPool *sliceBufferPool
} }
const ( const (
@ -47,74 +31,63 @@ const (
) )
var ( var (
mqpp = NewMysqlQueryPiecePool() mqpp = NewMysqlQueryPiecePool()
localSliceBufferPool = NewSliceBufferPool("json cache", 2*1024*1024) localSliceBufferPool = NewSliceBufferPool("json cache", 2*1024*1024)
) )
func NewPooledMysqlQueryPiece( var commonBaseQueryPiece = &BaseQueryPiece{}
sessionID, clientIP, visitUser, visitDB, clientHost, serverIP *string,
clientPort, serverPort int, throwPacketRate float64, stmtBeginTime int64) (
mqp *PooledMysqlQueryPiece) {
mqp = mqpp.Dequeue()
nowInMS := time.Now().UnixNano() / millSecondUnit func NewBaseQueryPiece(
mqp.SessionID = sessionID serverIP *string, serverPort int, throwPacketRate float64) (
mqp.ClientHost = clientIP bqp *BaseQueryPiece) {
mqp.ClientPort = clientPort bqp = commonBaseQueryPiece
mqp.ClientHost = clientHost bqp.ServerIP = serverIP
mqp.ServerIP = serverIP bqp.ServerPort = serverPort
mqp.ServerPort = serverPort bqp.SyncSend = false
mqp.VisitUser = visitUser bqp.ThrowPacketRate = throwPacketRate
mqp.VisitDB = visitDB bqp.BeginTime = time.Now().UnixNano() / millSecondUnit
mqp.SyncSend = false
mqp.ThrowPacketRate = throwPacketRate
mqp.BeginTime = stmtBeginTime
mqp.CostTimeInMS = nowInMS - stmtBeginTime
mqp.recoverPool = mqpp
mqp.sliceBufferPool = localSliceBufferPool
return return
} }
func (mqp *MysqlQueryPiece) String() (*string) { func (bqp *BaseQueryPiece) NeedSyncSend() (bool) {
content := mqp.Bytes() return bqp.SyncSend
}
func (bqp *BaseQueryPiece) SetNeedSyncSend(syncSend bool) {
bqp.SyncSend = syncSend
}
func (bqp *BaseQueryPiece) String() (*string) {
content := bqp.Bytes()
contentStr := hack.String(content) contentStr := hack.String(content)
return &contentStr return &contentStr
} }
func (mqp *MysqlQueryPiece) Bytes() (content []byte) { func (bqp *BaseQueryPiece) Bytes() (content []byte) {
// content, err := json.Marshal(mqp) // content, err := json.Marshal(bqp)
if len(mqp.jsonContent) > 0 { if bqp.jsonContent != nil && len(bqp.jsonContent) > 0 {
return mqp.jsonContent return bqp.jsonContent
} }
bqp.jsonContent = marsharQueryPiece(bqp)
return bqp.jsonContent
}
func (bqp *BaseQueryPiece) GetSQL() (*string) {
return nil
}
func (bqp *BaseQueryPiece) Recovery() {
}
func marsharQueryPiece(qp interface{}) []byte {
var cacheBuffer = localSliceBufferPool.Dequeue() var cacheBuffer = localSliceBufferPool.Dequeue()
buffer := bytes.NewBuffer(cacheBuffer) buffer := bytes.NewBuffer(cacheBuffer)
err := json.NewEncoder(buffer).Encode(mqp) err := json.NewEncoder(buffer).Encode(qp)
if err != nil { if err != nil {
mqp.jsonContent = []byte(err.Error()) return []byte(err.Error())
} else {
mqp.jsonContent = buffer.Bytes()
} }
return mqp.jsonContent return buffer.Bytes()
}
func (mqp *MysqlQueryPiece) GetSQL() (str *string) {
return mqp.QuerySQL
}
func (mqp *MysqlQueryPiece) NeedSyncSend() (bool) {
return mqp.SyncSend
}
func (mqp *MysqlQueryPiece) SetNeedSyncSend(syncSend bool) {
mqp.SyncSend = syncSend
}
func (pmqp *PooledMysqlQueryPiece) Recovery() {
pmqp.recoverPool.Enqueue(pmqp)
pmqp.sliceBufferPool.Enqueue(pmqp.jsonContent[:0])
pmqp.jsonContent = nil
} }

View File

@ -19,6 +19,8 @@ var (
coverRangePool = NewCoveragePool() coverRangePool = NewCoveragePool()
localStmtCache = model.NewSliceBufferPool("statement cache", MaxMysqlPacketLen) localStmtCache = model.NewSliceBufferPool("statement cache", MaxMysqlPacketLen)
PrepareStatement = []byte(":prepare")
) )
func init() { func init() {

View File

@ -258,7 +258,8 @@ func (ms *MysqlSession) GenerateQueryPiece() (qp model.QueryPiece) {
case ComStmtPrepare: case ComStmtPrepare:
mqp = ms.composeQueryPiece() mqp = ms.composeQueryPiece()
querySQLInBytes = ms.cachedStmtBytes[1:] querySQLInBytes = make([]byte, len(ms.cachedStmtBytes[1:]))
copy(querySQLInBytes, ms.cachedStmtBytes[1:])
querySQL := hack.String(querySQLInBytes) querySQL := hack.String(querySQLInBytes)
mqp.QuerySQL = &querySQL mqp.QuerySQL = &querySQL
ms.cachedPrepareStmt[ms.prepareInfo.prepareStmtID] = querySQLInBytes ms.cachedPrepareStmt[ms.prepareInfo.prepareStmtID] = querySQLInBytes
@ -267,10 +268,15 @@ func (ms *MysqlSession) GenerateQueryPiece() (qp model.QueryPiece) {
case ComStmtExecute: case ComStmtExecute:
prepareStmtID := bytesToInt(ms.cachedStmtBytes[1:5]) prepareStmtID := bytesToInt(ms.cachedStmtBytes[1:5])
mqp = ms.composeQueryPiece() mqp = ms.composeQueryPiece()
querySQLInBytes = ms.cachedPrepareStmt[prepareStmtID] var ok bool
querySQLInBytes, ok = ms.cachedPrepareStmt[prepareStmtID]
if !ok {
querySQLInBytes = PrepareStatement
}
querySQL := hack.String(querySQLInBytes) querySQL := hack.String(querySQLInBytes)
mqp.QuerySQL = &querySQL mqp.QuerySQL = &querySQL
log.Debugf("execute prepare statement:%d", prepareStmtID)
// log.Debugf("execute prepare statement:%d", prepareStmtID)
case ComStmtClose: case ComStmtClose:
prepareStmtID := bytesToInt(ms.cachedStmtBytes[1:5]) prepareStmtID := bytesToInt(ms.cachedStmtBytes[1:5])