рдЧреЛ рдкрд░ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдмреИрд▓реЗрдВрд╕рд░ рд▓рд┐рдЦрдирд╛


рд▓реЛрдб рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рд╡реЗрдм рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдореЗрдВ рдорд╣рддреНрд╡рдкреВрд░реНрдг рднреВрдорд┐рдХрд╛ рдирд┐рднрд╛рддреЗ рд╣реИрдВред рд╡реЗ рдЖрдкрдХреЛ рдХрдИ рдмреИрдХрдПрдВрдб рдореЗрдВ рд▓реЛрдб рд╡рд┐рддрд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реИрдВ, рдЬрд┐рд╕рд╕реЗ рд╕реНрдХреЗрд▓реЗрдмрд┐рд▓рд┐рдЯреА рдореЗрдВ рд╕реБрдзрд╛рд░ рд╣реЛрддрд╛ рд╣реИред рдФрд░ рдЪреВрдВрдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХрдИ рдмреИрдХрдПрдВрдб рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд┐рдП рдЧрдП рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рд╕реЗрд╡рд╛ рдЕрддреНрдпрдзрд┐рдХ рдЙрдкрд▓рдмреНрдз рд╣реЛ рдЬрд╛рддреА рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдПрдХ рд╕рд░реНрд╡рд░ рдкрд░ рдЕрд╕рдлрд▓ рд╣реЛрдиреЗ рдХреА рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рдмреИрд▓реЗрдВрд╕рд░ рджреВрд╕рд░реЗ рдХрд╛рдо рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рд╕рд░реНрд╡рд░ рдХреЛ рдЪреБрди рд╕рдХрддрд╛ рд╣реИред

NGINX рдЬреИрд╕реЗ рдкреЗрд╢реЗрд╡рд░ рдмреИрд▓реЗрдиреНрд╕рд░ рдХреЗ рд╕рд╛рде рдЦреЗрд▓рдиреЗ рдХреЗ рдмрд╛рдж, рдореИрдВрдиреЗ рдорд╕реНрддреА рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдмреИрд▓реЗрдиреНрд╕рд░ рдмрдирд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреАред рдореИрдВрдиреЗ рдЗрд╕реЗ рдЧреЛ рдкрд░ рд▓рд┐рдЦрд╛, рдпрд╣ рдПрдХ рдЖрдзреБрдирд┐рдХ рднрд╛рд╖рд╛ рд╣реИ рдЬреЛ рдкреВрд░реНрдг рд╕рдорд╛рдирддрд╛ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддреА рд╣реИред рдЧреЛ рдореЗрдВ рдорд╛рдирдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдореЗрдВ рдХрдИ рд╡рд┐рд╢реЗрд╖рддрд╛рдПрдВ рд╣реИрдВ рдФрд░ рдЖрдкрдХреЛ рдХрдо рдХреЛрдб рд╡рд╛рд▓реЗ рдЙрдЪреНрдЪ-рдкреНрд░рджрд░реНрд╢рди рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЛ рд▓рд┐рдЦрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рдорд┐рд▓рддреА рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╡рд┐рддрд░рдг рдореЗрдВ рдЖрд╕рд╛рдиреА рдХреЗ рд▓рд┐рдП, рдпрд╣ рдПрдХ рдПрдХрд▓ рд╕рд╛рдВрдЦреНрдпрд┐рдХреАрдп рд░реВрдк рд╕реЗ рдЬреБрдбрд╝рд╛ рд╣реБрдЖ рдмрд╛рдЗрдирд░реА рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИред

рд╣рдорд╛рд░рд╛ рдмреИрд▓реЗрдВрд╕рд░ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ


рдмреИрдХрдПрдВрдб рдХреЗ рдмреАрдЪ рд▓реЛрдб рд╡рд┐рддрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд┐рднрд┐рдиреНрди рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:

  • рд░рд╛рдЙрдВрдб рд░реЙрдмрд┐рди - рд▓реЛрдб рд╕рдорд╛рди рд░реВрдк рд╕реЗ рд╡рд┐рддрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд╕рд░реНрд╡рд░ рдХреА рд╕рдорд╛рди рдХрдВрдкреНрдпреВрдЯрд┐рдВрдЧ рд╢рдХреНрддрд┐ рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрддреЗ рд╣реБрдПред
  • рднрд╛рд░рд┐рдд рд░рд╛рдЙрдВрдб рд░реЙрдмрд┐рди - рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рд╢рдХреНрддрд┐ рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рд╕рд░реНрд╡рд░реЛрдВ рдХреЛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рднрд╛рд░ рд╕реМрдВрдкрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
  • рдХрдо рд╕реЗ рдХрдо рдХрдиреЗрдХреНрд╢рди - рд▓реЛрдб рдХреЛ рдХрдо рд╕реЗ рдХрдо рд╕рдХреНрд░рд┐рдп рдХрдиреЗрдХреНрд╢рди рдХреЗ рд╕рд╛рде рд╕рд░реНрд╡рд░ рдкрд░ рд╡рд┐рддрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рд╣рдорд╛рд░реЗ рдмреИрд▓реЗрдВрд╕рд░ рдореЗрдВ, рд╣рдо рд╕рдмрд╕реЗ рд╕рд░рд▓ рдПрд▓реНрдЧреЛрд░рд┐рджрдо - рд░рд╛рдЙрдВрдб рд░реЙрдмрд┐рди рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВред



