虽然dashboard负责对集群的实际操作,但是用户的最直观操作,都是来自于fe的。这一节我们就来讲fe的启动,没有proxy和dashboard那么复杂。
首先,启动的时候指定fe的监听端口,这个就是我们最后通过浏览器打开fe的端口
--listen=0.0.0.0:18090
然后根据系统参数找到assets文件夹目录,再在这个目录下寻找index.html,没错,就是浏览器中看到的html。如果在本地启动的时候这一步报错,assets目录下找不到index.html,就自己手动写死assets的地址即可。
indexFile := filepath.Join(assets, "index.html")
if _, err := os.Stat(indexFile); err != nil {
log.PanicErrorf(err, "get stat of %s failed", indexFile)
}
接下来,找启动的时候配置的codis.json。通过codis.json连接到dashboard,fe就算是和集群关联起来了。
if d["--dashboard-list"] != nil {
file := utils.ArgumentMust(d, "--dashboard-list")
//只有一个字符串属性,指向codis.json的位置
loader = &StaticLoader{file}
log.Warnf("set --dashboard-list = %s", file)
} .....
//router是一个ReverseProxy结构,后面很多操作都是关于这个router的
router := NewReverseProxy(loader)
type ReverseProxy struct {
sync.Mutex
loadAt time.Time
loader ConfigLoader
//这个httputil.ReverseProxy,相当于一个请求的handler,收到客户端请求,将请求转发给另一个服务器,再将响应发回给客户端
routes map[string]*httputil.ReverseProxy
}
func NewReverseProxy(loader ConfigLoader) *ReverseProxy {
r := &ReverseProxy{}
r.loader = loader
//到目前为止只是把routes的结构初始化好,里面还是空的
r.routes = make(map[string]*httputil.ReverseProxy)
return r
}
使用martini框架,新建路由和handler
m := martini.New()
m.Use(martini.Recovery())
m.Use(render.Renderer())
m.Use(martini.Static(assets, martini.StaticOptions{SkipLogging: true}))
//新建一个路由实例
r := martini.NewRouter()
r.Get("/list", func() (int, string) {
//遍历ReverseProxy的routes,将键值组成字符串切片
names := router.GetNames()
sort.Sort(sort.StringSlice(names))
return rpc.ApiResponseJson(names)
})
r.Any("/**", func(w http.ResponseWriter, req *http.Request) {
//发送请求,得到对应的响应
name := req.URL.Query().Get("forward")
//在router的routes属性中。取出name对应的ReverseProxy
if p := router.GetProxy(name); p != nil {
p.ServeHTTP(w, req)
} else {
w.WriteHeader(http.StatusForbidden)
}
})
m.MapTo(r, (*martini.Routes)(nil))
m.Action(r.Handle)
最终我们得到了一个拥有完整规则的请求处理器handler,就是m。下一步,监听启动端口,新建路由表并将路由表指向刚才的martini框架的Router。最后一步,hs.Serve(l)这里,服务器接收指定监听器收到的请求,并为每个请求新建goroutine。goroutine负责读取并调用srv.Handler对请求进行相应
//监听10890端口,得到的l是一个Listener
l, err := net.Listen("tcp", listen)
//新建路由表
h := http.NewServeMux()
h.Handle("/", m)
hs := &http.Server{Handler: h}
if err := hs.Serve(l); err != nil {
log.PanicErrorf(err, "serve %s failed", listen)
}
补充一下go语言路由表的知识,路由表实际就是一个map。这个map的键就是路径,比如本例的”/”,值就是对应的handler,比如本例中的m。
go语言web服务器的工作流程如下:
- 创建并循环监听listen socket。
- 监听器监听到新的请求,并创建网络连接conn,然后开启一个goroutine负责处理该链接。
- 从链接根据请求参数构造出http.Request对象,然后根据请求路径在路由表中查找,把请求转发给对应的应用层的处理函数。
- 处理函数进行处理,并将响应返回给用户
- 应用层处理完该链接请求后关闭该链接,如果是http alive则不关闭
到这里,fe也已经启动成功,后面只需要用户对fe进行操作即可。
如果你前面已经成功启动了dashboard和proxy,打开浏览器输入下图中的地址,就能看到完整的页面了
说明
如有转载,请注明出处
http://blog.csdn.net/antony9118/article/details/76071846