Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Goで作る大量プロセス管理機構

 Goで作る大量プロセス管理機構

Go Conference'19 Summer in Fukuoka

Keita Mohri

July 13, 2019
Tweet

More Decks by Keita Mohri

Other Decks in Technology

Transcript

  1.  

  2.   ࣗࣾαʔϏε डୗ։ൃ 8FCαΠτ &$αΠτ FUD ۀ຿ΞϓϦ ίϯαϧ "3

    Ϋϥ΢υ *P5 'JO5FDI "* ΠϯλϥΫςΟϒίϯςϯπ εϚϗΞϓϦ
  3. ࣗࣾαʔϏε डୗ։ൃ 8FCαΠτ &$αΠτ FUD ۀ຿ΞϓϦ ίϯαϧ "3 Ϋϥ΢υ *P5

    'JO5FDI "* ΠϯλϥΫςΟϒίϯςϯπ εϚϗΞϓϦ ύʔτφʔ
  4.   PublicSubnet PrivateSubnet PrivateSubnet DynamoDB Lambda SNS SQS S3

    Bucket (Lot) S3 Bucket (Binary) Web Web Worker Worker Mock Mock Mock Mock Mock WebίϯιʔϧͰ ಈ࡞Λઃఆ mockΛૢ࡞
  5.   PublicSubnet PrivateSubnet DynamoDB Lambda SNS SQS S3 Bucket

    (Lot) S3 Bucket (Binary) Web Web Worker Worker WebίϯιʔϧͰ ಈ࡞Λઃఆ mockΛૢ࡞ mockૢ࡞JobΛ ൃߦ PrivateSubnet Mock Mock Mock Mock Mock
  6.   PublicSubnet PrivateSubnet DynamoDB Lambda SNS SQS S3 Bucket

    (Lot) S3 Bucket (Binary) Web Web Worker Worker mockૢ࡞JobΛ ൃߦ ઃఆϑΝΠϧΛ Ξοϓϩʔυ mockαʔόʔʹ ૢ࡞ࢦࣔ PrivateSubnet Mock Mock Mock Mock Mock Mock WebίϯιʔϧͰ ಈ࡞Λઃఆ mockΛૢ࡞
  7.   PublicSubnet PrivateSubnet DynamoDB Lambda SNS SQS S3 Bucket

    (Lot) S3 Bucket (Binary) Web Web Worker Worker mockૢ࡞JobΛ ൃߦ ઃఆϑΝΠϧΛ Ξοϓϩʔυ mockαʔόʔʹ ૢ࡞ࢦࣔ ઃఆϑΝΠϧ όΠφϦΛDL PrivateSubnet Mock Mock Mock Mock Mock Mock WebίϯιʔϧͰ ಈ࡞Λઃఆ mockΛૢ࡞
  8.   PublicSubnet PrivateSubnet DynamoDB Lambda SNS SQS S3 Bucket

    (Lot) S3 Bucket (Binary) Web Web Worker Worker mockૢ࡞JobΛ ൃߦ ઃఆϑΝΠϧΛ Ξοϓϩʔυ mockαʔόʔʹ ૢ࡞ࢦࣔ ઃఆϑΝΠϧ όΠφϦΛDL PrivateSubnet Mock Mock Mock Mock Mock Mock mockىಈ WebίϯιʔϧͰ ಈ࡞Λઃఆ mockΛૢ࡞
  9.   PublicSubnet PrivateSubnet DynamoDB Lambda SNS SQS S3 Bucket

    (Lot) S3 Bucket (Binary) Web Web Worker Worker mockૢ࡞JobΛ ൃߦ ઃఆϑΝΠϧΛ Ξοϓϩʔυ mockαʔόʔʹ ૢ࡞ࢦࣔ Քಇঢ়گɾϩάૹ৴ ઃఆϑΝΠϧ όΠφϦΛDL PrivateSubnet Mock Mock Mock Mock Mock Mock mockىಈ WebίϯιʔϧͰ ಈ࡞Λઃఆ mockΛૢ࡞
  10.   PublicSubnet PrivateSubnet DynamoDB Lambda SNS SQS S3 Bucket

    (Lot) S3 Bucket (Binary) Web Web Worker Worker ίϯιʔϧͰ mockΛૢ࡞ mockૢ࡞JobΛ ൃߦ ઃఆϑΝΠϧΛ Ξοϓϩʔυ mockαʔόʔʹ ૢ࡞ࢦࣔ Քಇঢ়گɾϩάૹ৴ ઃఆϑΝΠϧ όΠφϦΛDL PrivateSubnet Mock Mock Mock Mock Mock mockىಈ Mock Mock [ mock ] Go੡όΠφϦ͔Βཱͯͨ Ծ૝σόΠε໾ϓϩηε [ tower ] Go੡όΠφϦ͔Βཱͯͨ mock؅ཧϓϩηε
  11.   PublicSubnet PrivateSubnet DynamoDB Lambda SNS SQS S3 Bucket

    (Lot) S3 Bucket (Binary) Web Web Worker Worker mockૢ࡞JobΛ ൃߦ ઃఆϑΝΠϧΛ Ξοϓϩʔυ mockαʔόʔʹ ૢ࡞ࢦࣔ Քಇঢ়گɾϩάૹ৴ ઃఆϑΝΠϧ όΠφϦΛDL PrivateSubnet Mock Mock Mock Mock Mock Mock mockىಈ WebίϯιʔϧͰ ಈ࡞Λઃఆ mockΛૢ࡞
  12.   PublicSubnet PrivateSubnet DynamoDB Lambda SNS SQS S3 Bucket

    (Lot) S3 Bucket (Binary) Web Web Worker Worker mockૢ࡞JobΛ ൃߦ ઃఆϑΝΠϧΛ Ξοϓϩʔυ mockαʔόʔʹ ૢ࡞ࢦࣔ Քಇঢ়گɾϩάૹ৴ ઃఆϑΝΠϧ όΠφϦΛDL PrivateSubnet Mock Mock Mock Mock Mock Mock ͳΜͰϓϩηεʁ ͳΜͰGoʁ WebίϯιʔϧͰ ಈ࡞Λઃఆ mockΛૢ࡞
  13.   PublicSubnet PrivateSubnet DynamoDB Lambda SNS SQS S3 Bucket

    (Lot) S3 Bucket (Binary) Web Web Worker Worker mockૢ࡞JobΛ ൃߦ ઃఆϑΝΠϧΛ Ξοϓϩʔυ Քಇঢ়گɾϩάૹ৴ ઃఆϑΝΠϧ όΠφϦΛDL PrivateSubnet Mock Mock Mock Mock Mock Mock ͳΜͰϓϩηεʁ ͳΜͰGoʁ WebίϯιʔϧͰ ಈ࡞Λઃఆ mockΛૢ࡞ Ͳ͏΍ͬͯ େྔͷϓϩηεΛૢ࡞ʁ
  14.   PublicSubnet PrivateSubnet DynamoDB Lambda SNS SQS S3 Bucket

    (Lot) S3 Bucket (Binary) Web Web Worker Worker mockૢ࡞JobΛ ൃߦ ઃఆϑΝΠϧΛ Ξοϓϩʔυ Քಇঢ়گɾϩάૹ৴ PrivateSubnet Mock Mock Mock Mock Mock Mock ͳΜͰϓϩηεʁ ͳΜͰGoʁ WebίϯιʔϧͰ ಈ࡞Λઃఆ mockΛૢ࡞ Ͳ͏΍ͬͯ େྔͷϓϩηεΛૢ࡞ʁ mockͷࢮ׆؂ࢹ͸ Ͳ͏ͯ͠Δͷʁ ઃఆϑΝΠϧ όΠφϦΛDL
  15.   PublicSubnet PrivateSubnet DynamoDB Lambda SNS SQS S3 Bucket

    (Lot) S3 Bucket (Binary) Web Web Worker Worker mockૢ࡞JobΛ ൃߦ ઃఆϑΝΠϧΛ Ξοϓϩʔυ Քಇঢ়گɾϩάૹ৴ PrivateSubnet Mock Mock Mock Mock Mock Mock ͳΜͰϓϩηεʁ ͳΜͰGoʁ WebίϯιʔϧͰ ಈ࡞Λઃఆ mockΛૢ࡞ Ͳ͏΍ͬͯ େྔͷϓϩηεΛૢ࡞ʁ mockͷࢮ׆؂ࢹ͸ Ͳ͏ͯ͠Δͷʁ όΠφϦͷ ߋ৽͸ Ͳ͏͢Δͷʁ
  16. ‣ ϑΝΠϧϕʔεͰͷૢ࡞  ಛఆͷσΟϨΫτϦʹϑΝΠϧΛஔ͔ΕͨͷΛݕ஌ͯ͠ॲཧΛߦ͏  ૢ࡞͕ඞཁͳ෼͚ͩϑΝΠϧΛஔ͚͹͍͍ NPDLͷૢ࡞   NPDLىಈ

    NPDLఀࢭ ىಈτϦΨʔ
 ϑΝΠϧઃஔ tower͕ݕ஌͠ mockΛىಈ ఀࢭτϦΨʔ
 ϑΝΠϧઃஔ ֤mock༻ ఀࢭτϦΨʔ
 ϑΝΠϧઃஔ mock͕ݕ஌͠ ࣗݾফ໓
  17. GTOPUJGZ   watcher, err := fsnotify.NewWatcher() defer watcher.Close() err

    = watcher.Add("path/to/trigger/directory") // ϝΠϯϧʔϓ for { select { case ev := <-watcher.Events: // ϑΝΠϧ࡞੒Ҏ֎͸ແࢹ if (ev.Op & fsnotify.Create) == 0 { continue } // τϦΨʔϑΝΠϧͷॲཧ runTriggerProcessor(ev.Name) // Ұ੪ʹmock͕ىಈ͢Δͱड͚ଆ͕େมͳͷͰద੾ʹsleep // (ུ) case err := <-watcher.Errors: // Τϥʔॲཧ case //ͦͷଞॾʑͷॲཧ } }
  18. watcher, err := fsnotify.NewWatcher() defer watcher.Close() err = watcher.Add("path/to/trigger/directory") //

    ϝΠϯϧʔϓ for { select { case ev := <-watcher.Events: // ϑΝΠϧ࡞੒Ҏ֎͸ແࢹ if (ev.Op & fsnotify.Create) == 0 { continue } // τϦΨʔϑΝΠϧͷॲཧ runTriggerProcessor(ev.Name) // Ұ੪ʹmock͕ىಈ͢Δͱड͚ଆ͕େมͳͷͰద੾ʹsleep // (ུ) case err := <-watcher.Errors: // Τϥʔॲཧ case //ͦͷଞॾʑͷॲཧ } } GTOPUJGZ   ؂ࢹର৅ͷσΟϨΫτϦΛઃఆ func (w *Watcher) Add(name string) error
  19. watcher, err := fsnotify.NewWatcher() defer watcher.Close() err = watcher.Add("path/to/trigger/directory") //

    ϝΠϯϧʔϓ for { select { case ev := <-watcher.Events: // ϑΝΠϧ࡞੒Ҏ֎͸ແࢹ if (ev.Op & fsnotify.Create) == 0 { continue } // τϦΨʔϑΝΠϧͷॲཧ runTriggerProcessor(ev.Name) // Ұ੪ʹmock͕ىಈ͢Δͱड͚ଆ͕େมͳͷͰద੾ʹsleep // (ུ) case err := <-watcher.Errors: // Τϥʔॲཧ case //ͦͷଞॾʑͷॲཧ } } GTOPUJGZ   ؂ࢹର৅ͷσΟϨΫτϦΛઃఆ func (w *Watcher) Add(name string) error type Event struct { Name string // Πϕϯτ͕͋ͬͨ file/directory Op Op // ૢ࡞छผΛද͢Ϗοτྻ }
  20. GTOPUJGZ   watcher, err := fsnotify.NewWatcher() defer watcher.Close() err

    = watcher.Add("path/to/trigger/directory") // ϝΠϯϧʔϓ for { select { case ev := <-watcher.Events: // ϑΝΠϧ࡞੒Ҏ֎͸ແࢹ if (ev.Op & fsnotify.Create) == 0 { continue } // τϦΨʔϑΝΠϧͷॲཧ runTriggerProcessor(ev.Name) // Ұ੪ʹmock͕ىಈ͢Δͱड͚ଆ͕େมͳͷͰద੾ʹsleep // (ུ) case err := <-watcher.Errors: // Τϥʔॲཧ case //ͦͷଞॾʑͷॲཧ } } ؂ࢹର৅ͷσΟϨΫτϦΛઃఆ func (w *Watcher) Add(name string) error ev.OpʹϏοτϚεΫΛ͔͚Δ͜ͱͰૢ࡞छผΛ֬ೝ type Op uint32 const ( Create Op = 1 << iota Write Remove Rename Chmod ) type Event struct { Name string // Πϕϯτ͕͋ͬͨ file/directory Op Op // ૢ࡞छผΛද͢Ϗοτྻ }
  21. watcher, err := fsnotify.NewWatcher() defer watcher.Close() err = watcher.Add("path/to/trigger/directory") //

    ϝΠϯϧʔϓ for { select { case ev := <-watcher.Events: // ϑΝΠϧ࡞੒Ҏ֎͸ແࢹ if (ev.Op & fsnotify.Create) == 0 { continue } // τϦΨʔϑΝΠϧͷॲཧ runTriggerProcessor(ev.Name) // Ұ੪ʹmock͕ىಈ͢Δͱड͚ଆ͕େมͳͷͰద੾ʹsleep // (ུ) case err := <-watcher.Errors: // Τϥʔॲཧ case //ͦͷଞॾʑͷॲཧ } } GTOPUJGZ   ؂ࢹର৅ͷσΟϨΫτϦΛઃఆ func (w *Watcher) Add(name string) error ev.OpʹϏοτϚεΫΛ͔͚Δ͜ͱͰૢ࡞छผΛ֬ೝ type Op uint32 const ( Create Op = 1 << iota Write Remove Rename Chmod ) type Event struct { Name string // Πϕϯτ͕͋ͬͨ file/directory Op Op // ૢ࡞छผΛද͢Ϗοτྻ } sleepೖΕͯ΋ͪΌΜͱશ෦௨஌ͯ͘͠ΕΔͷͰ QueueͬΆ͍ײ͡ʹͳΔ
  22. ‣ NPDLఀࢭॲཧͰਖ਼ৗʹఀࢭͰ͖͔ͨ  NPDL༻ͷఀࢭτϦΨʔϑΝΠϧΛઃஔ  ࣗવఀࢭ w ࠷େՔಇ࣌ؒܦա w ఀࢭεςʔλε΁ͷભҠ

    ‣ NPDL͕ҟৗऴ͍ྃͯ͠ͳ͍͔  NPDL͕ಥવͷࢮΛܴ͑ΔՄೳੑ΋θϩͰ͸ͳ͍  ద੾ʹݕ஌ɾ௨஌͠ͳ͚Ε͹ NPDLͷࢮ׆؂ࢹ  
  23. ‣ NPDLఀࢭॲཧͰਖ਼ৗʹఀࢭͰ͖͔ͨ  NPDL༻ͷఀࢭτϦΨʔϑΝΠϧΛઃஔ  ࣗવఀࢭ w ࠷େՔಇ࣌ؒܦա w ఀࢭεςʔλε΁ͷભҠ

    ‣ NPDL͕ҟৗऴ͍ྃͯ͠ͳ͍͔  NPDL͕ಥવͷࢮΛܴ͑ΔՄೳੑ΋θϩͰ͸ͳ͍  ద੾ʹݕ஌ɾ௨஌͠ͳ͚Ε͹ NPDLͷࢮ׆؂ࢹ   ϓϩηεͷ ঢ়ଶมԽΛ؂ࢹ
  24. NPDLϓϩηεͷঢ়ଶมԽΛ؂ࢹ   processExitChannel chan int func (t *Tower) mockExec(mock

    MockCode, version string, ...) { // ىಈઃఆϑΝΠϧͷऔಘͱ͔(ུ) // ϓϩηεىಈ var proc *os.Process proc, err = os.StartProcess(binPath, args, attr) // PidΛอଘ mockProcessTable[proc.Pid] = mock // goroutineͰऴྃ؂ࢹ go func(t *Tower, mock MockCode, pid int) { for { var status syscall.WaitStatus var rusage syscall.Rusage wpid, err := syscall.Wait4(pid, &status, syscall.WNOHANG, &rusage) if err != nil || (wpid != 0 && status.Exited()) { processExitChannel <- pid return } time.Sleep(intervalMsec) } }(t, mock, proc.Pid)
  25. processExitChannel chan int func (t *Tower) mockExec(mock MockCode, version string,

    ...) { // ىಈઃఆϑΝΠϧͷऔಘͱ͔(ུ) // ϓϩηεىಈ var proc *os.Process proc, err = os.StartProcess(binPath, args, attr) // PidΛอଘ mockProcessTable[proc.Pid] = mock // goroutineͰऴྃ؂ࢹ go func(t *Tower, mock MockCode, pid int) { for { var status syscall.WaitStatus var rusage syscall.Rusage wpid, err := syscall.Wait4(pid, &status, syscall.WNOHANG, &rusage) if err != nil || (wpid != 0 && status.Exited()) { processExitChannel <- pid return } time.Sleep(intervalMsec) } }(t, mock, proc.Pid) NPDLϓϩηεͷঢ়ଶมԽΛ؂ࢹ   ϓϩηεىಈޙɺgoroutineΛ૸Βͤͯ؂ࢹ͢Δ (ىಈ͍ͯ͠Δmockͷ਺͚ͩgoroutineΛ૸Β͍ͤͯΔ)
  26. NPDLϓϩηεͷঢ়ଶมԽΛ؂ࢹ   processExitChannel chan int func (t *Tower) mockExec(mock

    MockCode, version string, ...) { // ىಈઃఆϑΝΠϧͷऔಘͱ͔(ུ) // ϓϩηεىಈ var proc *os.Process proc, err = os.StartProcess(binPath, args, attr) // PidΛอଘ mockProcessTable[proc.Pid] = mock // goroutineͰऴྃ؂ࢹ go func(t *Tower, mock MockCode, pid int) { for { var status syscall.WaitStatus var rusage syscall.Rusage wpid, err := syscall.Wait4(pid, &status, syscall.WNOHANG, &rusage) if err != nil || (wpid != 0 && status.Exited()) { processExitChannel <- pid return } time.Sleep(intervalMsec) } }(t, mock, proc.Pid) ϓϩηεىಈޙɺgoroutineΛ૸Βͤͯ؂ࢹ͢Δ (ىಈ͍ͯ͠Δmockͷ਺͚ͩgoroutineΛ૸Β͍ͤͯΔ) WNOHANGΦϓγϣϯ: ঢ়ଶมԽ͕ىͬͨ͜ࢠϓϩηε͕ͳ͍৔߹ʹ͙͢ʹ෮ؼ
  27. processExitChannel chan int func (t *Tower) mockExec(mock MockCode, version string,

    ...) { // ىಈઃఆϑΝΠϧͷऔಘͱ͔(ུ) // ϓϩηεىಈ var proc *os.Process proc, err = os.StartProcess(binPath, args, attr) // PidΛอଘ mockProcessTable[proc.Pid] = mock // goroutineͰऴྃ؂ࢹ go func(t *Tower, mock MockCode, pid int) { for { var status syscall.WaitStatus var rusage syscall.Rusage wpid, err := syscall.Wait4(pid, &status, syscall.WNOHANG, &rusage) if err != nil || (wpid != 0 && status.Exited()) { processExitChannel <- pid return } time.Sleep(intervalMsec) } }(t, mock, proc.Pid) NPDLϓϩηεͷঢ়ଶมԽΛ؂ࢹ   ϓϩηεىಈޙɺgoroutineΛ૸Βͤͯ؂ࢹ͢Δ (ىಈ͍ͯ͠Δmockͷ਺͚ͩgoroutineΛ૸Β͍ͤͯΔ) WNOHANGΦϓγϣϯ: ঢ়ଶมԽ͕ىͬͨ͜ࢠϓϩηε͕ͳ͍৔߹ʹ͙͢ʹ෮ؼ status.ExitStatus()Ͱҟৗऴྃ֬ೝ΋ͨ͠Γ͢Δ
  28. processExitChannel chan int func (t *Tower) mockExec(mock MockCode, version string,

    ...) { // ىಈઃఆϑΝΠϧͷऔಘͱ͔(ུ) // ϓϩηεىಈ var proc *os.Process proc, err = os.StartProcess(binPath, args, attr) // PIDΛอଘ mockProcessTable[proc.Pid] = mock // goroutineͰऴྃ؂ࢹ go func(t *Tower, mock MockCode, pid int) { for { var status syscall.WaitStatus var rusage syscall.Rusage wpid, err := syscall.Wait4(pid, &status, syscall.WNOHANG, &rusage) if err != nil || (wpid != 0 && status.Exited()) { processExitChannel <- pid return } time.Sleep(intervalMsec) } }(t, mock, proc.Pid) NPDLϓϩηεͷঢ়ଶมԽΛ؂ࢹ   ϓϩηεىಈޙɺgoroutineΛ૸Βͤͯ؂ࢹ͢Δ (ىಈ͍ͯ͠Δmockͷ਺͚ͩgoroutineΛ૸Β͍ͤͯΔ) ऴྃͨ͠ΒprocessExitChannelʹ௨஌ WNOHANGΦϓγϣϯ: ঢ়ଶมԽ͕ىͬͨ͜ࢠϓϩηε͕ͳ͍৔߹ʹ͙͢ʹ෮ؼ status.ExitStatus()Ͱҟৗऴྃ֬ೝ΋ͨ͠Γ͢Δ
  29. NPDLϓϩηεͷঢ়ଶมԽΛ؂ࢹ   // ϝΠϯϧʔϓ for { select { case

    // τϦΨʔϑΝΠϧͷݕ஌ॲཧͱ͔ case pid := <-processExitChannel: mock := mockProcessTable[pid] // ऴྃޙͷ͓ย෇͚΋Ζ΋Ζ delete(mockProcessTable, pid) } }
  30. ‣ NPDLఀࢭॲཧͰਖ਼ৗʹఀࢭͰ͖͔ͨ  NPDL༻ͷఀࢭτϦΨʔϑΝΠϧΛઃஔ  ࣗવఀࢭ w ࠷େՔಇ࣌ؒܦա w ఀࢭεςʔλε΁ͷભҠ

    ‣ NPDL͕ҟৗऴ͍ྃͯ͠ͳ͍͔  NPDL͕ಥવͷࢮΛܴ͑ΔՄೳੑ΋θϩͰ͸ͳ͍  ద੾ʹݕ஌ɾ௨஌͠ͳ͚Ε͹ NPDLͷࢮ׆؂ࢹ   ϓϩηεͷ ঢ়ଶมԽΛ؂ࢹ ఀࢭτϦΨʔϑΝΠϧͱ ಈ࡞தͷϓϩηεΛൺֱ
  31. ఀࢭτϦΨʔϑΝΠϧͷফԽ֬ೝ   ticker := time.NewTicker(tickerIntervalMsec) defer ticker.Stop() // ϝΠϯϧʔϓ

    for { select { case // τϦΨʔϑΝΠϧͷݕ஌ॲཧͱ͔ϓϩηεऴྃ࣌ͷॲཧͱ͔ case tickTime := <-ticker.C: // τϦΨʔϑΝΠϧ͕͋Δͷʹ࢒͍ͬͯΔϓϩηεΛ֬ೝ t.processLeftMock(tickTime) } } func (t *Tower) processLeftMock(cur time.Time) { for mock, term := range t.terminateTable { if cur.Before(term.triggeredAt.Add(ForceTerminateTime)) { continue } pid, processExist := t.mockTable[mock] proc, err := os.FindProcess(pid) err = proc.Signal(os.Kill) delete(t.terminateTable, mock) } }
  32. ఀࢭτϦΨʔϑΝΠϧͷফԽ֬ೝ   ticker := time.NewTicker(tickerIntervalMsec) defer ticker.Stop() // ϝΠϯϧʔϓ

    for { select { case // τϦΨʔϑΝΠϧͷݕ஌ॲཧͱ͔ϓϩηεऴྃ࣌ͷॲཧͱ͔ case tickTime := <-ticker.C: // τϦΨʔϑΝΠϧ͕͋Δͷʹ࢒͍ͬͯΔϓϩηεΛ֬ೝ t.processLeftMock(tickTime) } } func (t *Tower) processLeftMock(cur time.Time) { for mock, term := range t.terminateTable { if cur.Before(term.triggeredAt.Add(ForceTerminateTime)) { continue } pid, processExist := t.mockTable[mock] proc, err := os.FindProcess(pid) err = proc.Signal(os.Kill) delete(t.terminateTable, mock) } } tickerΛ࢖ͬͯఆظతʹະফԽτϦΨʔϑΝΠϧΛ֬ೝ
  33. ఀࢭτϦΨʔϑΝΠϧͷফԽ֬ೝ   ticker := time.NewTicker(tickerIntervalMsec) defer ticker.Stop() // ϝΠϯϧʔϓ

    for { select { case // τϦΨʔϑΝΠϧͷݕ஌ॲཧͱ͔ϓϩηεऴྃ࣌ͷॲཧͱ͔ case tickTime := <-ticker.C: // τϦΨʔϑΝΠϧ͕͋Δͷʹ࢒͍ͬͯΔϓϩηεΛ֬ೝ t.processLeftMock(tickTime) } } func (t *Tower) processLeftMock(cur time.Time) { for mock, term := range t.terminateTable { if cur.Before(term.triggeredAt.Add(ForceTerminateTime)) { continue } pid, processExist := t.mockTable[mock] proc, err := os.FindProcess(pid) err = proc.Signal(os.Kill) delete(t.terminateTable, mock) } } tickerΛ࢖ͬͯఆظతʹະফԽτϦΨʔϑΝΠϧΛ֬ೝ ઃஔޙҰఆ͕࣌ؒܦաͨ͠΋ͷͷΈ͕֬ೝର৅
  34. ఀࢭτϦΨʔϑΝΠϧͷফԽ֬ೝ   ticker := time.NewTicker(tickerIntervalMsec) defer ticker.Stop() // ϝΠϯϧʔϓ

    for { select { case // τϦΨʔϑΝΠϧͷݕ஌ॲཧͱ͔ϓϩηεऴྃ࣌ͷॲཧͱ͔ case tickTime := <-ticker.C: // τϦΨʔϑΝΠϧ͕͋Δͷʹ࢒͍ͬͯΔϓϩηεΛ֬ೝ t.processLeftMock(tickTime) } } func (t *Tower) processLeftMock(cur time.Time) { for mock, term := range t.terminateTable { if cur.Before(term.triggeredAt.Add(ForceTerminateTime)) { continue } pid, processExist := t.mockTable[mock] proc, err := os.FindProcess(pid) err = proc.Signal(os.Kill) delete(t.terminateTable, mock) } } tickerΛ࢖ͬͯఆظతʹະফԽτϦΨʔϑΝΠϧΛ֬ೝ ઃஔޙҰఆ͕࣌ؒܦաͨ͠΋ͷͷΈ͕֬ೝର৅ ϓϩηεڧ੍ऴྃ
  35. ‣ NPDL  Քಇத͸ߋ৽ෆཁ ಉ͡ઃఆͰಈ͖ଓ͚ΔͷͰ   ىಈ࣌ʹ࠷৽൛ͷόΠφϦΛ࣋ͬͯ͘Ε͹0, ‣ UPXFS

     NPDL͕ՔಇதͰ΋ߋ৽͍ͨ͠  ࠶ىಈ چUPXFSΛఀࢭ৽UPXFSΛىಈ Ͱ͖ΔΑ͏ʹ͓ͯ͘͠  NPDL؂ࢹঢ়گͷϨδϡʔϜΛ͕Μ͹Δʂ όΠφϦͷߋ৽  
  36. ‣ ࠶ىಈखॱ  <چ>UPXFSͷ࠶ىಈτϦΨʔϑΝΠϧͷݕ஌  <چ>τϦΨʔϑΝΠϧʹॻ͔Ε͍ͯΔόʔδϣϯΛ4͔Β%-ͯ͠ىಈ  <چ>ऴྃ  <৽>NPDLͷ؂ࢹঢ়گΛϨδϡʔϜ

    ‣ ϨδϡʔϜ͠ͳ͍ͱ͍͚ͳ͍΋ͷ  NPDL$PEFͱ1*%Λؔ࿈෇͚ΔNBQ  NPDLϓϩηεΛ؂ࢹ͢ΔHPSPVUJOF UPXFSͷ࠶ىಈ  
  37. ࠶ىಈτϦΨʔϑΝΠϧݕ஌dऴྃ   // ϝΠϯϧʔϓ for { select { case

    // τϦΨʔϑΝΠϧͷݕ஌ॲཧͱ͔ϓϩηεऴྃ࣌ͷॲཧͱ͔ఆظॲཧͱ͔ case ev := <-t.towerReboot.Events: if (ev.Op & fsnotify.Create) == 0 || (base != towerRebootName) { continue } rebootStrs, err := ioutil.ReadFile(ev.Name) reboot := strings.Split(strings.TrimSpace(string(rebootStrs)), " ") // ࠶ىಈ࣌ʹόΠφϦ͕ଘࡏ͠ͳ͍৔߹͸μ΢ϯϩʔυͯ͘͠Δ(ུ) // ৽towerىಈ _, err = os.StartProcess(binPath, args, attr) // ϝΠϯϧʔϓ͔Βൈ͚Δ return } }
  38. ࠶ىಈτϦΨʔϑΝΠϧݕ஌dऴྃ   // ϝΠϯϧʔϓ for { select { case

    // τϦΨʔϑΝΠϧͷݕ஌ॲཧͱ͔ϓϩηεऴྃ࣌ͷॲཧͱ͔ఆظॲཧͱ͔ case ev := <-t.towerReboot.Events: if (ev.Op & fsnotify.Create) == 0 || (base != towerRebootName) { continue } rebootStrs, err := ioutil.ReadFile(ev.Name) reboot := strings.Split(strings.TrimSpace(string(rebootStrs)), " ") // ࠶ىಈ࣌ʹόΠφϦ͕ଘࡏ͠ͳ͍৔߹͸μ΢ϯϩʔυͯ͘͠Δ(ུ) // ৽towerىಈ _, err = os.StartProcess(binPath, args, attr) // ϝΠϯϧʔϓ͔Βൈ͚Δ return } } ࠶ىಈτϦΨʔϑΝΠϧͷ࡞੒ΠϕϯτҎ֎͸ແࢹ
  39. ࠶ىಈτϦΨʔϑΝΠϧݕ஌dऴྃ   // ϝΠϯϧʔϓ for { select { case

    // τϦΨʔϑΝΠϧͷݕ஌ॲཧͱ͔ϓϩηεऴྃ࣌ͷॲཧͱ͔ఆظॲཧͱ͔ case ev := <-t.towerReboot.Events: if (ev.Op & fsnotify.Create) == 0 || (base != towerRebootName) { continue } rebootStrs, err := ioutil.ReadFile(ev.Name) reboot := strings.Split(strings.TrimSpace(string(rebootStrs)), " ") // ࠶ىಈ࣌ʹόΠφϦ͕ଘࡏ͠ͳ͍৔߹͸μ΢ϯϩʔυͯ͘͠Δ(ུ) // ৽towerىಈ _, err = os.StartProcess(binPath, args, attr) // ϝΠϯϧʔϓ͔Βൈ͚Δ return } } ࠶ىಈτϦΨʔϑΝΠϧͷ࡞੒ΠϕϯτҎ֎͸ແࢹ τϦΨʔϑΝΠϧͷத਎ΛݺΜͰόʔδϣϯΛऔಘ
  40. ࠶ىಈτϦΨʔϑΝΠϧݕ஌dऴྃ   // ϝΠϯϧʔϓ for { select { case

    // τϦΨʔϑΝΠϧͷݕ஌ॲཧͱ͔ϓϩηεऴྃ࣌ͷॲཧͱ͔ఆظॲཧͱ͔ case ev := <-t.towerReboot.Events: if (ev.Op & fsnotify.Create) == 0 || (base != towerRebootName) { continue } rebootStrs, err := ioutil.ReadFile(ev.Name) reboot := strings.Split(strings.TrimSpace(string(rebootStrs)), " ") // ࠶ىಈ࣌ʹόΠφϦ͕ଘࡏ͠ͳ͍৔߹͸μ΢ϯϩʔυͯ͘͠Δ(ུ) // ৽towerىಈ _, err = os.StartProcess(binPath, args, attr) // ϝΠϯϧʔϓ͔Βൈ͚Δ return } } ࠶ىಈτϦΨʔϑΝΠϧͷ࡞੒ΠϕϯτҎ֎͸ແࢹ τϦΨʔϑΝΠϧͷத਎ΛݺΜͰόʔδϣϯΛऔಘ ϝΠϯϧʔϓ͔Βൈ͚Δͱͦͷ··ऴྃ
  41. NPDL؂ࢹঢ়گͷϨδϡʔϜ   func NewTower() *Tower { // ͍Ζ͍ΖॳظԽ(ུ) //

    PIDϑΝΠϧΛऔಘ pidFiles, err := filepath.Glob(filepath.Join(t.PidsDir(), "mk-*")) for _, pidFile := range pidFiles { mock := MockCode(filepath.Base(pidFile)) // PIDϑΝΠϧ͔ΒPIDΛಡΈऔΓ pidStr, err := ioutil.ReadFile(pidFile) pid, err := strconv.Atoi(strings.TrimSpace(string(pidStr))) // PID͔Β࣮ࡍͷϓϩηεΛݟ͚ͭͯอଘ proc, err := os.FindProcess(pid) t.mockProcessTable[pid] = mock // ϓϩηεऴྃ௨஌goroutineΛ௥Ճ go func(t *Tower, mock MockCode, pid int) { // (ུ) }(&t, mock, pid) } }
  42. NPDL؂ࢹঢ়گͷϨδϡʔϜ   func NewTower() *Tower { // ͍Ζ͍ΖॳظԽ(ུ) //

    PIDϑΝΠϧΛऔಘ pidFiles, err := filepath.Glob(filepath.Join(t.PidsDir(), "mk-*")) for _, pidFile := range pidFiles { mock := MockCode(filepath.Base(pidFile)) // PIDϑΝΠϧ͔ΒPIDΛಡΈऔΓ pidStr, err := ioutil.ReadFile(pidFile) pid, err := strconv.Atoi(strings.TrimSpace(string(pidStr))) // PID͔Β࣮ࡍͷϓϩηεΛݟ͚ͭͯอଘ proc, err := os.FindProcess(pid) t.mockProcessTable[pid] = mock // ϓϩηεऴྃ௨஌goroutineΛ௥Ճ go func(t *Tower, mock MockCode, pid int) { // (ུ) }(&t, mock, pid) } } ֤mock͸ىಈ࣌ʹPIDϑΝΠϧΛ࡞Δ
  43. NPDL؂ࢹঢ়گͷϨδϡʔϜ   func NewTower() *Tower { // ͍Ζ͍ΖॳظԽ(ུ) //

    PIDϑΝΠϧΛऔಘ pidFiles, err := filepath.Glob(filepath.Join(t.PidsDir(), "mk-*")) for _, pidFile := range pidFiles { mock := MockCode(filepath.Base(pidFile)) // PIDϑΝΠϧ͔ΒPIDΛಡΈऔΓ pidStr, err := ioutil.ReadFile(pidFile) pid, err := strconv.Atoi(strings.TrimSpace(string(pidStr))) // PID͔Β࣮ࡍͷϓϩηεΛݟ͚ͭͯอଘ proc, err := os.FindProcess(pid) t.mockProcessTable[pid] = mock // ϓϩηεऴྃ௨஌goroutineΛ௥Ճ go func(t *Tower, mock MockCode, pid int) { // (ུ) }(&t, mock, pid) } } ֤mock͸ىಈ࣌ʹPIDϑΝΠϧΛ࡞Δ লུͯ͠Δ͚Ͳɺ ϓϩηε͕ݟ͔ͭΒͳ͔ͬͨΒPIDϑΝΠϧΛ࡟আ
  44. ‣ ɹɹʹ͓͍ͯɺ(PΛ࢖ͬͯ
 େྔͷϓϩηεΛͲͷΑ͏ʹ؅ཧ͍ͯ͠Δ͔Λ঺հ  ͦ΋ͦ΋ͳΜͰϓϩηεʁͳΜͰ(P   ϑΝΠϧϕʔεͷNPDLૢ࡞  NPDLͷࢮ׆؂ࢹ

     όΠφϦͷߋ৽ ‣ ʮ໌೔͔Β࢖͑ΔʯΑ͏ͳ಺༰Ͱ͸ͳ͍͸͚ͣͩͲɺ
 ָ͠ΜͰ΋Β͑ͨͳΒ޾͍Ͱ͢ ‣ (Pͨͷ͍͠ʂ ·ͱΊ