рд░рд╛рдЙрдВрдб рд░реЙрдмрд┐рди рдореЗрдВ рдЪрдпрди


рдЧреЛрд▓ рд░реЙрдмрд┐рди рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рд╕рд░рд▓ рд╣реИред рдпрд╣ рд╕рднреА рдХрд▓рд╛рдХрд╛рд░реЛрдВ рдХреЛ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдкреВрд░рд╛ рдХрд░рдиреЗ рдХрд╛ рд╕рдорд╛рди рдЕрд╡рд╕рд░ рджреЗрддрд╛ рд╣реИред


рдЖрдиреЗ рд╡рд╛рд▓реЗ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рд░рд╛рдЙрдВрдб рд░реЙрдмрд┐рди рдореЗрдВ рд╕рд░реНрд╡рд░ рдХрд╛ рдЪрдпрди рдХрд░реЗрдВред

рдЬреИрд╕рд╛ рдХрд┐ рдЪрд┐рддреНрд░рдг рдореЗрдВ рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рд╕рд░реНрд╡рд░реЛрдВ рдХреЛ рдПрдХ рдЪрдХреНрд░ рдореЗрдВ, рдЪрдХреНрд░реАрдп рд░реВрдк рд╕реЗ рдЪреБрдирддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рд╣рдо рдЙрдиреНрд╣реЗрдВ рд╕реАрдзреЗ , рд╕рд╣реА рдХрд╛ рдЪрдпрди рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ?

рдФрд░ рдЕрдЧрд░ рд╕рд░реНрд╡рд░ рдЭреВрда рдмреЛрд▓ рд░рд╣рд╛ рд╣реИ? рд╣рдореЗрдВ рд╢рд╛рдпрдж рдЗрд╕реЗ рдЯреНрд░реИрдлрд╝рд┐рдХ рднреЗрдЬрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред рдЕрд░реНрдерд╛рдд, рд╕рд░реНрд╡рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рддрдм рддрдХ рд╕реАрдзреЗ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдЬрдм рддрдХ рд╣рдо рдЗрд╕реЗ рд╡рд╛рдВрдЫрд┐рдд рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдирд╣реАрдВ рд▓рд╛рддреЗред рдХреЗрд╡рд▓ рдЙрди рд╕рд░реНрд╡рд░реЛрдВ рдХреЗ рд▓рд┐рдП рдпрд╛рддрд╛рдпрд╛рдд рдХреЛ рдирд┐рд░реНрджреЗрд╢рд┐рдд рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ рдЬреЛ рдКрдкрд░ рдФрд░ рдЪрд▓ рд░рд╣реЗ рд╣реИрдВред

рд╕рдВрд░рдЪрдирд╛ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВ


рд╣рдореЗрдВ рдмреИрдХрдПрдВрдб рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╕рднреА рд╡рд┐рд╡рд░рдгреЛрдВ рдХреЛ рдЯреНрд░реИрдХ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЖрдкрдХреЛ рдпрд╣ рдЬрд╛рдирдирд╛ рд╣реЛрдЧрд╛ рдХрд┐ рдХреНрдпрд╛ рд╡рд╣ рдЬреАрд╡рд┐рдд рд╣реИ, рдФрд░ URL рдХреЛ рдЯреНрд░реИрдХ рдХрд░ рд╕рдХрддрд╛ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕рдВрд░рдЪрдирд╛ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

type Backend struct { URL *url.URL Alive bool mux sync.RWMutex ReverseProxy *httputil.ReverseProxy } 

рдЪрд┐рдВрддрд╛ рди рдХрд░реЗрдВ, рдореИрдВ рдмреИрдХрдПрдВрдб рдореЗрдВ рдлрд╝реАрд▓реНрдбреНрд╕ рдХрд╛ рдЕрд░реНрде рд╕рдордЭрд╛рдКрдВрдЧрд╛ред

рдЕрдм рдмреИрд▓реЗрдВрд╕рд░ рдореЗрдВ рдЖрдкрдХреЛ рдХрд┐рд╕реА рддрд░рд╣ рд╕рднреА рдмреИрдХреЗрдВрдб рдХреЛ рдЯреНрд░реИрдХ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдк рд╕реНрд▓рд╛рдЗрд╕ рдФрд░ рдПрдХ рдЪрд░ рдХрд╛рдЙрдВрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕реЗ ServerPool рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВ:

 type ServerPool struct { backends []*Backend current uint64 } 

ReverseProxy рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛


рдЬреИрд╕рд╛ рдХрд┐ рд╣рдордиреЗ рдкрд╣рд▓реЗ рд╣реА рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рд╣реИ, рдмреИрд▓реЗрдВрд╕рд░ рдХрд╛ рд╕рд╛рд░ рд╡рд┐рднрд┐рдиреНрди рд╕рд░реНрд╡рд░реЛрдВ рдХреЛ рдЯреНрд░реИрдлрд╝рд┐рдХ рд╡рд┐рддрд░рд┐рдд рдХрд░рдиреЗ рдФрд░ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рдкрд░рд┐рдгрд╛рдо рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдореЗрдВ рд╣реИред рдЬреИрд╕рд╛ рдХрд┐ рдЧреЛ рдкреНрд░рд▓реЗрдЦрди рдХрд╣рддрд╛ рд╣реИ:

