// Start architecture func Start(a *archV0r1) { var r string if archaius.Conf.Population < 1 { log.Fatal("architecture: can't create less than 1 microservice") } else { log.Printf("architecture: scaling to %v%%", archaius.Conf.Population) } asgard.CreateChannels() asgard.CreateEureka() // service registries for each zone for _, s := range a.Services { log.Printf("Starting: %v\n", s) r = asgard.Create(s.Name, s.Gopackage, s.Regions*archaius.Conf.Regions, s.Count*archaius.Conf.Population/100, s.Dependencies...) } asgard.Run(r, a.Victim) // run the last service in the list, and point chaos monkey at the victim }
// main handles command line flags and starts up an architecture func main() { flag.StringVar(&archaius.Conf.Arch, "a", "netflixoss", "Architecture to create or read, fsm, lamp, migration, netflixoss or json/????_arch.json") flag.IntVar(&archaius.Conf.Population, "p", 100, "Pirate population for fsm or scale factor % for netflixoss etc.") flag.IntVar(&duration, "d", 10, "Simulation duration in seconds") flag.IntVar(&archaius.Conf.Regions, "w", 1, "Wide area regions") flag.BoolVar(&graphmlEnabled, "g", false, "Enable GraphML logging of nodes and edges to <arch>.graphml") flag.BoolVar(&graphjsonEnabled, "j", false, "Enable GraphJSON logging of nodes and edges to <arch>.json") flag.BoolVar(&archaius.Conf.Msglog, "m", false, "Enable console logging of every message") flag.BoolVar(&reload, "r", false, "Reload json/<arch>.json to setup architecture") flag.BoolVar(&archaius.Conf.Collect, "c", false, "Collect metrics to json/<arch>_metrics.json and via http:") flag.IntVar(&archaius.Conf.StopStep, "s", 0, "Stop creating microservices at this step, 0 = don't stop") flag.StringVar(&archaius.Conf.EurekaPoll, "u", "1s", "Polling interval for Eureka name service") flag.BoolVar(&archaius.Conf.Filter, "f", false, "Filter output names to simplify graph") flag.IntVar(&cpucount, "cpus", runtime.NumCPU(), "Number of CPUs for Go runtime") runtime.GOMAXPROCS(cpucount) var cpuprofile = flag.String("cpuprofile", "", "Write cpu profile to file") flag.Parse() if *cpuprofile != "" { f, err := os.Create(*cpuprofile) if err != nil { log.Fatal(err) } pprof.StartCPUProfile(f) defer pprof.StopCPUProfile() } if archaius.Conf.Collect { collect.Serve(8123) // start web server at port } if graphjsonEnabled || graphmlEnabled { if graphjsonEnabled { archaius.Conf.GraphjsonFile = archaius.Conf.Arch } if graphmlEnabled { archaius.Conf.GraphmlFile = archaius.Conf.Arch } // make a buffered channel so logging can start before edda is scheduled edda.Logchan = make(chan gotocol.Message, 100) } archaius.Conf.RunDuration = time.Duration(duration) * time.Second // start up the selected architecture go edda.Start(archaius.Conf.Arch + ".edda") // start edda first if reload { asgard.Run(asgard.Reload(archaius.Conf.Arch), "") } else { switch archaius.Conf.Arch { case "fsm": fsm.Start() //case "netflixoss": replaced by json_arch/netflixoss_arch.json // netflixoss.Start() //case "lamp": replaced by json_arch/lamp_arch.json // lamp.Start() case "migration": migration.Start() // step by step from lamp to netflixoss default: a := architecture.ReadArch(archaius.Conf.Arch) if a == nil { log.Fatal("Architecture " + archaius.Conf.Arch + " isn't recognized") } else { architecture.Start(a) } } } log.Println("spigo: complete") // stop edda if it's running and wait for edda to flush messages if edda.Logchan != nil { close(edda.Logchan) } edda.Wg.Wait() flow.Shutdown() }
// Start lamp to netflixoss step by step migration func Start() { regions := archaius.Conf.Regions if archaius.Conf.Population < 1 { log.Fatal("migration: can't create less than 1 microservice") } else { log.Printf("migration: scaling to %v%%", archaius.Conf.Population) } // Build the configuration step by step // start mysql data store layer, which connects to itself mysqlcount := 2 sname := "rds-mysql" // start memcached layer, only one per region mname := "memcache" mcount := 1 if archaius.Conf.StopStep >= 3 { // start evcache layer, one per zone mname = "evcache" mcount = 3 } // priam managed Cassandra cluster, turtle because it's used to configure other clusters priamCassandracount := 12 * archaius.Conf.Population / 100 cname := "cassTurtle" // staash data access layer connects to mysql master and slave, and evcache staashcount := 6 * archaius.Conf.Population / 100 tname := "turtle" // php business logic, we can create a network of simple services from the karyon package phpcount := 9 * archaius.Conf.Population / 100 pname := "php" // some node microservice logic, we can create a network of simple services from the karyon package nodecount := 9 * archaius.Conf.Population / 100 nname := "node" // zuul api proxies and insert between elb and php zuulcount := 9 * archaius.Conf.Population / 100 zuname := "wwwproxy" // AWS elastic load balancer elbname := "www-elb" // DNS endpoint dns := "www" switch archaius.Conf.StopStep { case 0: // basic LAMP asgard.CreateChannels() asgard.CreateEureka() // service registries for each zone asgard.Create(sname, asgard.StorePkg, regions, mysqlcount, sname) asgard.Create(pname, asgard.MonolithPkg, regions, phpcount, sname) asgard.Create(elbname, asgard.ElbPkg, regions, 0, pname) case 1: // basic LAMP with memcache asgard.CreateChannels() asgard.CreateEureka() // service registries for each zone asgard.Create(sname, asgard.StorePkg, regions, mysqlcount, sname) asgard.Create(mname, asgard.StorePkg, regions, mcount) asgard.Create(pname, asgard.MonolithPkg, regions, phpcount, sname, mname) asgard.Create(elbname, asgard.ElbPkg, regions, 0, pname) case 2: // LAMP with zuul and memcache asgard.CreateChannels() asgard.CreateEureka() // service registries for each zone asgard.Create(sname, asgard.StorePkg, regions, mysqlcount, sname) asgard.Create(mname, asgard.StorePkg, regions, mcount) asgard.Create(pname, asgard.MonolithPkg, regions, phpcount, sname, mname) asgard.Create(zuname, asgard.ZuulPkg, regions, zuulcount, pname) asgard.Create(elbname, asgard.ElbPkg, regions, 0, zuname) case 3: // LAMP with zuul and staash and evcache asgard.CreateChannels() asgard.CreateEureka() // service registries for each zone asgard.Create(sname, asgard.StorePkg, regions, mysqlcount, sname) asgard.Create(mname, asgard.StorePkg, regions, mcount) asgard.Create(tname, asgard.StaashPkg, regions, staashcount, sname, mname) asgard.Create(pname, asgard.KaryonPkg, regions, phpcount, tname) asgard.Create(zuname, asgard.ZuulPkg, regions, zuulcount, pname) asgard.Create(elbname, asgard.ElbPkg, regions, 0, zuname) case 4: // added node microservice asgard.CreateChannels() asgard.CreateEureka() // service registries for each zone asgard.Create(sname, asgard.StorePkg, regions, mysqlcount, sname) asgard.Create(mname, asgard.StorePkg, regions, mcount) asgard.Create(tname, asgard.StaashPkg, regions, staashcount, sname, mname, cname) asgard.Create(pname, asgard.KaryonPkg, regions, phpcount, tname) asgard.Create(nname, asgard.KaryonPkg, regions, nodecount, tname) asgard.Create(zuname, asgard.ZuulPkg, regions, zuulcount, pname, nname) asgard.Create(elbname, asgard.ElbPkg, regions, 0, zuname) case 5: // added cassandra alongside mysql asgard.CreateChannels() asgard.CreateEureka() // service registries for each zone asgard.Create(cname, asgard.PriamCassandraPkg, regions, priamCassandracount, cname) asgard.Create(sname, asgard.StorePkg, regions, mysqlcount, sname) asgard.Create(mname, asgard.StorePkg, regions, mcount) asgard.Create(tname, asgard.StaashPkg, regions, staashcount, sname, mname, cname) asgard.Create(pname, asgard.KaryonPkg, regions, phpcount, tname) asgard.Create(nname, asgard.KaryonPkg, regions, nodecount, tname) asgard.Create(zuname, asgard.ZuulPkg, regions, zuulcount, pname, nname) asgard.Create(elbname, asgard.ElbPkg, regions, 0, zuname) case 6: // removed mysql so that multi-region will work properly asgard.CreateChannels() asgard.CreateEureka() // service registries for each zone asgard.Create(cname, asgard.PriamCassandraPkg, regions, priamCassandracount, cname) asgard.Create(mname, asgard.StorePkg, regions, mcount) asgard.Create(tname, asgard.StaashPkg, regions, staashcount, mname, cname) asgard.Create(pname, asgard.KaryonPkg, regions, phpcount, tname) asgard.Create(nname, asgard.KaryonPkg, regions, nodecount, tname) asgard.Create(zuname, asgard.ZuulPkg, regions, zuulcount, pname, nname) asgard.Create(elbname, asgard.ElbPkg, regions, 0, zuname) case 7: // set two regions with disconnected priamCassandra regions = 2 archaius.Conf.Regions = regions asgard.CreateChannels() asgard.CreateEureka() // service registries for each zone asgard.Create(cname, asgard.PriamCassandraPkg, regions, priamCassandracount, cname) asgard.Create(mname, asgard.StorePkg, regions, mcount) asgard.Create(tname, asgard.StaashPkg, regions, staashcount, mname, cname) asgard.Create(pname, asgard.KaryonPkg, regions, phpcount, tname) asgard.Create(nname, asgard.KaryonPkg, regions, nodecount, tname) asgard.Create(zuname, asgard.ZuulPkg, regions, zuulcount, pname, nname) asgard.Create(elbname, asgard.ElbPkg, regions, 0, zuname) case 8: // set two regions with connected priamCassandra regions = 2 archaius.Conf.Regions = regions asgard.CreateChannels() asgard.CreateEureka() // service registries for each zone asgard.Create(cname, asgard.PriamCassandraPkg, regions, priamCassandracount, "eureka", cname) asgard.Create(mname, asgard.StorePkg, regions, mcount) asgard.Create(tname, asgard.StaashPkg, regions, staashcount, mname, cname) asgard.Create(pname, asgard.KaryonPkg, regions, phpcount, tname) asgard.Create(nname, asgard.KaryonPkg, regions, nodecount, tname) asgard.Create(zuname, asgard.ZuulPkg, regions, zuulcount, pname, nname) asgard.Create(elbname, asgard.ElbPkg, regions, 0, zuname) case 9: // set three regions with disconnected priamCassandra regions = 3 archaius.Conf.Regions = regions asgard.CreateChannels() asgard.CreateEureka() // service registries for each zone asgard.Create(cname, asgard.PriamCassandraPkg, regions, priamCassandracount, "eureka", cname) asgard.Create(mname, asgard.StorePkg, regions, mcount) asgard.Create(tname, asgard.StaashPkg, regions, staashcount, mname, cname) asgard.Create(pname, asgard.KaryonPkg, regions, phpcount, tname) asgard.Create(nname, asgard.KaryonPkg, regions, nodecount, tname) asgard.Create(zuname, asgard.ZuulPkg, regions, zuulcount, pname, nname) asgard.Create(elbname, asgard.ElbPkg, regions, 0, zuname) } dnsname := asgard.Create(dns, asgard.DenominatorPkg, 0, 0, elbname) asgard.Run(dnsname, "") }