Example #1
0
// 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
}
Example #2
0
// 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, migration, or read from json_arch/<arch>_arch.json")
	flag.IntVar(&archaius.Conf.Population, "p", 100, "Pirate population for fsm or scale factor % for other architectures")
	flag.IntVar(&duration, "d", 10, "Simulation duration in seconds")
	flag.IntVar(&archaius.Conf.Regions, "w", 1, "Wide area regions to replicate architecture into, defaults based on 6 AWS region names")
	flag.BoolVar(&graphmlEnabled, "g", false, "Enable GraphML logging of nodes and edges to gml/<arch>.graphml")
	flag.BoolVar(&graphjsonEnabled, "j", false, "Enable GraphJSON logging of nodes and edges to json/<arch>.json")
	flag.BoolVar(&neo4jEnabled, "n", false, "Enable Neo4j logging of nodes and edges")
	flag.BoolVar(&archaius.Conf.Msglog, "m", false, "Enable console logging of every message")
	flag.BoolVar(&reload, "r", false, "Reload graph from json/<arch>.json to setup architecture")
	flag.BoolVar(&archaius.Conf.Collect, "c", false, "Collect metrics and flows to json_metrics csv_metrics neo4j and via http: extvars")
	flag.IntVar(&archaius.Conf.StopStep, "s", 0, "Sequence number to create multiple runs for ui to step through in json/<arch><s>.json")
	flag.StringVar(&archaius.Conf.EurekaPoll, "u", "1s", "Polling interval for Eureka name service, increase for large populations")
	flag.StringVar(&archaius.Conf.Keyvals, "kv", "", "Configuration key:value - chat:10ms sets default message insert rate")
	flag.BoolVar(&archaius.Conf.Filter, "f", false, "Filter output names to simplify graph by collapsing instances to services")
	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")
	var confFile = flag.String("config", "", "Config file to read from json_arch/<config>_conf.json. This config overrides any other command-line arguments.")
	var saveConfFile = flag.Bool("saveconfig", false, "Save config file to json_arch/<arch>_conf.json, using the arch name from -a.")
	flag.Parse()

	if *confFile != "" {
		archaius.ReadConf(*confFile)
	}
	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 || neo4jEnabled {
		if graphjsonEnabled {
			archaius.Conf.GraphjsonFile = archaius.Conf.Arch
		}
		if graphmlEnabled {
			archaius.Conf.GraphmlFile = archaius.Conf.Arch
		}
		if neo4jEnabled {
			if archaius.Conf.Filter {
				log.Fatal("Neo4j cannot be used with filtered names option -f")
			}
			pw := os.Getenv("NEO4JPASSWORD")
			url := os.Getenv("NEO4JURL")
			if pw == "" {
				log.Fatal("Neo4j requires environment variable NEO4JPASSWORD is set")
			}
			if url == "" {
				archaius.Conf.Neo4jURL = "localhost:7474"
			} else {
				archaius.Conf.Neo4jURL = url
			}
			log.Println("Graph will be written to Neo4j via NEO4JURL=" + archaius.Conf.Neo4jURL)
		}
		// make a big buffered channel so logging can start before edda is scheduled
		edda.Logchan = make(chan gotocol.Message, 1000)
	}
	archaius.Conf.RunDuration = time.Duration(duration) * time.Second

	if *saveConfFile {
		archaius.WriteConf()
	}

	// 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 "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()
}
Example #3
0
// 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, StorePkg, regions, mysqlcount, sname)
		asgard.Create(pname, MonolithPkg, regions, phpcount, sname)
		asgard.Create(elbname, ElbPkg, regions, 0, pname)
	case 1: // basic LAMP with memcache
		asgard.CreateChannels()
		asgard.CreateEureka() // service registries for each zone
		asgard.Create(sname, StorePkg, regions, mysqlcount, sname)
		asgard.Create(mname, StorePkg, regions, mcount)
		asgard.Create(pname, MonolithPkg, regions, phpcount, sname, mname)
		asgard.Create(elbname, ElbPkg, regions, 0, pname)
	case 2: // LAMP with zuul and memcache
		asgard.CreateChannels()
		asgard.CreateEureka() // service registries for each zone
		asgard.Create(sname, StorePkg, regions, mysqlcount, sname)
		asgard.Create(mname, StorePkg, regions, mcount)
		asgard.Create(pname, MonolithPkg, regions, phpcount, sname, mname)
		asgard.Create(zuname, ZuulPkg, regions, zuulcount, pname)
		asgard.Create(elbname, 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, StorePkg, regions, mysqlcount, sname)
		asgard.Create(mname, StorePkg, regions, mcount)
		asgard.Create(tname, StaashPkg, regions, staashcount, sname, mname)
		asgard.Create(pname, KaryonPkg, regions, phpcount, tname)
		asgard.Create(zuname, ZuulPkg, regions, zuulcount, pname)
		asgard.Create(elbname, ElbPkg, regions, 0, zuname)
	case 4: // added node microservice
		asgard.CreateChannels()
		asgard.CreateEureka() // service registries for each zone
		asgard.Create(sname, StorePkg, regions, mysqlcount, sname)
		asgard.Create(mname, StorePkg, regions, mcount)
		asgard.Create(tname, StaashPkg, regions, staashcount, sname, mname, cname)
		asgard.Create(pname, KaryonPkg, regions, phpcount, tname)
		asgard.Create(nname, KaryonPkg, regions, nodecount, tname)
		asgard.Create(zuname, ZuulPkg, regions, zuulcount, pname, nname)
		asgard.Create(elbname, ElbPkg, regions, 0, zuname)
	case 5: // added cassandra alongside mysql
		asgard.CreateChannels()
		asgard.CreateEureka() // service registries for each zone
		asgard.Create(cname, PriamCassandraPkg, regions, priamCassandracount, cname)
		asgard.Create(sname, StorePkg, regions, mysqlcount, sname)
		asgard.Create(mname, StorePkg, regions, mcount)
		asgard.Create(tname, StaashPkg, regions, staashcount, sname, mname, cname)
		asgard.Create(pname, KaryonPkg, regions, phpcount, tname)
		asgard.Create(nname, KaryonPkg, regions, nodecount, tname)
		asgard.Create(zuname, ZuulPkg, regions, zuulcount, pname, nname)
		asgard.Create(elbname, 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, PriamCassandraPkg, regions, priamCassandracount, cname)
		asgard.Create(mname, StorePkg, regions, mcount)
		asgard.Create(tname, StaashPkg, regions, staashcount, mname, cname)
		asgard.Create(pname, KaryonPkg, regions, phpcount, tname)
		asgard.Create(nname, KaryonPkg, regions, nodecount, tname)
		asgard.Create(zuname, ZuulPkg, regions, zuulcount, pname, nname)
		asgard.Create(elbname, 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, PriamCassandraPkg, regions, priamCassandracount, cname)
		asgard.Create(mname, StorePkg, regions, mcount)
		asgard.Create(tname, StaashPkg, regions, staashcount, mname, cname)
		asgard.Create(pname, KaryonPkg, regions, phpcount, tname)
		asgard.Create(nname, KaryonPkg, regions, nodecount, tname)
		asgard.Create(zuname, ZuulPkg, regions, zuulcount, pname, nname)
		asgard.Create(elbname, 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, PriamCassandraPkg, regions, priamCassandracount, "eureka", cname)
		asgard.Create(mname, StorePkg, regions, mcount)
		asgard.Create(tname, StaashPkg, regions, staashcount, mname, cname)
		asgard.Create(pname, KaryonPkg, regions, phpcount, tname)
		asgard.Create(nname, KaryonPkg, regions, nodecount, tname)
		asgard.Create(zuname, ZuulPkg, regions, zuulcount, pname, nname)
		asgard.Create(elbname, 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, PriamCassandraPkg, regions, priamCassandracount, "eureka", cname)
		asgard.Create(mname, StorePkg, regions, mcount)
		asgard.Create(tname, StaashPkg, regions, staashcount, mname, cname)
		asgard.Create(pname, KaryonPkg, regions, phpcount, tname)
		asgard.Create(nname, KaryonPkg, regions, nodecount, tname)
		asgard.Create(zuname, ZuulPkg, regions, zuulcount, pname, nname)
		asgard.Create(elbname, ElbPkg, regions, 0, zuname)
	}
	dnsname := asgard.Create(dns, DenominatorPkg, 0, 0, elbname)
	asgard.Run(dnsname, "")
}