ReverseProxy рдПрдХ HTTP рд╣реИрдВрдбрд▓рд░ рд╣реИ рдЬреЛ рдЖрдиреЗ рд╡рд╛рд▓реЗ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рд▓реЗрддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рдПрдХ рдЕрдиреНрдп рд╕рд░реНрд╡рд░ рдкрд░ рднреЗрдЬрддрд╛ рд╣реИ, рдЬреЛ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рдПрдВ рджреЗрддрд╛ рд╣реИред

рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╣рдореЗрдВ рдЬреЛ рдЪрд╛рд╣рд┐рдПред рдкрд╣рд┐рдпрд╛ рдХреЛ рд╕реБрджреГрдврд╝ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред рдЖрдк рдмрд╕ ReverseProxy рдорд╛рдзреНрдпрдо рд╕реЗ рд╣рдорд╛рд░реЗ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рд╕реНрдЯреНрд░реАрдо рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

 u, _ := url.Parse("http://localhost:8080") rp := httputil.NewSingleHostReverseProxy(u) // initialize your server and add this as handler http.HandlerFunc(rp.ServeHTTP) 

httputil.NewSingleHostReverseProxy(url) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ httputil.NewSingleHostReverseProxy(url) рдЖрдк ReverseProxy рдХреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рдХрд┐ рджрд┐рдП рдЧрдП url рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рдкреНрд░рд╕рд╛рд░рд┐рдд рдХрд░реЗрдЧрд╛ред рдКрдкрд░ рджрд┐рдП рдЧрдП рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рд╕рднреА рдЕрдиреБрд░реЛрдз рд╕реНрдерд╛рдиреАрдпрд╣реЛрд╕реНрдЯ рдХреЛ рднреЗрдЬреЗ рдЧрдП рдереЗ: 8080, рдФрд░ рдкрд░рд┐рдгрд╛рдо рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рднреЗрдЬреЗ рдЧрдП рдереЗред

рдпрджрд┐ рдЖрдк ServeHTTP рд╡рд┐рдзрд┐ рдХреЗ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдХреЛ рджреЗрдЦрддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдЗрд╕рдореЗрдВ HTTP рд╣реИрдВрдбрд▓рд░ рдХреЗ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕рд▓рд┐рдП, рдЖрдк рдЗрд╕реЗ http рдореЗрдВ HandlerFunc рдХреЛ рдкрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдЕрдиреНрдп рдЙрджрд╛рд╣рд░рдг рдкреНрд░рд▓реЗрдЦрди рдореЗрдВ рд╣реИрдВ ред

рд╣рдорд╛рд░реЗ рдмреИрд▓реЗрдВрд╕рд░ рдХреЗ рд▓рд┐рдП, рдЖрдк Backend рдореЗрдВ рд╕рдВрдмрдВрдзрд┐рдд URL рд╕рд╛рде ReverseProxy рдЖрд░рдВрдн рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рддрд╛рдХрд┐ ReverseProxy рд░реВрдЯ URL рд▓рд┐рдП рдЕрдиреБрд░реЛрдз URL ред

рд╕рд░реНрд╡рд░ рдЪрдпрди рдкреНрд░рдХреНрд░рд┐рдпрд╛


рдЕрдЧрд▓реЗ рд╕рд░реНрд╡рд░ рдХреЗ рдЪрдпрди рдХреЗ рджреМрд░рд╛рди, рд╣рдореЗрдВ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рд╕рд░реНрд╡рд░ рдХреЛ рдЫреЛрдбрд╝рдирд╛ рд╣реЛрдЧрд╛ред рд▓реЗрдХрд┐рди рдЖрдкрдХреЛ рдЧрд┐рдирддреА рдХреЛ рд╡реНрдпрд╡рд╕реНрдерд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

рдХрдИ рдЧреНрд░рд╛рд╣рдХ рдмреИрд▓реЗрдВрд╕рд░ рд╕реЗ рдЬреБрдбрд╝реЗрдВрдЧреЗ, рдФрд░ рдЬрдм рдЙрдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдЕрдЧрд▓реЗ рдиреЛрдб рдХреЛ рдЯреНрд░реИрдлрд╝рд┐рдХ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣реЗрдВрдЧреЗ, рддреЛ рд░реЗрд╕ рдХреА рд╕реНрдерд┐рддрд┐ рдЙрддреНрдкрдиреНрди рд╣реЛ рд╕рдХрддреА рд╣реИред рдЗрд╕реЗ рд░реЛрдХрдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо ServerPool рдХреЛ mutex рд╕рд╛рде рдмреНрд▓реЙрдХ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд▓реЗрдХрд┐рди рдпрд╣ рдмреЗрдорд╛рдиреА рд╣реЛрдЧрд╛, рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛ рд╣рдо ServerPool рдмреНрд▓реЙрдХ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рд╣рдореЗрдВ рд╕рд┐рд░реНрдл рдПрдХ-рдПрдХ рдХрд░рдХреЗ рдХрд╛рдЙрдВрдЯрд░ рдмрдврд╝рд╛рдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИред

рдЗрди рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рдХреЛ рдкреВрд░рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рд╕рдорд╛рдзрд╛рди рдкрд░рдорд╛рдгреБ рд╡реГрджреНрдзрд┐ рд╣реЛрдЧрд╛ред рдЧреЛ atomic рдкреИрдХреЗрдЬ рдХреЗ рд╕рд╛рде рдЗрд╕рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИред

 func (s *ServerPool) NextIndex() int { return int(atomic.AddUint64(&s.current, uint64(1)) % uint64(len(s.backends))) } 

