func GetExecutorPath() string { filedirectory := filepath.Dir(os.Args[0]) execPath, err := filepath.Abs(filedirectory) if err != nil { log.PanicErrorf(err, "get executor path failed") } return execPath }
func (top *Topology) InitZkConn() { var err error // 连接到zk // 30s的timeout top.ZkConn, err = zkhelper.ConnectToZk(top.zkAddr, 30) // 参考: Codis的默认配置 if err != nil { log.PanicErrorf(err, "init failed") } }
// Router负责监听zk中服务列表的变化 func (bk *Router) WatchServices() { var evtbus chan interface{} = make(chan interface{}, 2) // 1. 保证Service目录存在,否则会报错 servicesPath := bk.topo.ProductServicesPath() _, e1 := bk.topo.CreateDir(servicesPath) if e1 != nil { log.PanicErrorf(e1, "Zk Path Create Failed: %s", servicesPath) } go func() { for true { // 无限监听 services, err := bk.topo.WatchChildren(servicesPath, evtbus) if err == nil { bk.serviceLock.Lock() // 保证数据更新是有效的 oldServices := bk.services bk.services = make(map[string]*BackService, len(services)) for _, service := range services { log.Println("Found Service: ", Magenta(service)) back, ok := oldServices[service] if ok { bk.services[service] = back delete(oldServices, service) } else { bk.addBackService(service) } } if len(oldServices) > 0 { for _, conn := range oldServices { // 标记下线(现在应该不会有新的请求,最多只会处理一些收尾的工作 conn.Stop() } } bk.serviceLock.Unlock() // 等待事件 <-evtbus } else { log.ErrorErrorf(err, "zk watch error: %s, error: %v\n", servicesPath, err) time.Sleep(time.Duration(5) * time.Second) } } }() // 读取zk, 等待 log.Println("ProductName: ", Magenta(bk.topo.ProductName)) }
func RpcMain(binaryName string, serviceDesc string, configCheck ConfigCheck, serverFactory ServerFactorory, buildDate string, gitVersion string) { // 1. 准备解析参数 usage = fmt.Sprintf(usage, binaryName, binaryName) version := fmt.Sprintf("Version: %s\nBuildDate: %s\nDesc: %s\nAuthor: [email protected]", gitVersion, buildDate, serviceDesc) args, err := docopt.Parse(usage, nil, true, version, true) if err != nil { fmt.Println(err) os.Exit(1) } if s, ok := args["-V"].(bool); ok && s { fmt.Println(Green(version)) os.Exit(1) } // 这就是为什么 Codis 傻乎乎起一个 http server的目的 if s, ok := args["--profile-addr"].(string); ok && len(s) > 0 { go func() { log.Printf(Red("Profile Address: %s"), s) log.Println(http.ListenAndServe(s, nil)) }() } // 2. 解析Log相关的配置 log.SetLevel(log.LEVEL_INFO) var maxKeepDays int = 3 if s, ok := args["--log-keep-days"].(string); ok && s != "" { v, err := strconv.ParseInt(s, 10, 32) if err != nil { log.PanicErrorf(err, "invalid max log file keep days = %s", s) } maxKeepDays = int(v) } // set output log file if s, ok := args["-L"].(string); ok && s != "" { f, err := log.NewRollingFile(s, maxKeepDays) if err != nil { log.PanicErrorf(err, "open rolling log file failed: %s", s) } else { defer f.Close() log.StdLog = log.New(f, "") } } log.SetLevel(log.LEVEL_INFO) log.SetFlags(log.Flags() | log.Lshortfile) // set log level if s, ok := args["--log-level"].(string); ok && s != "" { SetLogLevel(s) } // 没有就没有 workDir, _ := args["--work-dir"].(string) codeUrlVersion, _ := args["--code-url-version"].(string) if len(workDir) == 0 { workDir, _ = os.Getwd() } log.Printf("WorkDir: %s, CodeUrl: %s, Wd: %s", workDir, codeUrlVersion) // 3. 解析Config configFile := args["-c"].(string) conf, err := LoadConf(configFile) if err != nil { log.PanicErrorf(err, "load config failed") } // 额外的配置信息 conf.WorkDir = workDir conf.CodeUrlVersion = codeUrlVersion if configCheck != nil { configCheck(conf) } else { log.Panic("No Config Check Given") } // 每次启动的时候都打印版本信息 log.Infof(Green("-----------------\n%s\n--------------------------------------------------------------------"), version) // 启动服务 server := serverFactory(conf) server.Run() }
func LoadConf(configFile string) (*Config, error) { c := cfg.NewCfg(configFile) if err := c.Load(); err != nil { log.PanicErrorf(err, "load config '%s' failed", configFile) } conf := &Config{} // 读取product conf.ProductName, _ = c.ReadString("product", "test") if len(conf.ProductName) == 0 { log.Panicf("invalid config: product entry is missing in %s", configFile) } // 读取zk conf.ZkAddr, _ = c.ReadString("zk", "") if len(conf.ZkAddr) == 0 { log.Panicf("invalid config: need zk entry is missing in %s", configFile) } conf.ZkAddr = strings.TrimSpace(conf.ZkAddr) loadConfInt := func(entry string, defInt int) int { v, _ := c.ReadInt(entry, defInt) if v < 0 { log.Panicf("invalid config: read %s = %d", entry, v) } return v } conf.ZkSessionTimeout = loadConfInt("zk_session_timeout", 30) conf.Verbose = loadConfInt("verbose", 0) == 1 conf.Service, _ = c.ReadString("service", "") conf.Service = strings.TrimSpace(conf.Service) conf.FrontHost, _ = c.ReadString("front_host", "") conf.FrontHost = strings.TrimSpace(conf.FrontHost) conf.FrontPort, _ = c.ReadString("front_port", "") conf.FrontPort = strings.TrimSpace(conf.FrontPort) conf.FrontSock, _ = c.ReadString("front_sock", "") conf.FrontSock = strings.TrimSpace(conf.FrontSock) // 配置文件中使用的是相对路径,在注册到zk时,需要还原成为绝对路径 if len(conf.FrontSock) > 0 { dir, _ := os.Getwd() conf.FrontSock = path.Clean(path.Join(dir, conf.FrontSock)) } conf.IpPrefix, _ = c.ReadString("ip_prefix", "") conf.IpPrefix = strings.TrimSpace(conf.IpPrefix) // 注意先后顺序: // FrontHost, FrontPort, IpPrefix之后才能计算FrontendAddr conf.FrontendAddr = conf.getFrontendAddr(conf.FrontHost, conf.IpPrefix, conf.FrontPort) conf.BackAddr, _ = c.ReadString("back_address", "") conf.BackAddr = strings.TrimSpace(conf.BackAddr) conf.ProxyAddr, _ = c.ReadString("proxy_address", "") conf.ProxyAddr = strings.TrimSpace(conf.ProxyAddr) conf.FalconClient, _ = c.ReadString("falcon_client", "") profile, _ := c.ReadInt("profile", 0) conf.Profile = profile == 1 return conf, nil }