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 := utils.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() }
// // Load Balance如何运维呢? // 1. 在服务提供方,会会启动Load Balance, 它只负责本机器的某个指定服务的lb // 2. 正常情况下,不能被轻易杀死 // 3. 需要考虑 graceful stop, 在死之前告知所有的proxy,如何告知呢? TODO // // func main() { args, err := docopt.Parse(usage, nil, true, "Chunyu RPC Load Balance v0.1", true) if err != nil { log.Println(err) os.Exit(1) } var maxFileFrag = 2 var maxFragSize int64 = bytesize.GB * 1 if s, ok := args["--log-filesize"].(string); ok && s != "" { v, err := bytesize.Parse(s) if err != nil { log.PanicErrorf(err, "invalid max log file size = %s", s) } maxFragSize = v } // set output log file if s, ok := args["-L"].(string); ok && s != "" { f, err := log.NewRollingFile(s, maxFileFrag, maxFragSize) 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) } var backendAddr, frontendAddr, zkAddr, productName, serviceName string // set config file if args["-c"] != nil { configFile := args["-c"].(string) conf, err := utils.LoadConf(configFile) if err != nil { log.PanicErrorf(err, "load config failed") } productName = conf.ProductName if conf.FrontHost == "" { fmt.Println("FrontHost: ", conf.FrontHost, ", Prefix: ", conf.IpPrefix) if conf.IpPrefix != "" { conf.FrontHost = utils.GetIpWithPrefix(conf.IpPrefix) } } if conf.FrontPort != "" && conf.FrontHost != "" { frontendAddr = fmt.Sprintf("tcp://%s:%s", conf.FrontHost, conf.FrontPort) } backendAddr = conf.BackAddr serviceName = conf.Service zkAddr = conf.ZkAddr config.VERBOSE = conf.Verbose } else { productName = "" zkAddr = "" } if s, ok := args["--product"].(string); ok && s != "" { productName = s } else if productName == "" { // 既没有config指定,也没有命令行指定,则报错 log.PanicErrorf(err, "Invalid ProductName: %s", s) } if s, ok := args["--zk"].(string); ok && s != "" { zkAddr = s } else if zkAddr == "" { log.PanicErrorf(err, "Invalid zookeeper address: %s", s) } if s, ok := args["--service"].(string); ok && s != "" { serviceName = s } else if serviceName == "" { log.PanicErrorf(err, "Invalid ServiceName: %s", s) } if s, ok := args["--baddr"].(string); ok && s != "" { backendAddr = s } else if backendAddr == "" { log.PanicErrorf(err, "Invalid backend address: %s", s) } if s, ok := args["--faddr"].(string); ok && s != "" { frontendAddr = s } else if frontendAddr == "" { // log.PanicErrorf(err, "Invalid frontend address: %s", s) } // 正式的服务 mainBody(zkAddr, productName, serviceName, frontendAddr, backendAddr) }
// // Proxy关闭,则整个机器就OVER, 需要考虑将整个机器下线 // 因此Proxy需要设计的非常完美,不要轻易地被杀死,或自杀 // func main() { // 解析输入参数 args, err := docopt.Parse(usage, nil, true, "Chunyu RPC Local Proxy v0.1", true) if err != nil { log.Println(err) os.Exit(1) } var maxFileFrag = 2 var maxFragSize int64 = bytesize.GB * 1 if s, ok := args["--log-filesize"].(string); ok && s != "" { v, err := bytesize.Parse(s) if err != nil { log.PanicErrorf(err, "invalid max log file size = %s", s) } maxFragSize = v } // set output log file if s, ok := args["-L"].(string); ok && s != "" { f, err := log.NewRollingFile(s, maxFileFrag, maxFragSize) 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) } var zkAddr, frontAddr, productName string // 从config文件中读取数据 if args["-c"] != nil { configFile := args["-c"].(string) conf, err := utils.LoadConf(configFile) if err != nil { log.PanicErrorf(err, "load config failed") } productName = conf.ProductName frontAddr = conf.ProxyAddr zkAddr = conf.ZkAddr config.VERBOSE = conf.Verbose config.PROFILE = conf.Profile } else { productName = "" zkAddr = "" } if s, ok := args["--product"].(string); ok && s != "" { productName = s } else if productName == "" { log.PanicErrorf(err, "Invalid ProductName: %s", s) } if s, ok := args["--zk"].(string); ok && s != "" { zkAddr = s } else if zkAddr == "" { log.PanicErrorf(err, "Invalid zookeeper address: %s", s) } if s, ok := args["--faddr"].(string); ok && s != "" { frontAddr = s } else if frontAddr == "" { log.PanicErrorf(err, "Invalid Proxy address: %s", s) } // 正式的服务 mainBody(productName, frontAddr, zkAddr) }