рд╣рдо рдПрдЯреЛрдорд┐рдХ рд░реВрдк рд╕реЗ рд╡рд░реНрддрдорд╛рди рдореВрд▓реНрдп рдХреЛ рдПрдХ рд╕реЗ рдмрдврд╝рд╛рддреЗ рд╣реИрдВ рдФрд░ рд╕рд░рдгреА рдХреА рд▓рдВрдмрд╛рдИ рдХреЛ рдмрджрд▓рдХрд░ рд╕реВрдЪрдХрд╛рдВрдХ рд╡рд╛рдкрд╕ рдХрд░рддреЗ рд╣реИрдВред рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдорд╛рди рд╣рдореЗрд╢рд╛ 0 рд╕реЗ рд▓реЗрдХрд░ рд╕рд░рдгреА рдХреА рд▓рдВрдмрд╛рдИ рддрдХ рдХреА рд╕реАрдорд╛ рдореЗрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдЕрдВрдд рдореЗрдВ, рд╣рдо рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕реВрдЪрдХрд╛рдВрдХ рдореЗрдВ рджрд┐рд▓рдЪрд╕реНрдкреА рд▓реЗрдВрдЧреЗ, рди рдХрд┐ рдкреВрд░реЗ рдХрд╛рдЙрдВрдЯрд░ рдкрд░ред

рдПрдХ рд▓рд╛рдЗрд╡ рд╕рд░реНрд╡рд░ рдЪреБрдирдирд╛


рд╣рдо рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рд╣рдорд╛рд░реЗ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рд╕рднреА рд╕рд░реНрд╡рд░реЛрдВ рдкрд░ рдЪрдХреНрд░реАрдп рд░реВрдк рд╕реЗ рдШреБрдорд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдФрд░ рд╣рдореЗрдВ рдХреЗрд╡рд▓ рдирд┐рд╖реНрдХреНрд░рд┐рдп рдХреЛ рдЫреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

GetNext() рд╣рдореЗрд╢рд╛ рдорд╛рди 0 рд╕реЗ рд▓реЗрдХрд░ рд╕рд░рдгреА рдХреА рд▓рдВрдмрд╛рдИ рддрдХ рджреЗрддрд╛ рд╣реИред рдХрд┐рд╕реА рднреА рд╕рдордп, рд╣рдо рдЕрдЧрд▓рд╛ рдиреЛрдб рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдпрджрд┐ рдпрд╣ рдирд┐рд╖реНрдХреНрд░рд┐рдп рд╣реИ, рддреЛ рд╣рдореЗрдВ рд▓реВрдк рдХреЗ рд╣рд┐рд╕реНрд╕реЗ рдХреЗ рд░реВрдк рдореЗрдВ рд╕рд░рдгреА рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдФрд░ рдЦреЛрдЬ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред


рд╣рдо рд╕рд░рдгреА рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд▓реВрдк рдХрд░рддреЗ рд╣реИрдВред

рдЬреИрд╕рд╛ рдХрд┐ рдЪрд┐рддреНрд░рдг рдореЗрдВ рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд╣рдо рд╕реВрдЪреА рдХреЗ рдЕрдВрдд рдореЗрдВ рдЕрдЧрд▓реЗ рдиреЛрдб рд╕реЗ рдЬрд╛рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдпрд╣ next + length рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдПрдХ рд╕реВрдЪрдХрд╛рдВрдХ рдХрд╛ рдЪрдпрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдЗрд╕реЗ рд╕рд░рдгреА рдХреА рд▓рдВрдмрд╛рдИ рддрдХ рд╕реАрдорд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдпрд╣ рд╕рдВрд╢реЛрдзрд┐рдд рдСрдкрд░реЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЖрд╕рд╛рдиреА рд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рдЦреЛрдЬ рдХреЗ рджреМрд░рд╛рди рд╣рдореЗрдВ рдПрдХ рдХрд╛рд░реНрдпрд╢реАрд▓ рд╕рд░реНрд╡рд░ рдорд┐рд▓рдиреЗ рдХреЗ рдмрд╛рдж, рдЗрд╕реЗ рд╡рд░реНрддрдорд╛рди рдХреЗ рд░реВрдк рдореЗрдВ рдЪрд┐рд╣реНрдирд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП:

 // GetNextPeer returns next active peer to take a connection func (s *ServerPool) GetNextPeer() *Backend { // loop entire backends to find out an Alive backend next := s.NextIndex() l := len(s.backends) + next // start from next and move a full cycle for i := next; i < l; i++ { idx := i % len(s.backends) // take an index by modding with length // if we have an alive backend, use it and store if its not the original one if s.backends[idx].IsAlive() { if i != next { atomic.StoreUint64(&s.current, uint64(idx)) // mark the current one } return s.backends[idx] } } return nil } 

рдмреИрдХрдПрдВрдб рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ рджреМрдбрд╝ рдХреА рд╕реНрдерд┐рддрд┐ рд╕реЗ рдмрдЪрдирд╛


