一、codis-proxy启动http服务接受集群命令
func newApiServer(p *Proxy) http.Handler {
m := martini.New() //go-martini web开发框架
m.Use(martini.Recovery())
m.Use(render.Renderer())
m.Use(func(w http.ResponseWriter, req *http.Request, c martini.Context) {
path := req.URL.Path
if req.Method != "GET" && strings.HasPrefix(path, "/api/") {
var remoteAddr = req.RemoteAddr
var headerAddr string
for _, key := range []string{
"X-Real-IP", "X-Forwarded-For"} {
if val := req.Header.Get(key)
headerAddr = val
break
}
}
log.Warnf("[%p] API call %s from %s [%s]", p, path, remoteAddr, headerAddr)
}
c.Next()
})
m.Use(gzip.All())
m.Use(func(c martini.Context, w http.ResponseWriter) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
})
api := &apiServer{proxy: p}
r := martini.NewRouter()
r.Get("/", func(r render.Render) {
r.Redirect("/proxy")
})
r.Any("/debug/**", func(w http.ResponseWriter, req *http.Request) {
http.DefaultServeMux.ServeHTTP(w, req)
})
r.Group("/proxy", func(r martini.Router) {
r.Get("", api.Overview)
r.Get("/model", api.Model)
r.Get("/stats", api.StatsNoXAuth)
r.Get("/slots", api.SlotsNoXAuth)
})
r.Group("/api/proxy", func(r martini.Router) {
r.Get("/model", api.Model)
r.Get("/xping/:xauth", api.XPing)
r.Get("/stats/:xauth", api.Stats)
r.Get("/stats/:xauth/:flags", api.Stats)
r.Get("/slots/:xauth", api.Slots)
r.Put("/start/:xauth", api.Start)
r.Put("/stats/reset/:xauth", api.ResetStats)
r.Put("/forcegc/:xauth", api.ForceGC)
r.Put("/shutdown/:xauth", api.Shutdown)
r.Put("/loglevel/:xauth/:value", api.LogLevel)
r.Put("/fillslots/:xauth", binding.Json([]*models.Slot{}), api.FillSlots)
r.Put("/sentinels/:xauth", binding.Json(models.Sentinel{}), api.SetSentinels)
r.Put("/sentinels/:xauth/rewatch", api.RewatchSentinels)
})
m.MapTo(r, (*martini.Routes)(nil))
m.Action(r.Handle)
return m
}
- apiServer提供http服务,包括服务端和客户端Api,当codis-proxy启动之后启动http服务等待集群配置命令的请求,具体的的Api路径在$GOPATH/src/github.com/CodisLabs/codis/pkg/proxy/proxy_api.go;
二、codis-proxy启动redis协议服务处理redis命令
func NewSession(sock net.Conn, config *Config) *Session {
c := redis.NewConn(sock,
config.SessionRecvBufsize.AsInt(),
config.SessionSendBufsize.AsInt(),
)
c.ReaderTimeout = config.SessionRecvTimeout.Duration()
c.WriterTimeout = config.SessionSendTimeout.Duration()
c.SetKeepAlivePeriod(config.SessionKeepAlivePeriod.Duration())
s := &Session{
Conn: c, config: config, //会话的核心结果
CreateUnix: time.Now().Unix(),
}
s.stats.opmap = make(map[string]*opStats, 16)
log.Infof("session [%p] create: %s", s, s)
return s
}
func (s *Session) Start(d *Router) {
s.start.Do(func() {
if int(incrSessions()) > s.config.ProxyMaxClients {
go func() {
s.Conn