1
0

upstream.go 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. package upstream
  2. import (
  3. "net"
  4. "sync"
  5. "time"
  6. )
  7. const MaxTimeout = 5 * time.Second
  8. const MaxConcurrentWorker = 10
  9. type Status struct {
  10. Online bool `json:"online"`
  11. Latency float32 `json:"latency"`
  12. }
  13. func AvailabilityTest(body []string) (result map[string]*Status) {
  14. result = make(map[string]*Status)
  15. wg := sync.WaitGroup{}
  16. wg.Add(len(body))
  17. c := make(chan struct{}, MaxConcurrentWorker)
  18. for _, socket := range body {
  19. c <- struct{}{}
  20. s := &Status{}
  21. go testLatency(c, &wg, socket, s)
  22. result[socket] = s
  23. }
  24. wg.Wait()
  25. return
  26. }
  27. func testLatency(c chan struct{}, wg *sync.WaitGroup, socket string, status *Status) {
  28. defer func() {
  29. wg.Done()
  30. <-c
  31. }()
  32. scopedWg := sync.WaitGroup{}
  33. scopedWg.Add(2)
  34. go testTCPLatency(&scopedWg, socket, status)
  35. go testUnixSocketLatency(&scopedWg, socket, status)
  36. scopedWg.Wait()
  37. }
  38. func testTCPLatency(wg *sync.WaitGroup, socket string, status *Status) {
  39. defer func() {
  40. wg.Done()
  41. }()
  42. start := time.Now()
  43. conn, err := net.DialTimeout("tcp", socket, MaxTimeout)
  44. if err != nil {
  45. return
  46. }
  47. defer conn.Close()
  48. end := time.Now()
  49. status.Online = true
  50. status.Latency = float32(end.Sub(start)) / float32(time.Millisecond)
  51. }
  52. func testUnixSocketLatency(wg *sync.WaitGroup, socket string, status *Status) {
  53. defer func() {
  54. wg.Done()
  55. }()
  56. start := time.Now()
  57. conn, err := net.DialTimeout("unix", socket, MaxTimeout)
  58. if err != nil {
  59. return
  60. }
  61. defer conn.Close()
  62. end := time.Now()
  63. status.Online = true
  64. status.Latency = float32(end.Sub(start)) / float32(time.Millisecond)
  65. }