рдпрд╣рд╛рдВ рдЖрдкрдХреЛ рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдореБрджреНрджрд╛ рдпрд╛рдж рд░рдЦрдирд╛ рд╣реЛрдЧрд╛ред Backend рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ рдПрдХ рдЪрд░ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдХрдИ рдЧреЛрд░реЛрдирд╛рдЗрдЯ рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ рд╕рдВрд╢реЛрдзрд┐рдд рдпрд╛ рдХреНрд╡реЗрд░реА рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рд╣рдо рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдЧреЛрд░реЛрдЗрдЯрд┐рди рдЗрд╕реЗ рд▓рд┐рдЦрдиреЗ рдХреЗ рдмрдЬрд╛рдп рдЪрд░ рдХреЛ рдкрдврд╝реЗрдЧрд╛ред рдЗрд╕рд▓рд┐рдП, Alive рддрдХ рдкрд╣реБрдВрдЪ рдХреЛ RWMutex рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП Alive рд╣рдордиреЗ RWMutex рдЪреБрдирд╛ред

 // SetAlive for this backend func (b *Backend) SetAlive(alive bool) { b.mux.Lock() b.Alive = alive b.mux.Unlock() } // IsAlive returns true when backend is alive func (b *Backend) IsAlive() (alive bool) { b.mux.RLock() alive = b.Alive b.mux.RUnlock() return } 

рд╕рдВрддреБрд▓рди рдЕрдиреБрд░реЛрдз


рдЕрдм рд╣рдо рдЕрдкрдиреЗ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рд╕рдВрддреБрд▓рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд░рд▓ рд╡рд┐рдзрд┐ рддреИрдпрд╛рд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рддрднреА рд╡рд┐рдлрд▓ рд╣реЛрдЧрд╛ рдЬрдм рд╕рднреА рд╕рд░реНрд╡рд░ рдЧрд┐рд░ рдЬрд╛рдПрдВрдЧреЗред

 // lb load balances the incoming request func lb(w http.ResponseWriter, r *http.Request) { peer := serverPool.GetNextPeer() if peer != nil { peer.ReverseProxy.ServeHTTP(w, r) return } http.Error(w, "Service not available", http.StatusServiceUnavailable) } 

рдЗрд╕ рд╡рд┐рдзрд┐ рдХреЛ HTTP рд╕рд░реНрд╡рд░ рдореЗрдВ рдХреЗрд╡рд▓ рдПрдХ HandlerFunc рд░реВрдк рдореЗрдВ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

 server := http.Server{ Addr: fmt.Sprintf(":%d", port), Handler: http.HandlerFunc(lb), } 

рд╣рдо рдЯреНрд░реИрдлрд┐рдХ рдХреЛ рдХреЗрд╡рд▓ рд░рдирд┐рдВрдЧ рд╕рд░реНрд╡рд░ рддрдХ рд╣реА рд╕реАрдорд┐рдд рдХрд░рддреЗ рд╣реИрдВ


рд╣рдорд╛рд░реЗ рдмреИрд▓реЗрдиреНрд╕рд░ рдореЗрдВ рдПрдХ рдЧрдВрднреАрд░ рд╕рдорд╕реНрдпрд╛ рд╣реИред рд╣рдореЗрдВ рдирд╣реАрдВ рдкрддрд╛ рдХрд┐ рд╕рд░реНрд╡рд░ рдЪрд▓ рд░рд╣рд╛ рд╣реИ рдпрд╛ рдирд╣реАрдВред рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рд╕рд░реНрд╡рд░ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рджреЛ рддрд░реАрдХреЗ рд╣реИрдВ:

  • рд╕рдХреНрд░рд┐рдп: рд╡рд░реНрддрдорд╛рди рдЕрдиреБрд░реЛрдз рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рддреЗ рд╣реБрдП, рд╣рдо рдкрд╛рддреЗ рд╣реИрдВ рдХрд┐ рдЪрдпрдирд┐рдд рд╕рд░реНрд╡рд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдирд╣реАрдВ рджреЗ рд░рд╣рд╛ рд╣реИ, рдФрд░ рдЗрд╕реЗ рдирд┐рд╖реНрдХреНрд░рд┐рдп рдХреЗ рд░реВрдк рдореЗрдВ рдЪрд┐рд╣реНрдирд┐рдд рдХрд░рддрд╛ рд╣реИред
  • рдирд┐рд╖реНрдХреНрд░рд┐рдп: рдЖрдк рдХреБрдЫ рдЕрдВрддрд░рд╛рд▓ рдкрд░ рд╕рд░реНрд╡рд░ рдХреЛ рдкрд┐рдВрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рд╕реНрдерд┐рддрд┐ рдХреА рдЬрд╛рдВрдЪ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рд╕рдХреНрд░рд┐рдп рд░реВрдк рд╕реЗ рдЪрд▓ рд░рд╣реЗ рд╕рд░реНрд╡рд░ рдХреА рдЬрд╛рдБрдЪ


рдпрджрд┐ рдХреЛрдИ рддреНрд░реБрдЯрд┐ ReverseProxy ErrorHandler рдХреЙрд▓рдмреИрдХ рдлрд╝рдВрдХреНрд╢рди рдЖрд░рдВрдн рдХрд░рддрд╛ рд╣реИред рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рд╡рд┐рдлрд▓рддрд╛рдУрдВ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:

 proxy.ErrorHandler = func(writer http.ResponseWriter, request *http.Request, e error) { log.Printf("[%s] %s\n", serverUrl.Host, e.Error()) retries := GetRetryFromContext(request) if retries < 3 { select { case <-time.After(10 * time.Millisecond): ctx := context.WithValue(request.Context(), Retry, retries+1) proxy.ServeHTTP(writer, request.WithContext(ctx)) } return } // after 3 retries, mark this backend as down serverPool.MarkBackendStatus(serverUrl, false) // if the same request routing for few attempts with different backends, increase the count attempts := GetAttemptsFromContext(request) log.Printf("%s(%s) Attempting retry %d\n", request.RemoteAddr, request.URL.Path, attempts) ctx := context.WithValue(request.Context(), Attempts, attempts+1) lb(writer, request.WithContext(ctx)) } 

рдЗрд╕ рддреНрд░реБрдЯрд┐ рд╣реИрдВрдбрд▓рд░ рдХреЛ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдиреЗ рдореЗрдВ, рд╣рдордиреЗ рдХреНрд▓реЛрдЬрд░ рдХреА рдХреНрд╖рдорддрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ред рдпрд╣ рд╣рдореЗрдВ рдмрд╛рд╣рд░реА рдЪрд░ рдЬреИрд╕реЗ рдХрд┐ рд╕рд░реНрд╡рд░ URL рдХреЛ рдЕрдкрдиреА рд╡рд┐рдзрд┐ рдореЗрдВ рдкрдХрдбрд╝рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рд╣реИрдВрдбрд▓рд░ рд░рд┐рдЯреНрд░реА рдХрд╛рдЙрдВрдЯрд░ рдХреА рдЬрд╛рдВрдЪ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдпрджрд┐ рдпрд╣ 3 рд╕реЗ рдХрдо рд╣реИ, рддреЛ рд╣рдо рдлрд┐рд░ рд╕реЗ рдЙрд╕реА рд╕рд░реНрд╡рд░ рдкрд░ рдПрдХ рд╣реА рдЕрдиреБрд░реЛрдз рднреЗрдЬрддреЗ рд╣реИрдВред рдРрд╕рд╛ рдЗрд╕рд▓рд┐рдП рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЕрд╕реНрдерд╛рдпреА рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рдХрд╛рд░рдг, рд╕рд░реНрд╡рд░ рд╣рдорд╛рд░реЗ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рдЫреЛрдбрд╝ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдЬрд▓реНрдж рд╣реА рдЙрдкрд▓рдмреНрдз рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ (рд╕рд░реНрд╡рд░ рдореЗрдВ рдирдП рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреЗ рд▓рд┐рдП рдореБрдлреНрдд рд╕реЙрдХреЗрдЯ рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ)ред рддреЛ рдЖрдкрдХреЛ рд▓рдЧрднрдЧ 10 рдПрдордПрд╕ рдХреЗ рдмрд╛рдж рдПрдХ рдирдП рдкреНрд░рдпрд╛рд╕ рдХреЗ рд▓рд┐рдП рджреЗрд░реА рдЯрд╛рдЗрдорд░ рд╕реЗрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдкреНрд░рддреНрдпреЗрдХ рдЕрдиреБрд░реЛрдз рдХреЗ рд╕рд╛рде рд╣рдо рдкреНрд░рдпрд╛рд╕реЛрдВ рдХреЗ рдХрд╛рдЙрдВрдЯрд░ рдХреЛ рдмрдврд╝рд╛рддреЗ рд╣реИрдВред

рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рдпрд╛рд╕ рдХреА рд╡рд┐рдлрд▓рддрд╛ рдХреЗ рдмрд╛рдж, рд╣рдо рд╕рд░реНрд╡рд░ рдХреЛ рдирд┐рд╖реНрдХреНрд░рд┐рдп рдХреЗ рд░реВрдк рдореЗрдВ рдЪрд┐рд╣реНрдирд┐рдд рдХрд░рддреЗ рд╣реИрдВред

рдЕрдм рдЖрдкрдХреЛ рдЙрд╕реА рдЕрдиреБрд░реЛрдз рдХреЗ рд▓рд┐рдП рдПрдХ рдирдпрд╛ рд╕рд░реНрд╡рд░ рдЕрд╕рд╛рдЗрди рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╣рдо context рдкреИрдХреЗрдЬ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкреНрд░рдпрд╛рд╕ рдХрд╛рдЙрдВрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред рдкреНрд░рдпрд╛рд╕реЛрдВ рдХреЗ рдХрд╛рдЙрдВрдЯрд░ рдХреЛ рдмрдврд╝рд╛рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдо рдЕрдиреБрд░реЛрдз рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдирдП рд╕рд░реНрд╡рд░ рдХрд╛ рдЪрдпрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕реЗ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВред

рд╣рдо рдпрд╣ рдЕрдирд┐рд╢реНрдЪрд┐рдд рдХрд╛рд▓ рддрдХ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рд╣рдо lb рдореЗрдВ рдЬрд╛рдВрдЪ рдХрд░реЗрдВрдЧреЗ рдХрд┐ рдЕрдиреБрд░реЛрдз рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдЬрд╛рд░реА рд░рдЦрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдЕрдзрд┐рдХрддрдо рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдкреНрд░рдпрд╛рд╕ рд╣реБрдП рд╣реИрдВ рдпрд╛ рдирд╣реАрдВред

рдЖрдк рдЕрдиреБрд░реЛрдз рд╕реЗ рдмрд╕ рдкреНрд░рдпрд╛рд╕ рдХрд╛рдЙрдВрдЯрд░ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдпрджрд┐ рдпрд╣ рдЕрдзрд┐рдХрддрдо рддрдХ рдкрд╣реБрдВрдЪрддрд╛ рд╣реИ, рддреЛ рд╣рдо рдЕрдиреБрд░реЛрдз рдХреЛ рдмрд╛рдзрд┐рдд рдХрд░рддреЗ рд╣реИрдВред

 // lb load balances the incoming request func lb(w http.ResponseWriter, r *http.Request) { attempts := GetAttemptsFromContext(r) if attempts > 3 { log.Printf("%s(%s) Max attempts reached, terminating\n", r.RemoteAddr, r.URL.Path) http.Error(w, "Service not available", http.StatusServiceUnavailable) return } peer := serverPool.GetNextPeer() if peer != nil { peer.ReverseProxy.ServeHTTP(w, r) return } http.Error(w, "Service not available", http.StatusServiceUnavailable) } 

рдпрд╣ рдПрдХ рдкреБрдирд░рд╛рд╡рд░реНрддреА рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИред

рд╕рдВрджрд░реНрдн рдкреИрдХреЗрдЬ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛


context рдкреИрдХреЗрдЬ рдЖрдкрдХреЛ HTTP рдЕрдиреБрд░реЛрдзреЛрдВ рдореЗрдВ рдЙрдкрдпреЛрдЧреА рдбреЗрдЯрд╛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рд╣рдо рдЕрдиреБрд░реЛрдзреЛрдВ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдбреЗрдЯрд╛ рдХреЛ рдЯреНрд░реИрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдХреНрд░рд┐рдп рд░реВрдк рд╕реЗ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ - Attempt рдФрд░ Retry рдХрд╛рдЙрдВрдЯрд░ред

рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЖрдкрдХреЛ рд╕рдВрджрд░реНрдн рдХреЗ рд▓рд┐рдП рдХреБрдВрдЬреА рд╕реЗрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдпрд╣ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рдиреЗ рдХреА рд╕рд┐рдлрд╛рд░рд┐рд╢ рдХреА рдЬрд╛рддреА рд╣реИ, рд▓реЗрдХрд┐рди рдЕрджреНрд╡рд┐рддреАрдп рд╕рдВрдЦреНрдпрд╛рддреНрдордХ рдорд╛рдиред рдЧреЛ рдХреЗ рдкрд╛рд╕ рд╕реНрдерд┐рд░рд╛рдВрдХ рдХреЗ рд╡реГрджреНрдзрд┐рд╢реАрд▓ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд▓рд┐рдП рдПрдХ iota рдХреАрд╡рд░реНрдб рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдореЗрдВ рдПрдХ рдЕрджреНрд╡рд┐рддреАрдп рдореВрд▓реНрдп рд╣реИред рдпрд╣ рд╕рдВрдЦреНрдпрд╛рддреНрдордХ рдХреБрдВрдЬрд┐рдпреЛрдВ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╢рд╛рдирджрд╛рд░ рд╕рдорд╛рдзрд╛рди рд╣реИред

 const ( Attempts int = iota Retry ) 

рдлрд┐рд░ рдЖрдк рдорд╛рди рдирд┐рдХрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреИрд╕рд╛ рдХрд┐ рд╣рдо рдЖрдорддреМрд░ рдкрд░ HashMap рд╕рд╛рде рдХрд░рддреЗ рд╣реИрдВред рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдорд╛рди рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рдкрд░ рдирд┐рд░реНрднрд░ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред

 // GetAttemptsFromContext returns the attempts for request func GetRetryFromContext(r *http.Request) int { if retry, ok := r.Context().Value(Retry).(int); ok { return retry } return 0 } 

рдирд┐рд╖реНрдХреНрд░рд┐рдп рд╕рд░реНрд╡рд░ рд╕рддреНрдпрд╛рдкрди


рдирд┐рд╖реНрдХреНрд░рд┐рдп рдЪреЗрдХ рдЧрд┐рд░ рдЧрдП рд╕рд░реНрд╡рд░реЛрдВ рдХреА рдкрд╣рдЪрд╛рди рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВред рд╣рдо рдЙрдирдХреА рд╕реНрдерд┐рддрд┐ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рдЕрдВрддрд░рд╛рд▓ рдкрд░ рдЙрдиреНрд╣реЗрдВ рдкрд┐рдВрдЧ рдХрд░рддреЗ рд╣реИрдВред

рдкрд┐рдВрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЯреАрд╕реАрдкреА рдХрдиреЗрдХреНрд╢рди рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред рдпрджрд┐ рд╕рд░реНрд╡рд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХрд░рддрд╛ рд╣реИ, рддреЛ рд╣рдо рдЗрд╕реЗ рдХрд╛рдо рдХрд░рддреЗ рд╣реБрдП рдЪрд┐рд╣реНрдирд┐рдд рдХрд░рддреЗ рд╣реИрдВред рдЗрд╕ рдкрджреНрдзрддрд┐ рдХреЛ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдПрдВрдбрдкреЙрдЗрдВрдЯреНрд╕ рдЬреИрд╕реЗ /status рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рд╕рд░реНрд╡рд░ рдкрд░ рдЕрддрд┐рд░рд┐рдХреНрдд рд▓реЛрдб рдХреЛ рдХрдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдирд╛рдП рдЬрд╛рдиреЗ рдХреЗ рдмрд╛рдж рдХрдиреЗрдХреНрд╢рди рдХреЛ рдмрдВрдж рдХрд░рдирд╛ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВред рдЕрдиреНрдпрдерд╛, рд╡рд╣ рдЗрд╕ рд╕рдВрдмрдВрдз рдХреЛ рдмрдирд╛рдП рд░рдЦрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдЧрд╛ рдФрд░ рдЕрдВрддрддрдГ рдЕрдкрдиреЗ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреЛ рд╕рдорд╛рдкреНрдд рдХрд░ рджреЗрдЧрд╛ред

 // isAlive checks whether a backend is Alive by establishing a TCP connection func isBackendAlive(u *url.URL) bool { timeout := 2 * time.Second conn, err := net.DialTimeout("tcp", u.Host, timeout) if err != nil { log.Println("Site unreachable, error: ", err) return false } _ = conn.Close() // close it, we dont need to maintain this connection return true } 

рдЕрдм рдЖрдк рд╕рд░реНрд╡рд░ рдХреЛ рдкреБрдирд░рд╛рд╡реГрддреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЙрдирдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдЪрд┐рд╣реНрдирд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

 // HealthCheck pings the backends and update the status func (s *ServerPool) HealthCheck() { for _, b := range s.backends { status := "up" alive := isBackendAlive(b.URL) b.SetAlive(alive) if !alive { status = "down" } log.Printf("%s [%s]\n", b.URL, status) } } 

рдЗрд╕ рдХреЛрдб рдХреЛ рд╕рдордп-рд╕рдордп рдкрд░ рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдк рдЯрд╛рдЗрдорд░ рдХреЛ рдЧреЛ рдореЗрдВ рдЪрд▓рд╛ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рдЖрдкрдХреЛ рдЪреИрдирд▓ рдореЗрдВ рдШрдЯрдирд╛рдУрдВ рдХреЛ рд╕реБрдирдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛ред

 // healthCheck runs a routine for check status of the backends every 2 mins func healthCheck() { t := time.NewTicker(time.Second * 20) for { select { case <-tC: log.Println("Starting health check...") serverPool.HealthCheck() log.Println("Health check completed") } } } 

рдЗрд╕ рдХреЛрдб рдореЗрдВ, <-tC рдЪреИрдирд▓ рд╣рд░ 20 рд╕реЗрдХрдВрдб рдореЗрдВ рдПрдХ рдорд╛рди рд▓реМрдЯрд╛рдПрдЧрд╛ред select рдЖрдкрдХреЛ рдЗрд╕ рдШрдЯрдирд╛ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред default рд╕реНрдерд┐рддрд┐ рдХреА рдЕрдиреБрдкрд╕реНрдерд┐рддрд┐ рдореЗрдВ, рдпрд╣ рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рддрд╛ рд╣реИ рдЬрдм рддрдХ рдХрд┐ рдХрдо рд╕реЗ рдХрдо рдПрдХ рдорд╛рдорд▓реЗ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рдЕрдм рдПрдХ рдЕрд▓рдЧ рдЧреЛрд░реЛрдЗрди рдореЗрдВ рдХреЛрдб рдЪрд▓рд╛рдПрдБ:

 go healthCheck() 

рдирд┐рд╖реНрдХрд░реНрд╖


рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рд╣рдордиреЗ рдХрдИ рд╕рд╡рд╛рд▓реЛрдВ рдХреА рдЬрд╛рдБрдЪ рдХреА:

  • рд░рд╛рдЙрдВрдб рд░реЙрдмрд┐рди рдПрд▓реНрдЧреЛрд░рд┐рдердо
  • рдорд╛рдирдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╕реЗ ReverseProxy
  • mutexes
  • рдкрд░рдорд╛рдгреБ рд╕рдВрдЪрд╛рд▓рди
  • рд╢реЙрд░реНрдЯ рд╕рд░реНрдХрд┐рдЯ
  • рдХреЙрд▓рдмреИрдХ
  • рдЪрдпрди рдСрдкрд░реЗрд╢рди

рд╣рдорд╛рд░реЗ рдмреИрд▓реЗрдВрд╕рд░ рдХреЛ рдмреЗрд╣рддрд░ рдмрдирд╛рдиреЗ рдХреЗ рдХрдИ рдФрд░ рддрд░реАрдХреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:

  • рдЦреЛрдЬ рдЧреБрдВрдЬрд╛рдЗрд╢ рдХрдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд▓рд╛рдЗрд╡ рд╕рд░реНрд╡рд░ рдХреЛ рд╕реЙрд░реНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реАрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред
  • рдЖрдВрдХрдбрд╝реЗ рдЗрдХрдЯреНрдард╛ рдХрд░реЗрдВред
  • рдХрдо рд╕реЗ рдХрдо рдХрдиреЗрдХреНрд╢рди рдХреЗ рд╕рд╛рде рднрд╛рд░рд┐рдд рд░рд╛рдЙрдВрдб-рд░реЙрдмрд┐рди рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЛ рд▓рд╛рдЧреВ рдХрд░реЗрдВред
  • рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдерди рдЬреЛрдбрд╝реЗрдВред

рдФрд░ рдЗрд╕реА рддрд░рд╣ред

рд╕реНрд░реЛрдд рдХреЛрдб рдпрд╣рд╛рдБ рд╣реИ

Source: https://habr.com/ru/post/hi476276/


All Articles