{"id":362376,"date":"2024-05-21T01:33:50","date_gmt":"2024-05-21T01:33:50","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=362376"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=362376","title":{"rendered":"<span>\u0421\u0432\u043e\u0451 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0435 \u043c\u0435\u0436\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u043e\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 \u0431\u043b\u0435\u043a\u0434\u0436\u0435\u043a\u043e\u043c \u0438 gRPC<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0418\u043b\u044c\u044f\u0441. \u041c\u044b \u0441 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 \u0434\u0435\u043b\u0430\u0435\u043c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 Service Mesh \u0432 Ozon Tech, \u0438 \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0437\u0430 \u0432\u0435\u0447\u0435\u0440 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0435 \u0441\u0443\u043f\u0435\u0440 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0435 \u043c\u0435\u0436\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u043e\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435. \u041a \u043a\u043e\u043d\u0446\u0443 \u0441\u0442\u0430\u0442\u044c\u0438 \u043c\u044b \u0441 \u0432\u0430\u043c\u0438 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u043a\u0438, \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u043a\u0430\u043d\u0430\u0440\u0435\u0435\u0447\u043d\u044b\u0435 \u0434\u0435\u043f\u043b\u043e\u0438, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0443\u0437\u043d\u0430\u0435\u043c, \u043a\u0430\u043a \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u0443\u0447\u0443 \u0434\u0440\u0443\u0433\u0438\u0445 \u0441\u0443\u043f\u0435\u0440\u043d\u0435\u043e\u0431\u044b\u0447\u043d\u044b\u0445 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u043e\u0432 \u043c\u0435\u0436\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u043e\u0433\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435, \u043d\u0435 \u043f\u043e\u0432\u0435\u0440\u0438\u0442\u0435, \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 gRPC :D. \u0418 \u0434\u0430, \u043c\u044b \u0441 \u043c\u043e\u0435\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 \u0443\u0436\u0435 \u0440\u0430\u0441\u043a\u0430\u0442\u0438\u043b\u0438 \u044d\u0442\u043e \u043d\u0430 \u0432\u0435\u0441\u044c Ozon Tech, \u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0438\u0439 \u0438\u0437 5000 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u041f\u0440\u0438\u0441\u0442\u0435\u0433\u043d\u0438\u0442\u0435\u0441\u044c \u2014 \u043c\u044b \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u043c\u2026 \ud83d\ude42<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/1d9\/e7f\/fcd\/1d9e7ffcd304211d0f1f1bea58bca467.png\" width=\"1920\" height=\"1080\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/1d9\/e7f\/fcd\/1d9e7ffcd304211d0f1f1bea58bca467.png\"\/><\/figure>\n<p>\u2026 \u043f\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0443.<\/p>\n<h2>\u041c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u0438 \u0435\u0451 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438<\/h2>\n<p>\u0421 \u043f\u0440\u0438\u0445\u043e\u0434\u043e\u043c \u0432 \u043d\u0430\u0448 \u043c\u0438\u0440 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0431\u0435\u043b \u043c\u0435\u0436\u0434\u0443 \u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b \u043e\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043f\u043e \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0432\u044f\u0437\u043d\u043e\u0441\u0442\u0438 \u044d\u0442\u0438\u0445 \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u0421\u0430\u043c\u044b\u043c \u043f\u0440\u043e\u0441\u0442\u044b\u043c \u0438 \u043b\u043e\u0433\u0438\u0447\u043d\u044b\u043c \u0431\u044b\u043b\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u0442 \u0436\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0442\u0440\u0430\u0444\u0438\u043a \u043e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e \u2014 HTTP. \u041d\u043e \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441 \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u043d\u0430 \u043c\u0435\u0441\u0442\u0435. \u0414\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u043b\u0438 \u0442\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434, \u043a\u0430\u043a RPC (remote procedure call, \u0438\u043b\u0438 \u043d\u0430 \u0432\u0435\u043b\u0438\u043a\u043e\u043c \u0438 \u043c\u043e\u0433\u0443\u0447\u0435\u043c \u2013 \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u044b\u0439 \u0432\u044b\u0437\u043e\u0432 \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u044b). \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0439 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u2014 \u043a\u0430\u043a \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 JSON \u0432 \u043f\u0440\u0438\u0432\u044b\u0447\u043d\u044b\u0445 HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445, \u0442\u0430\u043a \u0438 \u0443\u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0431\u043e\u043b\u0435\u0435 \u0441\u0436\u0430\u0442\u043e\u043c \u0432\u0438\u0434\u0435. \u0421\u0430\u043c\u044b\u0439 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0439 \u0438 \u0443\u0432\u0430\u0436\u0430\u0435\u043c\u044b\u0439 \u0432 Ozon Tech \u2014 gRPC. \u0411\u043e\u043b\u044c\u0448\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0433\u043e \u043c\u0435\u0436\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u043e\u0433\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0432 \u043d\u0430\u0448\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430.\u00a0<\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0440\u0435\u0447\u044c \u043f\u043e\u0439\u0434\u0451\u0442 \u043d\u0435 \u043f\u0440\u043e \u00ab\u0440\u0435\u043a\u043b\u0430\u043c\u043d\u044b\u0435\u00bb \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430 gRPC, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a \u0432\u044b\u0441\u043e\u043a\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c, \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u043e \u0438 \u0442. \u0434., \u0430 \u043a\u043e\u0435 \u043e \u0447\u0451\u043c \u043d\u0435\u043e\u0431\u044b\u0447\u043d\u043e\u043c, \u0447\u0442\u043e \u043a\u043e\u0433\u0434\u0430-\u0442\u043e \u043b\u0438\u0447\u043d\u043e \u043c\u0435\u043d\u044f \u043f\u043e\u0440\u0430\u0437\u0438\u043b\u043e, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e \u2014 \u043e \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u043e\u043c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u0435 \u043f\u043e\u0438\u0441\u043a\u0430 \u0430\u0434\u0440\u0435\u0441\u043e\u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0441\u043e\u0432\u0435\u0440\u0448\u0430\u044e\u0442\u0441\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u044b, \u043e \u043c\u0435\u043d\u0435\u0434\u0436\u043c\u0435\u043d\u0442\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 \u043a \u0440\u0430\u0437\u043d\u044b\u043c \u0435\u0433\u043e \u0430\u0434\u0440\u0435\u0441\u0430\u043c, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u043a\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043c\u0435\u0436\u0434\u0443 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u043a\u043e\u043f\u0438\u044f\u043c\u0438 \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041d\u0443 \u0438\u043b\u0438, \u0435\u0441\u043b\u0438 \u043a\u043e\u0440\u043e\u0442\u043a\u043e, &#8212; \u0440\u0435\u0447\u044c \u043f\u0440\u043e Resolver, Balancer \u0438 Picker \u0432 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 gRPC-go \ud83d\ude42<\/p>\n<p>\u041c\u044b \u043f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u043c\u0441\u044f \u0441\u043e \u0432\u0441\u0435\u043c\u0438 \u044d\u0442\u0438\u043c\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438, \u043f\u0440\u0435\u043f\u0430\u0440\u0438\u0440\u0443\u0435\u043c \u0438\u0445 \u0438 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u0430\u0436\u0434\u043e\u0439 \u0438\u0437 \u043d\u0438\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0442 \u043d\u0430\u043c \u043a \u043a\u043e\u043d\u0446\u0443 \u0441\u0442\u0430\u0442\u044c\u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f\u043c\u0438 \u043c\u0435\u0436\u0434\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438. \u0421\u0442\u0430\u0442\u044c\u044f \u043d\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0430 \u043a\u043e\u0434\u043e\u043c, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u043c \u043d\u0430 Go, \u043d\u043e \u0432 \u0446\u0435\u043b\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043c\u0430 \u0438 \u043a \u0434\u0440\u0443\u0433\u0438\u043c \u044f\u0437\u044b\u043a\u0430\u043c, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0435\u0441\u0442\u044c \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f gRPC \u043e\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 Google (\u0421#, Java, C++, JavaScript, Swift \u0438 <a href=\"https:\/\/grpc.io\/docs\/languages\/\"><u>\u0434\u0440\u0443\u0433\u0438\u0445<\/u><\/a>). \u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f\u0437\u044b\u043a\u0438 \u0438\u043c\u0435\u044e\u0442 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e, \u0430 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u2014 \u043e\u0431\u0451\u0440\u0442\u043a\u0443 \u043d\u0430\u0434 \u0433\u043b\u0430\u0432\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 \u043d\u0430 \u0421.\u00a0<\/p>\n<h2>\u041a\u043e\u0433\u0434\u0430 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430?<\/h2>\n<p>\u041a\u043e\u0433\u0434\u0430 \u043c\u043e\u043d\u043e\u043b\u0438\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0442 \u0440\u0430\u0441\u043f\u0438\u043b\u0438\u0432\u0430\u0442\u044c \u043d\u0430 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0438\u043b\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442 \u043d\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442, \u0432\u0441\u044f \u0438\u043d\u0441\u0442\u0430\u043b\u043b\u044f\u0446\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0447\u0430\u0441\u0442\u0435\u0439 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0447\u0430\u0442\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0438\u0437 \u043e\u0434\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0432 \u0434\u0440\u0443\u0433\u043e\u0439, \u043c\u043e\u0436\u043d\u043e \u043b\u0438\u0431\u043e \u0437\u0430\u0445\u0430\u0440\u0434\u043a\u043e\u0434\u0438\u0442\u044c \u0430\u0434\u0440\u0435\u0441\u0430 \u0441\u0435\u0440\u0432\u0430\u043a\u043e\u0432 \u0438\u043b\u0438 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u043e\u043a, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0445\u043e\u0441\u0442\u0438\u0442\u0441\u044f \u043d\u0443\u0436\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c, \u043b\u0438\u0431\u043e \u043f\u043e\u0434\u0442\u044e\u043d\u0438\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 DNS, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0442\u0443\u0434\u0430 \u0437\u0430\u043f\u0438\u0441\u0438 \u0441 \u0430\u0434\u0440\u0435\u0441\u0430\u043c\u0438 \u044d\u0442\u0438\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432, \u0438 \u0440\u0435\u0437\u043e\u043b\u0432\u0438\u0442\u044c \u0430\u0434\u0440\u0435\u0441\u0430 \u0447\u0435\u0440\u0435\u0437 \u043d\u0435\u0433\u043e. \u041d\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u044d\u0442\u043e\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 Service Discovery (\u0434\u0430-\u0434\u0430, \u043f\u043e\u0438\u0441\u043a \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 :)). \u041d\u043e, \u043a\u043e\u0433\u0434\u0430 \u044d\u0442\u0438 \u0435\u0434\u0438\u043d\u0438\u0446\u044b \u0438 \u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u044e\u0442\u0441\u044f \u0432 \u0441\u043e\u0442\u043d\u0438 \u0438 \u0442\u044b\u0441\u044f\u0447\u0438, \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0442\u0441\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b. \u0410 \u0435\u0441\u043b\u0438 \u0435\u0449\u0451 \u0432\u0441\u0435 \u044d\u0442\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0437\u0430\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u044e\u0442 \u0432 Kubernetes, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0438\u043c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u0435\u0440\u0435\u0435\u0437\u0436\u0430\u0442\u044c \u0441 \u043e\u0434\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043d\u0430 \u0434\u0440\u0443\u0433\u043e\u0439, \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441\u0443\u0449\u0438\u0439 \u0430\u0434. \u041d\u043e \u0435\u0441\u0442\u044c \u00ab\u043a\u043e\u0440\u043e\u0431\u043e\u0447\u043d\u043e\u0435\u00bb \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u2014 Service Mesh, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c\u044b\u0439 \u0441\u0430\u0439\u0434\u043a\u0430\u0440\u043e\u043c (\u043f\u0440\u0438\u0432\u0435\u0442, Envoy \u0438 Linkerd :)).<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u0442\u043e \u0442\u0430\u043a\u043e\u0439 \u044d\u0442\u043e\u0442 \u0432\u0430\u0448 Service Mesh???<\/summary>\n<div class=\"spoiler__content\">\n<p>Service Mesh \u2014 \u044d\u0442\u043e <a href=\"https:\/\/istio.io\/latest\/about\/service-mesh\/#what-is-a-service-mesh\"><u>\u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043d\u044b\u0439 \u0441\u043b\u043e\u0439<\/u><\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432 \u043e\u0431\u0449\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u043f\u043e\u0438\u0441\u043a IP-\u0430\u0434\u0440\u0435\u0441\u043e\u0432 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432, \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439, \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u043a\u0443 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438, \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u0435 \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0440\u0430\u0444\u0438\u043a\u0430 \u0438 \u043f\u0440\u043e\u0447\u0438\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u0442\u043e\u043c \u043f\u0440\u043e\u0431\u0435\u043b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0438 \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u0430 \u043d\u0430 \u0447\u0430\u0441\u0442\u0438.\u00a0<\/p>\n<p>\u041e\u0431\u044b\u0447\u043d\u043e \u0432\u0441\u0435 \u043e\u043d\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0442\u0441\u044f \u043f\u0443\u0442\u0451\u043c \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043a \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e \u043d\u0435\u043a\u043e\u0435\u0433\u043e \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u043e\u0433\u043e \u0441\u0430\u0439\u0434\u043a\u0430\u0440\u043e\u043c, \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u0440\u043e\u043a\u0441\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432\u0435\u0441\u044c \u0442\u0440\u0430\u0444\u0438\u043a. \u041e\u043d\u043e \u043a\u0443\u0434\u0430-\u0442\u043e \u0441\u043e\u0432\u0435\u0440\u0448\u0430\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u044b, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u0430\u0434\u0440\u0435\u0441\u043e\u0432, \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u043a\u043e\u043d\u043d\u0435\u043a\u0442\u044b \u0438 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430 \u043d\u0438\u0445 \u0442\u0440\u0430\u0444\u0438\u043a (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, Envoy \u0434\u0435\u043b\u0430\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 Istio, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0432\u0441\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043f\u0440\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0432\u044b\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u0442 \u0438\u0437 Kubernetes API). \u0418 \u044f \u043d\u0430\u0437\u0432\u0430\u043b \u044d\u0442\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u00ab\u043a\u043e\u0440\u043e\u0431\u043e\u0447\u043d\u044b\u043c\u00bb, \u0442\u0430\u043a \u043a\u0430\u043a \u0435\u0433\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043b\u0435\u0433\u043a\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043a \u0432\u0430\u0448\u0435\u043c\u0443 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0443 Kubernetes, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u043f\u0440\u0430\u0432\u0438\u043b\u043e \u043d\u0430 \u0438\u043d\u044a\u0435\u043a\u0446\u0438\u044e \u0441\u0430\u0439\u0434\u043a\u0430\u0440\u0430 \u043a \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u0432 Kubernetes.\u00a0<\/p>\n<\/div>\n<\/details>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f gRPC \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u0442\u0435\u043c, \u0447\u0442\u043e \u0432\u0441\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u0438, \u043f\u043e \u0441\u0443\u0442\u0438, \u0432\u0448\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u0431\u0438\u043d\u0430\u0440\u044c \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0422\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u0445\u043e\u0440\u043e\u0448 \u0442\u0435\u043c, \u0447\u0442\u043e \u043e\u043d \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432, \u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u0441\u0430\u0439\u0434\u043a\u0430\u0440\u043e\u0432 (\u0442\u0430\u043a \u043a\u0430\u043a \u0441\u0430\u0439\u0434\u043a\u0430\u0440 \u2014 \u044d\u0442\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f). \u041d\u043e, \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435, \u0435\u0441\u0442\u044c \u043d\u044e\u0430\u043d\u0441\u044b, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441 \u0443\u0441\u043b\u043e\u0436\u043d\u0435\u043d\u0438\u0435\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e, \u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u0441\u0430\u0439\u0434\u043a\u0430\u0440\u0430, \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u0435\u0440\u0441\u0438\u0438 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u0432\u0441\u0451 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u0435\u0435 \u0438 \u0434\u043e\u043b\u044c\u0448\u0435, \u0447\u0435\u043c \u0437\u0430\u043c\u0435\u043d\u0430 \u0431\u0438\u043d\u0430\u0440\u044f \u0432 \u0441\u0430\u0439\u0434\u043a\u0430\u0440\u0435. \u0421\u0435\u0440\u0435\u0431\u0440\u044f\u043d\u043e\u0439 \u043f\u0443\u043b\u0438 \u0432\u0441\u0451 \u0435\u0449\u0451 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \ud83d\ude41<\/p>\n<h2>\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<details class=\"spoiler\">\n<summary>\u041d\u0435\u043c\u043d\u043e\u0433\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0439<\/summary>\n<div class=\"spoiler__content\">\n<p>\u041f\u0430\u0440\u0430 \u0441\u043b\u043e\u0432 \u043e\u0431 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u0445. \u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043d\u0435\u043a\u0438\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 1, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043d\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u041a\u041b\u0418\u0415\u041d\u0422\u041e\u041c, \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0432\u0435\u0440\u0448\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a \u043d\u0435\u043a\u043e\u0435\u043c\u0443 \u0441\u0435\u0440\u0432\u0438\u0441\u0443 2, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043d\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0411\u042d\u041a\u0415\u041d\u0414\u041e\u041c.\u00a0<\/p>\n<\/div>\n<\/details>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0451\u043c \u043e\u0442 \u0441\u043b\u043e\u0432 \u043a \u0434\u0435\u043b\u0443. \u041a\u043e\u0433\u0434\u0430 \u043c\u044b \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a \u043d\u0443\u0436\u043d\u043e\u043c\u0443 \u043d\u0430\u043c \u0431\u044d\u043a\u0435\u043d\u0434\u0443 \u0447\u0435\u0440\u0435\u0437 gRPC, \u043c\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e <a href=\"https:\/\/github.com\/grpc\/grpc-go\/blob\/c2398ced0efdd5151b4322922b20459b3d37a0d4\/clientconn.go#L105\"><u>grpc.Dial<\/u><\/a>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f, \u043f\u043e\u043c\u0438\u043c\u043e \u043e\u0448\u0438\u0431\u043a\u0438 (\u0432\u0441\u0451 \u0432 \u0436\u0438\u0437\u043d\u0438 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0439\u0442\u0438 \u043d\u0435 \u0442\u0430\u043a :D), \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043d\u0435\u043a\u0438\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 ClientConn. \u042d\u0442\u043e \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u0432 gRPC, \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0438\u0440\u0443\u044e\u0442 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b Service Discovery, Load Balancing \u0438 \u0434\u0440\u0443\u0433\u0438\u0435. \u0422\u0430\u043a\u0436\u0435 ClientConn \u043f\u0440\u043e\u043a\u0441\u0438\u0440\u0443\u0435\u0442 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u044d\u0442\u0438\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 (\u0447\u0443\u0442\u044c \u043f\u043e\u0437\u0436\u0435 \u0443\u0432\u0438\u0434\u0438\u043c).<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d75\/13f\/95d\/d7513f95d18a1fb970f51b331a5e0180.png\" alt=\"\u041d\u0430 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0430\u0445 \u043d\u0438\u0436\u0435 \u043e\u0431\u044a\u0435\u043a\u0442 \u041a\u041b\u0418\u0415\u041d\u0422 (\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430) \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f\" title=\"\u041d\u0430 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0430\u0445 \u043d\u0438\u0436\u0435 \u043e\u0431\u044a\u0435\u043a\u0442 \u041a\u041b\u0418\u0415\u041d\u0422 (\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430) \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f\" width=\"17156\" height=\"8274\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d75\/13f\/95d\/d7513f95d18a1fb970f51b331a5e0180.png\"\/><\/p>\n<div><figcaption><em>\u041d\u0430 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0430\u0445 \u043d\u0438\u0436\u0435 \u043e\u0431\u044a\u0435\u043a\u0442 \u041a\u041b\u0418\u0415\u041d\u0422 (\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430) \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f<\/em><\/figcaption><\/div>\n<\/figure>\n<h2>Resolver<\/h2>\n<h3>\u0421 \u0447\u0435\u0433\u043e \u043d\u0430\u0447\u0430\u0442\u044c?<\/h3>\n<p>\u0427\u0442\u043e\u0431\u044b \u043d\u0430\u043c \u043d\u0430\u0447\u0430\u0442\u044c \u0441\u043e\u0432\u0435\u0440\u0448\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b, \u043d\u0430\u0434\u043e \u043f\u043e\u043d\u044f\u0442\u044c, \u043a\u0443\u0434\u0430 \u0438\u0445 \u0441\u043e\u0432\u0435\u0440\u0448\u0430\u0442\u044c. \u041e\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u043d\u0438\u0436\u0435 \u0441\u0435\u0442\u0435\u0432\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f \u043f\u043e \u043c\u043e\u0434\u0435\u043b\u0438 OSI \u043c\u044b \u043d\u0435 \u0431\u0443\u0434\u0435\u043c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u0442\u0432\u0435\u0442\u043e\u043c \u043d\u0430 \u0432\u043e\u043f\u0440\u043e\u0441 \u00ab\u043a\u0443\u0434\u0430?\u00bb \u0431\u0443\u0434\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a IP-\u0430\u0434\u0440\u0435\u0441\u043e\u0432. \u041c\u044b \u0437\u043d\u0430\u0435\u043c, \u0447\u0442\u043e \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u0435\u043a\u0438\u0439 \u0431\u044d\u043a\u0435\u043d\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043a\u0430\u043a-\u0442\u043e \u0441\u0435\u0431\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u0442 (\u043f\u0443\u0441\u0442\u044c \u0443 \u043d\u0435\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u043a\u0430\u043a\u043e\u0435-\u0442\u043e \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0435 \u0438\u043c\u044f, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043d\u0430\u043c \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e, \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u044d\u0442\u043e \u0438\u043c\u044f \u0435\u043c\u0443 \u0434\u0430\u043b\u0438 \u043b\u0438\u0431\u043e \u043c\u044b, \u043b\u0438\u0431\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0438\u0437 \u0441\u043e\u0441\u0435\u0434\u043d\u0435\u0433\u043e \u043e\u0442\u0434\u0435\u043b\u0430. \u041c\u043e\u0436\u043d\u043e \u0441\u0445\u043e\u0434\u0438\u0442\u044c \u043a \u043d\u0438\u043c \u0438 \u0441\u043f\u0440\u043e\u0441\u0438\u0442\u044c :)).<\/p>\n<p>\u0412\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u043c <a href=\"https:\/\/github.com\/grpc\/grpc-go\/blob\/master\/examples\/helloworld\/greeter_server\/main.go\"><u>gRPC hello-\u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/u><\/a>. \u041d\u0430 \u0434\u0430\u043d\u043d\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u043d\u0430\u043c \u043d\u0430\u0434\u043e \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u0442\u044c \u043d\u0435\u043a\u0438\u0439 \u043e\u0431\u044a\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u043b\u043e\u0433\u0438\u043a\u043e\u0439 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0430\u0434\u0440\u0435\u0441\u043e\u0432 \u0431\u044d\u043a\u0435\u043d\u0434\u0430, \u0442\u043e \u0435\u0441\u0442\u044c \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u0442\u044c \u0438\u043c\u044f \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u0430\u0434\u0440\u0435\u0441\u043e\u0432. \u0412 gRPC \u043e\u043d \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f Resolver. \u0415\u0433\u043e \u0437\u0430\u0434\u0430\u0447\u0435\u0439 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0432\u0435\u0440\u0448\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u0432 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0430\u0434\u0440\u0435\u0441\u043e\u0432, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0432 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438. \u041d\u0443 \u0430 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, DNS-\u0441\u043b\u0443\u0436\u0431\u0430. \u0415\u0451 IP-\u0430\u0434\u0440\u0435\u0441 \u0432\u0441\u0435\u0433\u0434\u0430 \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435.\u00a0<\/p>\n<h3>\u041d\u0430\u0433\u043b\u044f\u0434\u043d\u044b\u0439 \u043c\u043e\u043a DNS-\u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/h3>\n<p>\u0414\u043b\u044f \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u043e\u0441\u0442\u0438 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043c\u043e\u043a DNS-\u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u2014 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043d\u0430 HTTP GET-\u0437\u0430\u043f\u0440\u043e\u0441 \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a IP-\u0430\u0434\u0440\u0435\u0441\u043e\u0432 \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0431\u044d\u043a\u0435\u043d\u0434\u0430. \u041d\u0430 \u043f\u043e\u0440\u0442\u0443 8081 \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u043c HTTP-\u0441\u0435\u0440\u0432\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430 GET \u0437\u0430\u043f\u0440\u043e\u0441 <code>\u201c\/endpoints\u201d<\/code> \u0441 query-\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c target \u0432\u0435\u0440\u043d\u0451\u0442 \u0430\u0434\u0440\u0435\u0441 \u0441 \u043f\u043e\u0440\u0442\u043e\u043c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u044e\u0449\u0435\u0433\u043e \u043d\u0430\u0441 \u0441\u0435\u0440\u0432\u0438\u0441\u0430. \u0412\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043e\u043d\u043e \u043a\u0430\u043a-\u0442\u043e \u0442\u0430\u043a:\u00a0<\/p>\n<pre><code class=\"go\">func main() { http.HandleFunc(\"\/endpoints\", HandleEndpointRequest) err := http.ListenAndServe(\"localhost:8081\", nil) if err != nil { log.Fatal(err) } } func HandleEndpointRequest(w http.ResponseWriter, req *http.Request) { log.Println(\"new request with query:\", req.URL.RawQuery) target := req.URL.Query().Get(\"target\") switch target { case \"helloworld_server\": _, err := w.Write([]byte(\"127.0.0.1:8080\")) if err != nil { log.Println(err) } default: w.WriteHeader(http.StatusNotFound) } } <\/code><\/pre>\n<h3>\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f Resolver<\/h3>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a Resolver\u2019\u0443 \u0438 \u0443\u0436\u0435 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043a gRPC. \u0414\u043b\u044f \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f <a href=\"https:\/\/github.com\/grpc\/grpc-go\/blob\/1b05500d8019885575a37efa2e961e278d680ee9\/resolver\/resolver.go#L51\"><u>\u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0431\u0438\u043b\u0434\u0435\u0440 Resolver<\/u><\/a>\u2019\u0430 \u0432 gRPC.<\/p>\n<pre><code class=\"go\">rb := &amp;ResolverBuilder{} resolver.Register(rb)<\/code><\/pre>\n<p>\u0421\u0430\u043c \u0431\u0438\u043b\u0434\u0435\u0440 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 <a href=\"https:\/\/github.com\/grpc\/grpc-go\/blob\/1b05500d8019885575a37efa2e961e278d680ee9\/resolver\/resolver.go#L290\"><u>\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441<\/u><\/a> \u2014 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 Build \u0438 Scheme. Build \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u0438\u043d\u0441\u0442\u0430\u043d\u0441 Resolver, \u0430 Scheme \u2014 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u0443 \u0441 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c \u043d\u0430\u0448\u0435\u0433\u043e Resolver. \u041c\u044b \u043f\u043e\u0437\u0436\u0435 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a \u0441\u0435\u0440\u0432\u0438\u0441\u0443. ClientConn, \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0442\u043e\u0442 Resolver, \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f (<a href=\"https:\/\/github.com\/grpc\/grpc\/blob\/master\/doc\/naming.md\"><u>\u0440\u0435\u0437\u043e\u043b\u044e\u0446\u0438\u044f \u0438\u043c\u0451\u043d<\/u><\/a>).\u00a0<\/p>\n<pre><code class=\"go\">type Builder interface { Build(target Target, cc ClientConn, opts BuildOptions) (Resolver, error) Scheme() string } <\/code><\/pre>\n<p>\u041d\u0430\u0437\u043e\u0432\u0451\u043c \u043d\u0430\u0448 Resolver <strong>habr<\/strong>. <\/p>\n<pre><code class=\"go\">func (b *ResolverBuilder) Scheme() string { return \"habr\" } <\/code><\/pre>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043a\u043e\u0433\u0434\u0430 \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f grpc.Dial, \u044d\u0442\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043d\u0430 \u0432\u0445\u043e\u0434 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0430\u0434\u0440\u0435\u0441, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f:<\/p>\n<p> <code>grpc.Dial(\u201cozon.ru\u201d, opts...)<\/code><\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0432\u044b\u0431\u0440\u0430\u0442\u044c Resolver, \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434 \u0430\u0434\u0440\u0435\u0441\u043e\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e \u0441\u0445\u0435\u043c\u0443:<\/p>\n<p>\u00a0<code>grpc.Dial(\u201chabr:\/\/\/ozon.ru\u201d, opts...)<\/code><\/p>\n<p>\u041f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 Dial \u044d\u0442\u0430 \u0441\u0442\u0440\u043e\u043a\u0430 \u0440\u0430\u0441\u043f\u0430\u0440\u0441\u0438\u0442\u0441\u044f \u2014 \u0438 \u0438\u0437 \u043c\u0430\u043f\u044b \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0431\u0438\u043b\u0434\u0435\u0440\u043e\u0432 Resolver\u2019\u043e\u0432 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0431\u0440\u0430\u043d \u043d\u0443\u0436\u043d\u044b\u0439, \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d Resolver:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/359\/891\/a7a\/359891a7a81432af0f0dab905cfa5540.png\" width=\"17156\" height=\"8274\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/359\/891\/a7a\/359891a7a81432af0f0dab905cfa5540.png\"\/><\/figure>\n<h3>\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0441\u0430\u043c\u043e\u0433\u043e Resolver<\/h3>\n<p><a href=\"https:\/\/github.com\/grpc\/grpc-go\/blob\/c2398ced0efdd5151b4322922b20459b3d37a0d4\/resolver\/resolver.go#L308\"><u>\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 Resolver<\/u><\/a> \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u043e\u0441\u0442. \u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f Resolver (Close) \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f ResolveNow. \u0421 \u0444\u0443\u043a\u043d\u0446\u0438\u0435\u0439 Close \u0432\u0441\u0451 \u043f\u043e\u043d\u044f\u0442\u043d\u043e: \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0433\u043e\u0432\u043e\u0440\u0438\u0442 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043f\u0440\u0438 \u0435\u0451 \u0432\u044b\u0437\u043e\u0432\u0435 Resolver \u0434\u043e\u043b\u0436\u0435\u043d \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u0441\u0432\u043e\u044e \u0440\u0430\u0431\u043e\u0442\u0443. \u041d\u0443 \u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f ResolveNow \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432\u044b\u0437\u0432\u0430\u043d\u0430 ClientConn \u0434\u043b\u044f \u0444\u043e\u0440\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0440\u0435\u0437\u043e\u043b\u0432\u0438\u043d\u0433\u0430 \u0430\u0434\u0440\u0435\u0441\u043e\u0432 \u0432 \u0440\u044f\u0434\u0435 \u044d\u043a\u0441\u0442\u0440\u0435\u043d\u043d\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0438\u0436\u0435 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u043b\u0438 \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f \u043d\u0438 \u043a \u043e\u0434\u043d\u043e\u043c\u0443 \u0438\u0437 \u0440\u0430\u043d\u0435\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u0430\u0434\u0440\u0435\u0441\u043e\u0432; \u043f\u043b\u044e\u0441 \u043e\u043d\u0430 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432\u044b\u0437\u0432\u0430\u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437 \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u043d\u043e). \u041f\u0440\u043e\u0441\u0442\u043e\u0439 Resolver \u043c\u043e\u0436\u0435\u0442 \u044d\u0442\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c. \u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u044b Resolver \u0434\u043e\u043b\u0436\u043d\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u0435\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432 \u0444\u043e\u043d\u0435 (\u0442\u043e \u0435\u0441\u0442\u044c \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0433\u043e\u0440\u0443\u0442\u0438\u043d\u0435), \u043d\u0430\u043f\u043e\u043b\u043d\u044f\u044f ClientConn \u0430\u0434\u0440\u0435\u0441\u0430\u043c\u0438.<\/p>\n<pre><code class=\"go\">type Resolver interface {    ResolveNow(ResolveNowOptions)    Close() } <\/code><\/pre>\n<p>\u0412 \u0444\u0443\u043d\u043a\u0446\u0438\u044e Build \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e \u0442\u0430\u0440\u0433\u0435\u0442\u0435 (\u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u0430, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f, \u0432 \u0432\u0438\u0434\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b URL \u0438\u0437 std \u043f\u0430\u043a\u0435\u0442\u0430 <code>net\/url<\/code>), \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 ClientConn (\u043e\u0431\u0451\u0440\u043d\u0443\u0442\u044b\u0439 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u043f\u0440\u043e\u043a\u0441\u0438\u0440\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u0434\u043b\u044f Resolver) \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0432 \u043d\u0435\u0433\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 BuildOptions.\u00a0<\/p>\n<pre><code class=\"go\">func (b *ResolverBuilder) Build(target resolver.Target, cc resolver.ClientConn, _ resolver.BuildOptions) (resolver.Resolver, error) { ctx, cancel := context.WithCancel(context.Background()) r := &amp;Resolver{ target: target.Endpoint, ctx:    ctx, cancel: cancel, wg:     sync.WaitGroup{}, cc:     cc, } r.wg.Add(1) \/\/ \u0422\u0430 \u0441\u0430\u043c\u0430\u044f \u0433\u043e\u0440\u0443\u0442\u0438\u043d\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432 \u0444\u043e\u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0430\u0434\u0440\u0435\u0441\u0430 go r.watch() return r, nil } <\/code><\/pre>\n<p>\u041f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 Resolver \u0431\u0443\u0434\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0433\u043e\u0440\u0443\u0442\u0438\u043d\u0443 \u0441 \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 watch. \u041e\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0432\u0435\u0440\u0448\u0430\u0442\u044c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435: \u0440\u0430\u0437 \u0432 5 \u0441\u0435\u043a\u0443\u043d\u0434 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c \u043d\u0435\u043a\u0438\u0439 lookup \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0433\u043e target. <\/p>\n<pre><code class=\"go\">func (r *Resolver) watch() { defer r.wg.Done() r.lookup(r.target) ticker := time.NewTicker(5 * time.Second) for { select { case &lt;-r.ctx.Done(): return case &lt;-ticker.C: r.lookup(r.target) } } } <\/code><\/pre>\n<p>\u0412 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 lookup \u0436\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0434\u0435\u043b\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u043a \u0432\u044b\u0448\u0435\u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u043c\u0443 \u043c\u043e\u043a\u0443 DNS-\u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u0430 \u0432 \u043a\u043e\u043d\u0446\u0435 \u2014 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0432 ClientConn \u0434\u043b\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 (\u0432\u0435\u0440\u043d\u0451\u043c\u0441\u044f \u043a \u044d\u0442\u043e\u043c\u0443 \u0447\u0443\u0442\u044c \u043f\u043e\u0437\u0436\u0435). \u0414\u043b\u044f \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f \u043e\u043f\u0443\u0441\u0442\u0438\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043e\u0448\u0438\u0431\u043e\u043a, \u0437\u0430\u043c\u0435\u043d\u0438\u0432 \u0438\u0445 \u043d\u0430 \u0432\u044b\u0432\u043e\u0434 \u043b\u043e\u0433\u0430.<\/p>\n<pre><code class=\"go\">func (r *Resolver) lookup(target string) { resp, err := http.Get(fmt.Sprintf(\"http:\/\/%s\/endpoints?target=%s\", lookupServerHostPort, target)) if err != nil { log.Println(err) return } data, err := io.ReadAll(resp.Body) if err != nil { log.Println(err) return } addrs := strings.Split(string(data), \" \") log.Println(\"resolver made request:\", addrs) newAddrs := make([]resolver.Address, 0, len(addrs)) for _, a := range addrs { newAddrs = append(newAddrs, resolver.Address{Addr: a}) } \/\/ \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0430\u0434\u0440\u0435\u0441\u0430 \u0432 ClientConn err = r.cc.UpdateState(resolver.State{ Addresses: newAddrs, ServiceConfig: defaultServiceConfig, }) if err != nil { log.Println(err) return } } <\/code><\/pre>\n<p>\u041d\u0443 \u0438 \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u0430\u0434\u0440\u0435\u0441\u043e\u0432 \u0438 \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0435\u0433\u043e \u0432 \u043d\u0443\u0436\u043d\u044b\u0439 \u043d\u0430\u043c \u0432\u0438\u0434, \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c \u044d\u0442\u0443 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u0431\u0440\u0430\u0442\u043d\u043e ClientConn \u0447\u0435\u0440\u0435\u0437 \u0444\u0443\u043d\u043a\u0446\u0438\u044e UpdateState. \u041d\u0430 \u044d\u0442\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043c\u044b \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0447\u0443\u0442\u044c \u043f\u043e\u0437\u0436\u0435, \u0430 \u043f\u043e\u043a\u0430 \u043f\u0440\u043e\u0441\u0442\u043e \u0431\u0443\u0434\u0435\u043c \u0441\u0447\u0438\u0442\u0430\u0442\u044c, \u0447\u0442\u043e \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0441\u043f\u0438\u0441\u043e\u043a \u0430\u0434\u0440\u0435\u0441\u043e\u0432 \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u043b\u0438 \u0435\u0433\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043a\u0443\u0434\u0430-\u0442\u043e \u0434\u0430\u043b\u044c\u0448\u0435.\u00a0<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/26c\/845\/193\/26c8451935d6a4ec93130c1d3e234570.png\" width=\"17156\" height=\"8274\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/26c\/845\/193\/26c8451935d6a4ec93130c1d3e234570.png\"\/><\/figure>\n<h3>\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b<\/h3>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0432\u0441\u0435 \u043d\u0430\u0448\u0438 3 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f: \u043c\u043e\u043a\u0438 DNS-\u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0441 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u043c Resolver. <\/p>\n<details class=\"spoiler\">\n<summary>\u041b\u043e\u0433\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430:<\/summary>\n<div class=\"spoiler__content\">\n<p>2023\/10\/21 16:45:17 resolver made request: [127.0.0.1:8080]<\/p>\n<p>2023\/10\/21 16:45:17 Greeting: Hello OzonTech<\/p>\n<p>2023\/10\/21 16:45:19 Greeting: Hello OzonTech<\/p>\n<p>2023\/10\/21 16:45:21 Greeting: Hello OzonTech<\/p>\n<p>2023\/10\/21 16:45:22 resolver made request: [127.0.0.1:8080]<\/p>\n<p>2023\/10\/21 16:45:23 Greeting: Hello OzonTech<\/p>\n<p>2023\/10\/21 16:45:25 Greeting: Hello OzonTech<\/p>\n<p>2023\/10\/21 16:45:27 resolver made request: [127.0.0.1:8080]<\/p>\n<p>2023\/10\/21 16:45:27 Greeting: Hello OzonTech<\/p>\n<p>2023\/10\/21 16:45:29 Greeting: Hello OzonTech<\/p>\n<p>2023\/10\/21 16:45:31 Greeting: Hello OzonTech<\/p>\n<p>2023\/10\/21 16:45:32 resolver made request: [127.0.0.1:8080]<\/p>\n<p>2023\/10\/21 16:45:33 Greeting: Hello OzonTech<\/p>\n<p>2023\/10\/21 16:45:35 Greeting: Hello OzonTech<\/p>\n<p>2023\/10\/21 16:45:37 resolver made request: [127.0.0.1:8080]<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>\u041b\u043e\u0433\u0438 \u0431\u044d\u043a\u0435\u043d\u0434\u0430: <\/summary>\n<div class=\"spoiler__content\">\n<p>2023\/10\/21 16:45:17 Received: OzonTech<\/p>\n<p>2023\/10\/21 16:45:19 Received: OzonTech<\/p>\n<p>2023\/10\/21 16:45:21 Received: OzonTech<\/p>\n<p>2023\/10\/21 16:45:23 Received: OzonTech<\/p>\n<p>2023\/10\/21 16:45:25 Received: OzonTech<\/p>\n<p>2023\/10\/21 16:45:27 Received: OzonTech<\/p>\n<p>2023\/10\/21 16:45:29 Received: OzonTech<\/p>\n<p>2023\/10\/21 16:45:31 Received: OzonTech<\/p>\n<p>2023\/10\/21 16:45:33 Received: OzonTech<\/p>\n<p>2023\/10\/21 16:45:35 Received: OzonTech<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>\u041b\u043e\u0433\u0438 \u043c\u043e\u043a\u0430 DNS-\u0441\u0435\u0440\u0432\u0435\u0440\u0430:\u00a0<\/summary>\n<div class=\"spoiler__content\">\n<p>2023\/10\/21 16:45:17 new request with query: target=helloworld_server<\/p>\n<p>2023\/10\/21 16:45:22 new request with query: target=helloworld_server<\/p>\n<p>2023\/10\/21 16:45:27 new request with query: target=helloworld_server<\/p>\n<p>2023\/10\/21 16:45:32 new request with query: target=helloworld_server<\/p>\n<p>2023\/10\/21 16:45:37 new request with query: target=helloworld_server<\/p>\n<\/div>\n<\/details>\n<p>\u0412 \u043b\u043e\u0433\u0430\u0445 \u043c\u044b \u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u043a\u043b\u0438\u0435\u043d\u0442 \u0434\u0435\u043b\u0430\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u043a \u043d\u0430\u0448\u0435\u043c\u0443 \u043c\u043e\u043a\u0443 DNS-\u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0434\u043e \u0431\u044d\u043a\u0435\u043d\u0434\u0430. \u0418 \u0434\u0430\u043b\u044c\u0448\u0435 \u0440\u0430\u0437 \u0432 5 \u0441\u0435\u043a\u0443\u043d\u0434 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0442 DNS-\u0441\u0435\u0440\u0432\u0435\u0440\u0430. <\/p>\n<h3>\u041f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0435 \u0432\u044b\u0432\u043e\u0434\u044b<\/h3>\n<p>\u041c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b\u0438 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043f\u043e\u0438\u0441\u043a\u0430 \u0430\u0434\u0440\u0435\u0441\u043e\u0432. \u041c\u044b \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u043c lookup \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0430\u0434\u0440\u0435\u0441\u0430 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u044e\u0449\u0438\u0445 \u043d\u0430\u0441 \u0431\u044d\u043a\u0435\u043d\u0434\u043e\u0432. \u0418\u0437 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u043e\u0432 \u0442\u0430\u043a\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0443 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0430\u0434\u0440\u0435\u0441\u043e\u0432. \u041d\u043e \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u043d\u0430\u0441 \u044d\u0442\u043e \u0443\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442.<\/p>\n<p>\u041f\u043e\u043a\u0430 \u0447\u0442\u043e \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043f\u0438\u0441\u043e\u043a \u2014 \u0438 \u0447\u0442\u043e-\u0442\u043e \u0434\u0430\u043b\u044c\u0448\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e \u0435\u0433\u043e, \u043d\u0430\u0447\u0430\u0432 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a \u0431\u044d\u043a\u0435\u043d\u0434\u0443. \u041b\u043e\u0433\u0438\u0447\u043d\u043e, \u0447\u0442\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043d\u0430\u043c \u043d\u0430\u0434\u043e \u0431\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a \u044d\u0442\u0438\u043c \u0430\u0434\u0440\u0435\u0441\u0430\u043c \u0438 \u043d\u0430\u0447\u0430\u0442\u044c \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0442\u044c \u0438\u0445 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442 Balancer, \u0437\u0430\u0434\u0430\u0447\u0435\u0439 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f, \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0438\u0445 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438 \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435 \u043a\u0430\u043a\u0443\u044e-\u0442\u043e \u043b\u043e\u0433\u0438\u043a\u0443 \u043f\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0443 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u0438 \u0442.\u0434. \u041d\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043d\u044f\u0442\u044c, \u0433\u0434\u0435 \u043e\u043d \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u0438 \u043a\u0430\u043a \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u043d\u0443\u0436\u043d\u044b\u0439 \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043a\u0430\u043a \u0432 \u043d\u0435\u0433\u043e \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e\u0431 \u0430\u0434\u0440\u0435\u0441\u0430\u0445.\u00a0<\/p>\n<h2>Balancer<\/h2>\n<p>\u0412 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 UpdateState \u0443 ClientConn, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u043b\u0438 \u0440\u0430\u043d\u0435\u0435, \u043f\u043e\u043c\u0438\u043c\u043e \u043f\u043e\u043b\u044f \u0441 \u0430\u0434\u0440\u0435\u0441\u0430\u043c\u0438, \u0431\u044b\u043b\u043e \u043f\u043e\u043b\u0435 ServiceConfig. \u0412 \u043d\u0451\u043c \u043a\u0430\u043a \u0440\u0430\u0437 \u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442\u0441\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0442\u043e\u043c, \u043a\u0430\u043a\u043e\u0439 Balancer \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0438 \u0434\u043b\u044f \u043d\u0435\u0433\u043e, \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u0438\u043c\u0435\u044e\u0442\u0441\u044f. \u0412 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0432\u044b\u0448\u0435 \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u043b\u0438 ClientConn \u0432 \u043f\u043e\u043b\u0435 ServiceConfig \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0443, \u043d\u043e \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u044b \u043e\u0442 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0449\u0435\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u043b \u043d\u0430\u043c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u0431 \u0430\u0434\u0440\u0435\u0441\u0430\u0445.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b7c\/7ac\/05c\/b7c7ac05ceb625617ce4ae677c414f24.png\" width=\"17156\" height=\"8274\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/b7c\/7ac\/05c\/b7c7ac05ceb625617ce4ae677c414f24.png\"\/><\/figure>\n<p>\u0412 \u043a\u043e\u043d\u0446\u0435 \u0441\u0432\u043e\u0435\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u044f UpdateState \u0441\u0442\u0430\u0432\u0438\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u043d\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f Balancer. \u041e\u0434\u043d\u043e\u0439 \u0438\u0437 \u0444\u0438\u0447 ClientConn \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 Balancer \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u043e, \u0447\u0442\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043e\u0434\u043d\u043e\u0439 \u0433\u043e\u0440\u0443\u0442\u0438\u043d\u043e\u0439, \u0432 \u0441\u0432\u044f\u0437\u0438 \u0441 \u0447\u0435\u043c \u043c\u0435\u0436\u0434\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438 Balancer \u043d\u0435 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 race condition \u0438 \u043d\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0442\u044c \u0437\u0430\u0449\u0438\u0442\u0443 \u043e\u0442 \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u043d\u043e\u0433\u043e \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043a \u043e\u0431\u0449\u0438\u043c \u0434\u0430\u043d\u043d\u044b\u043c \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u0445: <code>UpdateClientConnState<\/code>, <code>ResolverError<\/code>, <code>UpdateSubConnState<\/code> \u0438 <code>Close<\/code>.<\/p>\n<p>\u0421\u0430\u043c Balancer <a href=\"https:\/\/github.com\/grpc\/grpc-go\/blob\/c2398ced0efdd5151b4322922b20459b3d37a0d4\/balancer\/balancer.go#L56\"><u>\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f<\/u><\/a> \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e Resolver.\u00a0<\/p>\n<pre><code class=\"go\">bb := &amp;BalancerBuilder{} balancer.Register(bb)<\/code><\/pre>\n<p>\u0410 \u0432\u043e\u0442 \u0435\u0433\u043e <a href=\"https:\/\/github.com\/grpc\/grpc-go\/blob\/c2398ced0efdd5151b4322922b20459b3d37a0d4\/balancer\/balancer.go#L248\"><u>\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441<\/u><\/a> \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f. \u0412 Balancer \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e Build \u043d\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e \u0442\u0430\u0440\u0433\u0435\u0442\u0435 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u2014 \u043e\u043d\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0432 \u043e\u043f\u0446\u0438\u044f\u0445. \u041d\u0443 \u0438 \u0432\u043c\u0435\u0441\u0442\u043e \u043c\u0435\u0442\u043e\u0434\u0430 Scheme \u0432 \u043d\u0451\u043c \u043c\u0435\u0442\u043e\u0434 Name. \u041d\u043e \u0437\u0430\u0434\u0430\u0447\u0430 \u0432 \u0446\u0435\u043b\u043e\u043c \u0443 \u043d\u0435\u0433\u043e \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u0430\u044f.<\/p>\n<pre><code class=\"go\">type Builder interface { Build(cc ClientConn, opts BuildOptions) Balancer Name() string } <\/code><\/pre>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0436\u0435 Balancer. \u0415\u0433\u043e <a href=\"https:\/\/github.com\/grpc\/grpc-go\/blob\/c2398ced0efdd5151b4322922b20459b3d37a0d4\/balancer\/balancer.go#L370\"><u>\u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441<\/u><\/a> \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"go\">type Balancer interface { UpdateClientConnState(ClientConnState) error ResolverError(error) UpdateSubConnState(SubConn, SubConnState) Close() } <\/code><\/pre>\n<h3>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f<\/h3>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f UpdateClientConnState \u2014 \u043a\u0430\u043a \u0440\u0430\u0437 \u0442\u0430 \u0441\u0430\u043c\u0430\u044f, \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 ClientConn \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 Balancer.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/205\/3bc\/3e4\/2053bc3e40f1f3f2e3d11c7bbce24774.png\" width=\"17156\" height=\"8274\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/205\/3bc\/3e4\/2053bc3e40f1f3f2e3d11c7bbce24774.png\"\/><\/figure>\n<p>\u041e\u043d\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442 Balancer \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e\u0442 Resolver. \u0412 \u044d\u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432 Balancer \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u0430\u0434\u0440\u0435\u0441\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0440\u044f\u0434 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0441\u043e\u043e\u0431\u0449\u0438\u0442\u044c \u0435\u043c\u0443 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438. \u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u044d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0435\u043a\u043e\u0439 \u0442\u043e\u0447\u043a\u043e\u0439 \u0432\u0445\u043e\u0434\u0430 (\u043f\u043e\u0441\u043b\u0435 Build, \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435), \u043d\u0430\u0447\u043d\u0451\u043c \u0441 \u043d\u0435\u0451. <\/p>\n<pre><code class=\"go\">func (b *Balancer) UpdateClientConnState(s balancer.ClientConnState) error {    \/\/ \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043e\u0447\u0438\u0449\u0430\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443 Resolver (\u0432 \u043a\u043e\u043d\u0446\u0435 \u0431\u0443\u0434\u0435\u0442 \u043d\u043e\u0432\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u043d\u0435\u0451)    b.resolverErr = nil      addrsSet := b.createNewSubConns(s)      b.clearDeletedSubConns(addrsSet)      \/\/ \u0415\u0441\u043b\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 Resolver \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0430\u0434\u0440\u0435\u0441\u043e\u0432, \u0442\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443, \u0447\u0442\u043e\u0431\u044b ClientConn \u043f\u043e\u043f\u044b\u0442\u0430\u043b\u0441\u044f \u0432\u044b\u0437\u0432\u0430\u0442\u044c ResolveNow    \/\/ \u0422\u0430\u043a\u0436\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443 \u043e\u0431 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0438 \u0430\u0434\u0440\u0435\u0441\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0430\u0434\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f Balancer \u0440\u0435\u043f\u043e\u0440\u0442\u0438\u0442\u044c \u0435\u0451 \u043d\u0430\u0432\u0435\u0440\u0445      if len(s.ResolverState.Addresses) == 0 {       b.ResolverError(errors.New(\"produced zero addresses\"))       return balancer.ErrBadResolverState    }    \/\/ \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0435\u0441\u043b\u0438 \u0432\u0441\u0451 \u043e\u043a\u0435\u0439, \u043f\u0435\u0440\u0435\u0441\u043e\u0437\u0434\u0430\u0451\u043c Picker \u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 Balancer, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c ClientConn \u043d\u043e\u0432\u044b\u0439 Picker    b.regeneratePicker()    b.cc.UpdateState(balancer.State{ConnectivityState: b.state, Picker: b.picker})    return nil } <\/code><\/pre>\n<p>\u0413\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e \u0443 UpdateClientConnState \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u2014 \u043f\u0440\u043e\u0439\u0442\u0438\u0441\u044c \u043f\u043e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u043c\u0443 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044e \u0438 \u043f\u0440\u0438\u043d\u044f\u0442\u044c \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a\u0438\u0435 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u044e\u0449\u0438\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c, \u0438, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0437\u0430\u043a\u0440\u044b\u0442\u044c \u0442\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u044b\u043b\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u044b, \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u0438\u0441\u0447\u0435\u0437\u043b\u0438 \u0438\u0437 \u043d\u043e\u0432\u043e\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f. \u0412 \u043d\u0430\u0448\u0435\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0441 \u0442\u0435\u043c, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043e\u0442 Resolver. <\/p>\n<h2>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0438 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u0435 Subconnects<\/h2>\n<p>\u0421\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a \u0441\u0435\u0440\u0432\u0438\u0441\u0443 \u0432 gRPC \u043d\u0430\u0437\u044b\u0432\u0430\u044e\u0442 SubConn (\u0438\u043b\u0438 \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u044b). \u0421\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f \u043e\u043d\u0438 \u0442\u0430\u043a\u0436\u0435 \u0447\u0435\u0440\u0435\u0437 ClientConn.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/6f1\/85e\/c98\/6f185ec98c397f710d28faa4c11ff01d.png\" width=\"17156\" height=\"8274\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/6f1\/85e\/c98\/6f185ec98c397f710d28faa4c11ff01d.png\"\/><\/figure>\n<p>ClientConn \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u043d\u043e\u0432\u044b\u0439 SubConn \u2014 \u0438 \u043f\u043e\u0441\u043b\u0435 \u0432\u044b\u0437\u043e\u0432\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 Connect \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0433\u043e\u0440\u0443\u0442\u0438\u043d\u0435 SubConn \u0441\u043e\u0437\u0434\u0430\u0451\u0442 HTTP\/2-\u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442 \u0438 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435. \u0414\u0430\u043d\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0447\u0435\u0440\u0435\u0437 ClientConn \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f \u0443\u0436\u0435 Balancer \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 UpdateSubConnState.\u00a0<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ea8\/942\/462\/ea8942462d86e0778a6a77114eb2be79.png\" width=\"17156\" height=\"8274\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ea8\/942\/462\/ea8942462d86e0778a6a77114eb2be79.png\"\/><\/figure>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u0438 <code>createNewSubConns<\/code> \u0438 <code>clearDeletedSubConns<\/code>:<\/p>\n<pre><code class=\"go\">func (b *Balancer) createNewSubConns(s balancer.ClientConnState) *resolver.AddressMap {    \/\/ addrsSet \u2014 \u044d\u0442\u043e \u043c\u0430\u043f\u043a\u0430, \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0449\u0435 \u0443\u0434\u0430\u043b\u044f\u0442\u044c \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 Resolver \u0432 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 \u043d\u0435 \u0432\u0435\u0440\u043d\u0443\u043b    addrsSet := resolver.NewAddressMap()    for _, a := range s.ResolverState.Addresses {       addrsSet.Set(a, nil)       if _, ok := b.subConns.Get(a); !ok {          \/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442, \u0442\u0430\u043a \u043a\u0430\u043a \u0435\u0433\u043e \u043d\u0435\u0442 \u0432 \u0441\u0442\u0435\u0439\u0442\u0435 Balancer          sc, err := b.cc.NewSubConn([]resolver.Address{a}, balancer.NewSubConnOptions{})          if err != nil {             \/\/ \u0415\u0441\u043b\u0438 \u0447\u0442\u043e-\u0442\u043e \u043f\u043e\u0448\u043b\u043e \u043d\u0435 \u0442\u0430\u043a, \u0441\u043a\u0438\u043f\u0430\u0435\u043c \u0430\u0434\u0440\u0435\u0441 \u0438 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u043c             \/\/ \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438:             \/\/ -- len(addrs) &lt;= 0             \/\/ -- ErrClientConnClosing             \/\/ -- channelz.RegisterSubChannel error (errors.New(\"a SubChannel's parent id cannot be nil\"))             continue          }          \/\/ \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442          b.subConns.Set(a, sc)            b.scStates[sc] = connectivity.Idle          \/\/ \u0422\u0430\u043a \u043a\u0430\u043a \u044d\u0442\u043e \u043d\u043e\u0432\u044b\u0439 \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442, \u0441\u0447\u0438\u0442\u0430\u0435\u043c, \u0447\u0442\u043e \u0440\u0430\u043d\u0435\u0435 \u043e\u043d \u0431\u044b\u043b \u0432 \u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438          b.csEvltr.RecordTransition(connectivity.Shutdown, connectivity.Idle)          \/\/ \u0412\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u0430 (\u043f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0433\u043e\u0440\u0443\u0442\u0438\u043d\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e)          sc.Connect()       }    }    return addrsSet }   func (b *Balancer) clearDeletedSubConns(addrsSet *resolver.AddressMap) {    \/\/ \u041f\u0440\u043e\u0439\u0434\u0451\u043c\u0441\u044f \u043f\u043e \u0432\u0441\u0435\u043c \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u0430\u043c \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c, \u043d\u0435 \u0431\u044b\u043b\u0438 \u043b\u0438 \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u044b \u0443\u0434\u0430\u043b\u0435\u043d\u044b \u0432 \u043d\u043e\u0432\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 Resolver    for _, a := range b.subConns.Keys() {       sci, _ := b.subConns.Get(a)       sc := sci.(balancer.SubConn)       \/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0430\u0434\u0440\u0435\u0441\u0430 \u0432 \u043c\u0430\u043f\u043a\u0435 \u043d\u043e\u0432\u044b\u0445 \u0430\u0434\u0440\u0435\u0441\u043e\u0432       if _, ok := addrsSet.Get(a); !ok {          \/\/ \u0415\u0441\u043b\u0438 \u0432 \u043d\u043e\u0432\u043e\u043c \u0441\u0442\u0435\u0439\u0442\u0435 \u043d\u0435\u0442 \u044d\u0442\u043e\u0433\u043e \u0430\u0434\u0440\u0435\u0441\u0430, \u0434\u0435\u043b\u0430\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u043a \u0421lientConn \u043d\u0430 \u0435\u0433\u043e \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435          b.cc.RemoveSubConn(sc)          b.subConns.Delete(a)          \/\/ \u041d\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0437\u043e\u0439\u0434\u0451\u0442, \u043a\u043e\u0433\u0434\u0430 ClientConn \u0432\u0435\u0440\u043d\u0451\u0442 \u043a\u043e\u043b\u0431\u044d\u043a \u043e\u0431 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f          \/\/ \u044d\u0442\u043e\u0433\u043e \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u0430 \u0447\u0435\u0440\u0435\u0437 \u0444\u0443\u043d\u043a\u0446\u0438\u044e UpdateSubConnState       }    } } <\/code><\/pre>\n<p>\u0418\u0442\u0430\u043a, \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>UpdateSubConnState<\/code> \u043f\u0440\u0438\u0445\u043e\u0434\u044f\u0442 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0432. \u0412 \u043d\u0435\u0439 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u0430, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0437\u0430\u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0430\u0433\u0440\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0432\u0441\u0435\u0445 \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 Balancer.<\/p>\n<pre><code class=\"go\">func (b *Balancer) UpdateSubConnState(sc balancer.SubConn, state balancer.SubConnState) {    \/\/ \u0415\u0441\u043b\u0438 \u043a \u043d\u0430\u043c \u043f\u0440\u0438\u0448\u043b\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043d\u0435\u0442 \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u0442\u0435\u0439\u0442\u0435, \u0441\u043a\u0438\u043f\u0430\u0435\u043c \u0435\u0433\u043e    oldS, ok := b.scStates[sc]    if !ok {       return    }      s := state.ConnectivityState      if oldS == connectivity.TransientFailure &amp;&amp;       (s == connectivity.Connecting || s == connectivity.Idle) {       \/\/ \u0415\u0441\u043b\u0438 SubConn \u043f\u043e\u043f\u0430\u043b \u0432 TRANSIENT_FAILURE, \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 IDLE \u0438\u043b\u0438       \/\/ CONNECTING \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u044b, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0442\u0438\u0442\u044c \u0430\u0433\u0440\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043e\u0442       \/\/ \u043d\u0430\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0432 \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e\u043c CONNECTING \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438, \u043a\u043e\u0433\u0434\u0430 \u0435\u0441\u0442\u044c \u043c\u043d\u043e\u0433\u043e \u0431\u044d\u043a\u0435\u043d\u0434\u043e\u0432,       \/\/ \u043d\u043e \u0432\u0441\u0435 \u043e\u043d\u0438 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u043d\u0435\u0440\u0430\u0431\u043e\u0447\u0435\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438       if s == connectivity.Idle {          sc.Connect()       }       return    }    b.scStates[sc] = s    switch s {    case connectivity.Idle:       sc.Connect()    case connectivity.Shutdown:       \/\/ \u0412 \u044d\u0442\u043e\u043c \u043c\u0435\u0441\u0442\u0435 \u0443\u0434\u0430\u043b\u044f\u0435\u043c \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0430\u043d\u0435\u0435 \u043c\u044b \u043f\u043e\u043f\u0440\u043e\u0441\u0438\u043b\u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u044c \u0443 ClientConn \u0447\u0435\u0440\u0435\u0437 RemoveSubConn       delete(b.scStates, sc)    case connectivity.TransientFailure:       \/\/ \u0415\u0441\u043b\u0438 \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442 \u043f\u043e\u043f\u0430\u043b \u0432 TransientFailure => \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043e\u043d \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u044d\u0442\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438       b.connErr = state.ConnectionError    }      \/\/ \u0417\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u043d\u043e\u0432\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0432 \u0430\u0433\u0440\u0435\u0433\u0430\u0442\u043e\u0440 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 \u2014 \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043d\u043e\u0432\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 Balancer    b.state = b.csEvltr.RecordTransition(oldS, s)      \/\/ \u041f\u0435\u0440\u0435\u0441\u043e\u0437\u0434\u0430\u0451\u043c Picker \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445:    \/\/  - \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442 \u0441\u0442\u0430\u043b Ready \u0438\u043b\u0438 \u043d\u0430\u043e\u0431\u043e\u0440\u043e\u0442    \/\/  - \u0441\u0443\u043c\u043c\u0430\u0440\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 Balancer \u0441\u0442\u0430\u043b\u043e TransientFailure (\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0443 Balancer)    if (s == connectivity.Ready) != (oldS == connectivity.Ready) ||       b.state == connectivity.TransientFailure {       b.regeneratePicker()    }    \/\/ \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0441\u0442\u0435\u0439\u0442    b.cc.UpdateState(balancer.State{ConnectivityState: b.state, Picker: b.picker}) } <\/code><\/pre>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 Balancer \u2014 <code>ResolverError<\/code>, \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u044b \u0443\u0436\u0435 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438\u0441\u044c \u0432 UpdateClientConnState. \u042d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0430 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043e\u0448\u0438\u0431\u043e\u043a Resolver. \u041f\u043e\u043c\u0438\u043c\u043e \u0442\u043e\u0433\u043e \u0447\u0442\u043e \u043e\u043d\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 UpdateClientConnState, \u043e\u043d\u0430 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432\u044b\u0437\u0432\u0430\u043d\u0430 \u0432\u044b\u0448\u0435\u0441\u0442\u043e\u044f\u0449\u0438\u043c\u0438 \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u0430\u043c\u0438 (\u0434\u0430, \u0438\u0445 \u0438\u043d\u043e\u0433\u0434\u0430 \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u044e\u0442 \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0442 \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443, \u0435\u0441\u043b\u0438 \u044d\u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e).<\/p>\n<pre><code class=\"go\">func (b *Balancer) ResolverError(err error) {    \/\/ \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443 \u0432 \u0441\u0442\u0435\u0439\u0442    b.resolverErr = err      \/\/ \u0415\u0441\u043b\u0438 \u0443 Balancer \u043d\u0435\u0442 \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0432, \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u043c \u0435\u0433\u043e \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 TransientFailure    if b.subConns.Len() == 0 {       b.state = connectivity.TransientFailure    }      \/\/ \u0415\u0441\u043b\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043d\u0435 TransientFailure, Picker \u0434\u043e\u043b\u0436\u0435\u043d \u0434\u0430\u043b\u044c\u0448\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c, \u043f\u043e\u043a\u0430 Balancer \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0434\u0430\u0432\u0430\u0442\u044c \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u0443\u044e \u043e\u0448\u0438\u0431\u043a\u0443    if b.state != connectivity.TransientFailure {       return    }      \/\/ \u041f\u0435\u0440\u0435\u0441\u043e\u0437\u0434\u0430\u0451\u043c Picker \u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 ClientConn    b.regeneratePicker()    b.cc.UpdateState(balancer.State{       ConnectivityState: b.state,       Picker:            b.picker,    }) } <\/code><\/pre>\n<h2>\u0412\u044b\u0434\u0435\u043b\u044f\u0435\u043c \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u043a \u0440\u0430\u0431\u043e\u0442\u0435 Subconnects<\/h2>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f regeneratePicker \u0441\u043e\u0437\u0434\u0430\u0451\u0442 Picker, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u0436\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u043c \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c \u0432\u043e \u0432\u0441\u0435\u0439 \u0446\u0435\u043f\u043e\u0447\u043a\u0435, \u0442\u0430\u043a \u043a\u0430\u043a \u0438\u043c\u0435\u043d\u043d\u043e \u043e\u043d \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u043a\u0438.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/053\/2db\/6fe\/0532db6fe23e7537236ed015f58017ba.png\" width=\"17156\" height=\"8274\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/053\/2db\/6fe\/0532db6fe23e7537236ed015f58017ba.png\"\/><\/figure>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0441\u0451 \u0445\u043e\u0440\u043e\u0448\u043e (Balancer \u043d\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 <em>TransientFailure<\/em>), \u0442\u043e \u0441\u043e\u0431\u0435\u0440\u0451\u043c \u0441\u043b\u0430\u0439\u0441 \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0432, \u043d\u0430\u0445\u043e\u0434\u044f\u0449\u0438\u0445\u0441\u044f \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 Ready, \u0438 \u0432\u044b\u0437\u043e\u0432\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f Picker, \u043f\u0435\u0440\u0435\u0434\u0430\u0432 \u0442\u0443\u0434\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u0441\u043b\u0430\u0439\u0441. \u0415\u0441\u043b\u0438 \u0436\u0435 \u043d\u0430\u0448 Balancer \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 <em>TransientFailure, <\/em>\u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c no operate (noop) Picker, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430 \u0432\u0441\u0435 \u0432\u044b\u0437\u043e\u0432\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0438 Pick \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0443. \u0414\u0430\u043d\u043d\u0443\u044e \u043e\u0448\u0438\u0431\u043a\u0443 \u0431\u0443\u0434\u0435\u0442 \u0432\u0438\u0434\u0435\u0442\u044c \u043d\u0430\u0448 \u043a\u043b\u0438\u0435\u043d\u0442 \u043f\u0440\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u0432\u044b\u0437\u043e\u0432\u0430 RPC.<\/p>\n<pre><code class=\"go\">func (b *Balancer) regeneratePicker() { \/\/ \u0415\u0441\u043b\u0438 Balancer \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 TransientFailure, Picker\u2019\u0443 \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u043f\u0438\u043a \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043e\u0442\u0434\u0430\u0432\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0443 (\u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0434\u0432\u0443\u0445 \u043e\u0448\u0438\u0431\u043e\u043a: Resolver\u2019\u0430 \u0438 \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0432) if b.state == connectivity.TransientFailure { b.picker = NewErrPicker(b.mergeErrors()) return } \/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043c\u0430\u043f\u0443 \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0432 \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 Ready readySCs := make(map[balancer.SubConn]base.SubConnInfo) \/\/ \u0424\u0438\u043b\u044c\u0442\u0440\u0443\u0435\u043c \u0432\u0441\u0435 \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u044b \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 Ready \u0438\u0437 \u043c\u0430\u043f\u044b \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0432 for _, addr := range b.subConns.Keys() { sci, _ := b.subConns.Get(addr) sc := sci.(balancer.SubConn) if st, ok := b.scStates[sc]; ok &amp;&amp; st == connectivity.Ready { readySCs[sc] = base.SubConnInfo{Address: addr} } } \/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0439 RoundRobin Picker, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u0445 \u0432\u044b\u0448\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 ClientConn\u2019\u0430 b.picker = BuildRRPicker(base.PickerBuildInfo{ReadySCs: readySCs}) }  \u0412\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f mergeErrors \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0443 \u0438\u0437 \u0434\u0432\u0443\u0445 \u0440\u0430\u043d\u0435\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u0445: resolverErr \u0438 connErr. \u041e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u043d\u0430\u044f \u043e\u0448\u0438\u0431\u043a\u0430 \u0434\u0430\u043b\u0435\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f \u0432 ErrPicker \u0438 \u043f\u0440\u043e\u043a\u0438\u0434\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0434\u043e \u0441\u0430\u043c\u043e\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 RPC.  func (b *Balancer) mergeErrors() error { \/\/ \u041b\u0438\u0431\u043e \u0443 \u043d\u0430\u0441 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0441 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f\u043c\u0438, \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u044b, \/\/ \u043b\u0438\u0431\u043e \u0443 \u043d\u0430\u0441 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0441 Resolver, \u0435\u0441\u043b\u0438 \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0432 \u043d\u0435\u0442 if b.connErr == nil { return fmt.Errorf(\"last resolver error: %v\", b.resolverErr) } if b.resolverErr == nil { return fmt.Errorf(\"last connection error: %v\", b.connErr) } \/\/ \u041f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043e\u0431\u0435 \u043e\u0448\u0438\u0431\u043a\u0438, \u0435\u0441\u043b\u0438 \u0432 \u043b\u043e\u0433\u0438\u043a\u0435 Resolver \u0435\u0441\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u0430\u044f \u043b\u043e\u0433\u0438\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0443\u043f\u0430\u043b\u0430, \u043f\u043e\u043c\u0438\u043c\u043e \/\/ \u0442\u043e\u0433\u043e \u0447\u0442\u043e \u043e\u043d \u043d\u0435 \u0441\u043c\u043e\u0433 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u044b (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0431\u044b\u043b \u0441\u043e\u0432\u0435\u0440\u0448\u0451\u043d \u0444\u043e\u043b\u0431\u044d\u043a \u043d\u0430 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0440\u0435\u0437\u043e\u043b\u0432\u0438\u043d\u0433\u0430) return fmt.Errorf(\"last connection error: %v; last resolver error: %v\", b.connErr, b.resolverErr) } <\/code><\/pre>\n<h3>\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438<\/h3>\n<p>\u041f\u043e\u043c\u0438\u043c\u043e \u044d\u0442\u043e\u0433\u043e, \u0432 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u043b\u0436\u0435\u043d \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c Balancer, \u0435\u0441\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044f ExitIdle, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 ClientConn \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0444\u043e\u0440\u0441\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u0445\u043e\u0434 \u0432\u0441\u0435\u0445 \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0432 \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f. \u0412 \u043d\u0430\u0448\u0435\u043c Balancer \u043c\u044b \u043d\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043b\u043e\u0433\u0438\u043a\u0443 \u0441 \u043a\u0430\u043a\u0438\u043c-\u043b\u0438\u0431\u043e \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u0435\u043c \u043f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c, \u043a\u0430\u043a \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f \u043a \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u0430\u043c \u0438\u0437 \u0441\u043f\u0438\u0441\u043a\u0430 \u0430\u0434\u0440\u0435\u0441\u043e\u0432, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0433\u043e \u043e\u0442 Resolver:<\/p>\n<pre><code class=\"go\">func (b *Balancer) ExitIdle() {}<\/code><\/pre>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f Close \u043d\u0443\u0436\u043d\u0430 \u0434\u043b\u044f \u043e\u0447\u0438\u0441\u0442\u043a\u0438 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f Balancer, \u0435\u0441\u043b\u0438 \u043e\u043d\u043e \u0438\u043c\u0435\u0435\u0442\u0441\u044f. \u0421\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u044b \u0432 Close \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u043d\u0435 \u043d\u0443\u0436\u043d\u043e.<\/p>\n<pre><code class=\"go\">func (b *Balancer) Close() {}<\/code><\/pre>\n<p>\u041c\u044b \u043f\u0440\u043e\u0434\u0435\u043b\u0430\u043b\u0438 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043f\u0443\u0442\u044c. \u0423 \u043d\u0430\u0441 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c Resolver, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u0430\u0434\u0440\u0435\u0441\u043e\u0432 \u043f\u043e \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044e \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442 \u0438\u0445 \u0432 \u0444\u043e\u043d\u0435. Balancer, \u043f\u043e\u043b\u0443\u0447\u0430\u044f \u044d\u0442\u0438 \u0430\u0434\u0440\u0435\u0441\u0430, \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 \u043a \u043d\u0438\u043c, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u044d\u0442\u0438\u0445 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439. \u041c\u044b \u0443\u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u0432 \u0431\u044d\u043a\u0435\u043d\u0434, \u043d\u043e\u2026<\/p>\n<h2>Picker<\/h2>\n<h3>Round-robin Picker<\/h3>\n<p>\u041e\u0441\u0442\u0430\u043b\u0441\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u2014 <a href=\"https:\/\/github.com\/grpc\/grpc-go\/blob\/c2398ced0efdd5151b4322922b20459b3d37a0d4\/balancer\/balancer.go#L339\"><u>Picker<\/u><\/a>. \u0418\u043c\u0435\u044f \u043c\u0430\u0441\u0441\u0438\u0432 \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u043a \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0432, \u043d\u0443\u0436\u043d\u043e \u0440\u0435\u0448\u0438\u0442\u044c, \u0432 \u043a\u0430\u043a\u043e\u0439 \u0436\u0435 \u0438\u0437 \u043d\u0438\u0445 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441. \u0418 \u043a\u0430\u043a \u0440\u0430\u0437 \u044d\u0442\u0443 \u0437\u0430\u0434\u0430\u0447\u0443 \u0440\u0435\u0448\u0430\u0435\u0442 Picker, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430 \u0432\u0445\u043e\u0434 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0432, \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u043a \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435 RPC, \u0438 \u043f\u043e \u043d\u0435\u043c\u0443 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u043a\u0438. \u0415\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044f Pick \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437. \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 RoundRobin Picker.\u00a0<\/p>\n<pre><code class=\"go\">func BuildRRPicker(info base.PickerBuildInfo) balancer.Picker { if len(info.ReadySCs) == 0 { return NewErrPicker(balancer.ErrNoSubConnAvailable) } scs := make([]balancer.SubConn, 0, len(info.ReadySCs)) \/\/ \u041f\u0440\u043e\u0445\u043e\u0434\u0438\u043c\u0441\u044f \u043f\u043e Ready subconnects  for sc := range info.ReadySCs { scs = append(scs, sc) } return &amp;rrPicker{ subConns: scs, \/\/ \u041f\u0435\u0440\u0432\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u043c \u043d\u0430 \u0440\u0430\u043d\u0434\u043e\u043c\u043d\u044b\u0439 \u0438\u043d\u0434\u0435\u043a\u0441, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \/\/ \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u043d \u0442\u0430\u043a\u043e\u0439 \u0436\u0435 RR Picker \u0432 \u0434\u0440\u0443\u0433\u043e\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u0435 \/\/ \u0438 \u043d\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0441\u043e \u0432\u0441\u0435\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u043d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \/\/ SubConn next: uint32(rand.Intn(len(scs))), } }  <\/code><\/pre>\n<p>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0443 RR Picker \u043a\u0440\u0430\u0439\u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u0430\u044f: \u043c\u0430\u0441\u0441\u0438\u0432 \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0432 \u0438 \u0438\u043d\u0434\u0435\u043a\u0441 \u044d\u0442\u043e\u0433\u043e \u043c\u0430\u0441\u0441\u0438\u0432\u0430, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0437\u0430\u043f\u0440\u043e\u0441.\u00a0<\/p>\n<pre><code class=\"go\">type rrPicker struct { subConns []balancer.SubConn next     uint32 } <\/code><\/pre>\n<p>\u0410\u0442\u043e\u043c\u0430\u0440\u043d\u043e \u0438\u043d\u043a\u0440\u0435\u043c\u0435\u043d\u0442\u0438\u043c \u0441\u0447\u0451\u0442\u0447\u0438\u043a \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0438 \u0431\u0435\u0440\u0451\u043c \u043e\u0441\u0442\u0430\u0442\u043e\u043a \u043e\u0442 \u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0435\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043d\u0430 \u0434\u043b\u0438\u043d\u0443 \u043c\u0430\u0441\u0441\u0438\u0432\u0430, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0432\u044b\u0432\u0430\u043b\u0438\u0442\u044c\u0441\u044f \u0437\u0430  \u0433\u0440\u0430\u043d\u0438\u0446\u044b. \u041d\u0443 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043d\u0430\u0448\u0435\u0433\u043e \u0432\u044b\u0431\u043e\u0440\u0430 \ud83d\ude42<\/p>\n<pre><code class=\"go\">func (p *rrPicker) Pick(balancer.PickInfo) (balancer.PickResult, error) { subConnsLen := uint32(len(p.subConns)) nextIndex := atomic.AddUint32(&amp;p.next, 1) sc := p.subConns[nextIndex%subConnsLen] return balancer.PickResult{SubConn: sc}, nil }<\/code><\/pre>\n<h2>Error Picker<\/h2>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0440\u0430\u043d\u0435\u0435 \u043c\u044b \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u043b\u0438 ErrorPicker. \u042d\u0442\u043e, \u043f\u043e \u0441\u0443\u0442\u0438, no operate Picker, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0435 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043d\u0430 \u0432\u0445\u043e\u0434 \u043e\u0448\u0438\u0431\u043a\u0443 \u0438 \u043d\u0430 \u0432\u0441\u0435 Pick \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0435\u0451. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u044d\u0442\u0430 \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u043e\u043a\u0438\u0434\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u043c\u0443 \u043a\u043b\u0438\u0435\u043d\u0442\u0443 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430.<\/p>\n<pre><code class=\"go\">func NewErrPicker(err error) balancer.Picker { return &amp;errPicker{err: err} } type errPicker struct { err error } func (p *errPicker) Pick(info balancer.PickInfo) (balancer.PickResult, error) { return balancer.PickResult{}, p.err } <\/code><\/pre>\n<p>\u041d\u043e \u043f\u043e\u043c\u0438\u043c\u043e \u0442\u043e\u0433\u043e \u0447\u0442\u043e Picker \u043c\u043e\u0436\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u043a\u0438 (\u043a\u0430\u043a \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 RR, \u0438\u043b\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 chash \u0438 WRR), \u0435\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u043a\u0438. \u0412 \u043e\u0442\u0432\u0435\u0442\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 Pick \u0432 <a href=\"https:\/\/github.com\/grpc\/grpc-go\/blob\/c2398ced0efdd5151b4322922b20459b3d37a0d4\/balancer\/balancer.go#L305\"><u>balancer.PickResult<\/u><\/a> \u0435\u0441\u0442\u044c \u0434\u0432\u0430 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0445 \u043f\u043e\u043b\u044f:<\/p>\n<pre><code class=\"go\">\/\/ PickResult contains information related to a connection chosen for an RPC. type PickResult struct {    \/\/ SubConn is the connection to use for this pick, if its state is Ready.    \/\/ If the state is not Ready, gRPC will block the RPC until a new Picker is    \/\/ provided by the balancer (using ClientConn.UpdateState).  The SubConn    \/\/ must be one returned by ClientConn.NewSubConn.    SubConn SubConn      \/\/ Done is called when the RPC is completed.  If the SubConn is not ready,    \/\/ this will be called with a nil parameter.  If the SubConn is not a valid    \/\/ type, Done may not be called.  May be nil if the balancer does not wish    \/\/ to be notified when the RPC completes.    Done func(DoneInfo)      \/\/ Metadata provides a way for LB policies to inject arbitrary per-call    \/\/ metadata. Any metadata returned here will be merged with existing    \/\/ metadata added by the client application.    \/\/    \/\/ LB policies with child policies are responsible for propagating metadata    \/\/ injected by their children to the ClientConn, as part of Pick().    Metadata metadata.MD } <\/code><\/pre>\n<p>\u041f\u043e\u043b\u0435 Done, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u0432\u0430\u043d\u043e \u043f\u043e \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0442\u044c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e in-flight \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0432 \u0438\u043b\u0438 \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u0441\u0440\u0435\u0434\u043d\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u043e\u0442\u0432\u0435\u0442\u0430 \u0438 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0442\u0440\u0430\u0444\u0438\u043a \u0441 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u043e\u043c \u043d\u0430 \u0441\u0430\u043c\u044b\u0439 \u0431\u044b\u0441\u0442\u0440\u044b\u0439 \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442.\u00a0<\/p>\n<p>\u041f\u043e\u043b\u0435 Metadata \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430\u043c \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u043a\u0438 \u043f\u043e\u043c\u0435\u0449\u0430\u0442\u044c \u0432 \u0437\u0430\u043f\u0440\u043e\u0441 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e, \u0435\u0441\u043b\u0438 \u044d\u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e.<\/p>\n<p>\u0418 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u0431\u0443\u0434\u0443\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u044b \u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u044b \u0432\u0441\u0435 \u0432\u044b\u0448\u0435\u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u043d\u0430\u0448 ClientConn \u0431\u0443\u0434\u0435\u0442 \u0433\u043e\u0442\u043e\u0432 \u043a \u0442\u043e\u043c\u0443, \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u0441\u0432\u043e\u0439 \u043f\u0435\u0440\u0432\u044b\u0439 RPC.<\/p>\n<h2>\u0421\u0430\u043c\u043e\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0435<\/h2>\n<p>\u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438\u0441\u044c \u0441 \u0442\u0435\u043c, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0432\u0441\u0435 \u0443\u043f\u043e\u043c\u044f\u043d\u0443\u0442\u044b\u0435 \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0445 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u043e\u0432, \u043e \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u044f \u043f\u0438\u0441\u0430\u043b \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u0441\u0442\u0430\u0442\u044c\u0438.<\/p>\n<p>\u041d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u0441\u0430\u043c\u044b\u043c\u0438 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u043c\u0438 \u0438 \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0438\u0440\u0443\u0435\u043c\u044b\u043c\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f Picker \u0438 Resolver. \u041c\u043e\u0436\u043d\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 <a href=\"https:\/\/github.com\/grpc\/grpc-go\/blob\/c2398ced0efdd5151b4322922b20459b3d37a0d4\/balancer\/base\/balancer.go#L61\"><u>base.Balancer<\/u><\/a> \u043e\u0442 gRPC, \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c <a href=\"https:\/\/github.com\/grpc\/grpc-go\/blob\/c2398ced0efdd5151b4322922b20459b3d37a0d4\/balancer\/base\/base.go#L39\"><u>PickerBuilder<\/u><\/a> \u0438 \u043d\u0430\u0437\u043d\u0430\u0447\u0438\u0442\u044c \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0435 \u0438\u043c\u044f.\u00a0<\/p>\n<pre><code class=\"go\">base.NewBalancerBuilder(\"habr\", pb, base.Config{})<\/code><\/pre>\n<p>PickerBuilder \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u0432\u0430\u043d \u0432 \u043c\u043e\u043c\u0435\u043d\u0442 regeneratePicker: <\/p>\n<pre><code class=\"go\">type PickerBuilder interface {    Build(info PickerBuildInfo) balancer.Picker } <\/code><\/pre>\n<h3>\u041a\u0430\u043d\u0430\u0440\u0435\u0435\u0447\u043d\u044b\u0435 \u0434\u0435\u043f\u043b\u043e\u0438<\/h3>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0436\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b, \u0443\u043f\u043e\u043c\u044f\u043d\u0443\u0442\u044b\u0435 \u0432 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0435 \u0441\u0442\u0430\u0442\u044c\u0438. \u041d\u0430\u0447\u043d\u0451\u043c \u0441 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u2014 \u0441 \u043a\u0430\u043d\u0430\u0440\u0435\u0435\u0447\u043d\u043e\u0433\u043e \u0434\u0435\u043f\u043b\u043e\u044f. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a \u0430\u0434\u0440\u0435\u0441\u0430\u043c \u0432 \u043e\u0442\u0432\u0435\u0442\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u043c\u043e\u043a\u0430 DNS-\u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e \u0432\u0435\u0440\u0441\u0438\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0432\u0435\u0441\u0430 \u044d\u0442\u0438\u0445 \u0432\u0435\u0440\u0441\u0438\u0439. \u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0443 \u043d\u0430\u0441 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043c\u043e\u043a DNS-\u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u0430 \u043d\u0435\u0447\u0442\u043e \u043f\u043e\u0445\u043e\u0436\u0435\u0435 \u043d\u0430 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0439 control plane \u0434\u043b\u044f Service Mesh.<\/p>\n<pre><code class=\"go\">type (    Response struct {       Endpoints      []Endpoint    `json:\"endpoints\"`       VersionWeights map[string]int `json:\"version_weights\"`       ServiceConfig  string         `json:\"service_config\"`    }    Endpoint struct {       Address string `json:\"address\"`       Version string `json:\"version\"`    } )   var HelloWorldServerResponse = Response{    Endpoints: []Endpoint{       {          Address: \"127.0.0.1:8080\",          Version: \"v1\",       },       {          Address: \"127.0.0.1:8090\",          Version: \"v2\",       },    },    VersionWeights: map[string]int{       \"v1\": 10,       \"v2\": 90,    },    ServiceConfig: \"{\\\"loadBalancingPolicy\\\": \\\"habr_balancer\\\"}\", }<\/code><\/pre>\n<p>\u041d\u0443 \u0438, \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435, \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0430\u0448 Resolver, \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u0441\u043c\u043e\u0433 \u043f\u0430\u0440\u0441\u0438\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u043e\u043b\u044f. \u041f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0431\u0443\u0434\u0435\u043c \u0447\u0435\u0440\u0435\u0437 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u043c\u0435\u044e\u0442\u0441\u044f \u0432 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u043e\u0442\u0432\u0435\u0442\u0430 Resolver, \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u043e\u0439 \u0432 ClientConn:<\/p>\n<pre><code class=\"go\">func (r *Resolver) lookup(target string) {    resp, err := http.Get(fmt.Sprintf(\"http:\/\/%s\/endpoints?target=%s\", lookupServerHostPort, target))    if err != nil {       log.Println(err)       return    }    data, err := io.ReadAll(resp.Body)    if err != nil {       log.Println(err)       return    }    var epsResp Response    err = json.Unmarshal(data, &amp;epsResp)    if err != nil {       return    }      log.Println(\"resolver made request:\", epsResp)    newAddrs := make([]resolver.Address, 0, len(epsResp.Endpoints))    for _, ep := range epsResp.Endpoints {       newAddrs = append(newAddrs, resolver.Address{          Addr:               ep.Address,          Attributes:         attributes.New(versionAttrKey, ep.Version),          BalancerAttributes: attributes.New(versionAttrKey, ep.Version),       })    }    err = r.cc.UpdateState(resolver.State{       Addresses:     newAddrs,       ServiceConfig: r.cc.ParseServiceConfig(epsResp.ServiceConfig),       Attributes:    attributes.New(weightsAttrsKey, epsResp.VersionWeights),    })    if err != nil {       return    } }   func (b *Balancer) regeneratePicker() {    \/\/ \u0415\u0441\u043b\u0438 \u043c\u044b \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 TransientFailure => \u043f\u0438\u043a\u0435\u0440\u0443 \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u043f\u0438\u043a \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043e\u0442\u0434\u0430\u0432\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0443 (\u043c\u0435\u0440\u0436 \u0434\u0432\u0443\u0445 \u043e\u0448\u0438\u0431\u043e\u043a - \u0440\u0435\u0437\u043e\u043b\u0432\u0435\u0440\u0430 \u0438 \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0432)    if b.state == connectivity.TransientFailure {       b.picker = NewErrPicker(b.mergeErrors())       return    }      \/\/ \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043c\u0430\u043f\u0443 \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0432 \u0432 Ready \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438    readySCs := make(map[balancer.SubConn]base.SubConnInfo)      \/\/ \u0424\u0438\u043b\u044c\u0442\u0440\u0443\u0435\u043c \u0432\u0441\u0435 Ready \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u044b \u0438\u0437 \u043c\u0430\u043f\u044b \u0432\u0441\u0435\u0445 \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0432    for _, addr := range b.subConns.Keys() {       sci, _ := b.subConns.Get(addr)       sc := sci.(balancer.SubConn)       if st, ok := b.scStates[sc]; ok &amp;&amp; st == connectivity.Ready {          readySCs[sc] = base.SubConnInfo{Address: addr}       }    }      \/\/ \u0415\u0441\u043b\u0438 \u0432 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430\u0445 \u0438\u043c\u0435\u044e\u0442\u0441\u044f \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e \u0432\u0435\u0441\u0430\u0445 \u043f\u043e \u0432\u0435\u0440\u0441\u0438\u044f\u043c - \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u0430\u043d\u0430\u0440\u0435\u0435\u0447\u043d\u044b\u0439 \u043f\u0438\u043a\u0435\u0440    if weightByVersion, ok := b.lastResolverState.Attributes.Value(weightsAttrsKey).(map[string]int); ok {       b.picker = NewCanaryPicker(base.PickerBuildInfo{ReadySCs: readySCs}, weightByVersion)    } else {       \/\/ \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0439 RoundRobin \u043f\u0438\u043a\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u0445 \u0432\u044b\u0448\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 clientConn       b.picker = BuildRRPicker(base.PickerBuildInfo{ReadySCs: readySCs})    } } <\/code><\/pre>\n<p>\u042d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0430\u0434\u043e \u043f\u0440\u043e\u043a\u0438\u043d\u0443\u0442\u044c \u0432 PickerBuilder, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0439 Picker \u043d\u0443\u0436\u043d\u043e\u0439 \u043d\u0430\u043c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u043f\u0440\u043e \u0432\u0435\u0441\u0430 \u0440\u0435\u043b\u0438\u0437\u043e\u0432.<\/p>\n<p>\u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0436\u0435 Picker \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u043f\u0440\u043e \u0432\u0435\u0440\u0441\u0438\u0438 \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u043c \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u044b \u043d\u0430 \u0433\u0440\u0443\u043f\u043f\u044b, \u043c\u0435\u0436\u0434\u0443 \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0431\u0443\u0434\u0435\u043c \u0434\u0435\u043b\u0430\u0442\u044c \u0432\u044b\u0431\u043e\u0440. \u0414\u043b\u044f \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0439 Picker\u2019\u043e\u0432, \u0441\u043e\u0431\u0435\u0440\u0451\u043c \u0438\u0445 \u0432 \u0446\u0435\u043f\u043e\u0447\u043a\u0443. \u041a\u0430\u0436\u0434\u044b\u0439 \u0432\u044b\u0448\u0435\u0441\u0442\u043e\u044f\u0449\u0438\u0439 Picker \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u043a\u0430\u043a\u0443\u044e-\u0442\u043e \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443, \u0430 \u0441\u0430\u043c\u044b\u0439 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u2014 \u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u043a\u0438. \u041f\u043e\u043a\u0430 \u0447\u0442\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u043d\u0430\u0448\u0438\u043c \u043b\u044e\u0431\u0438\u043c\u044b\u043c RoundRobin Picker\u2019\u043e\u043c.\u00a0<\/p>\n<pre><code class=\"go\">func NewCanaryPicker(info base.PickerBuildInfo, weightsByVersion map[string]int) balancer.Picker {      byVersion := make(map[string]map[balancer.SubConn]base.SubConnInfo)      for subConn, connInfo := range info.ReadySCs {       v, ok := connInfo.Address.Attributes.Value(versionAttrKey).(string)       if !ok {          continue       }         m := byVersion[v]       if m == nil {          m = make(map[balancer.SubConn]base.SubConnInfo)       }       m[subConn] = connInfo       byVersion[v] = m    }      switch len(byVersion) {    case 0:       return NewErrPicker(balancer.ErrNoSubConnAvailable)    case 1:       \/\/ \u043d\u0435 \u043a\u0430\u043d\u0430\u0440\u0435\u0439\u043a\u0430 :)       for version, _ := range weightsByVersion {          return BuildRRPicker(base.PickerBuildInfo{ReadySCs: byVersion[version]})       }    }      byVersionPickers := make([]wrappedPicker, 0, len(byVersion))    var totalWeight int    for version, w := range weightsByVersion {       totalWeight += w       byVersionPickers = append(byVersionPickers, wrappedPicker{          weight: w,          picker: BuildRRPicker(base.PickerBuildInfo{ReadySCs: byVersion[version]}),       })    }      return &amp;CanaryPicker{       totalWeight:      totalWeight,       byVersionPickers: byVersionPickers,    } }   func (p *CanaryPicker) Pick(info balancer.PickInfo) (balancer.PickResult, error) {    weight := fastrand.Intn(p.totalWeight)      for _, version := range p.byVersionPickers {       weight -= version.weight       if weight &lt; 0 {          return version.picker.Pick(info)       }    }      if len(p.byVersionPickers) == 0 {       return balancer.PickResult{}, errors.New(\"picker has no versions available\")    }      return p.byVersionPickers[0].picker.Pick(info) } <\/code><\/pre>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u0432\u0441\u0451 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442:<\/p>\n<details class=\"spoiler\">\n<summary>\u041b\u043e\u0433\u0438 \u043c\u043e\u043a\u0430 DNS:<\/summary>\n<div class=\"spoiler__content\">\n<p>2023\/12\/06 22:05:37 new request with query: target=helloworld_server<\/p>\n<p>2023\/12\/06 22:05:42 new request with query: target=helloworld_server<\/p>\n<p>2023\/12\/06 22:05:47 new request with query: target=helloworld_server<\/p>\n<p>2023\/12\/06 22:05:52 new request with query: target=helloworld_server<\/p>\n<p>2023\/12\/06 22:05:57 new request with query: target=helloworld_server<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>\u041b\u043e\u0433\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430:<\/summary>\n<div class=\"spoiler__content\">\n<p>2023\/12\/06 22:05:37 resolver made request: {[{127.0.0.1:8080 v1} {127.0.0.1:8090 v2}] map[v1:10 v2:90] {&#171;loadBalancingPolicy&#187;: &#171;habr_balancer&#187;}}<\/p>\n<p>2023\/12\/06 22:05:37 Greeting: Hello OzonTech<\/p>\n<p>2023\/12\/06 22:05:39 Greeting: Hello OzonTech<\/p>\n<p>2023\/12\/06 22:05:41 Greeting: Hello OzonTech<\/p>\n<p>2023\/12\/06 22:05:42 resolver made request: {[{127.0.0.1:8080 v1} {127.0.0.1:8090 v2}] map[v1:10 v2:90] {&#171;loadBalancingPolicy&#187;: &#171;habr_balancer&#187;}}<\/p>\n<p>2023\/12\/06 22:05:43 Greeting: Hello OzonTech<\/p>\n<p>2023\/12\/06 22:05:45 Greeting: Hello OzonTech<\/p>\n<p>2023\/12\/06 22:05:47 resolver made request: {[{127.0.0.1:8080 v1} {127.0.0.1:8090 v2}] map[v1:10 v2:90] {&#171;loadBalancingPolicy&#187;: &#171;habr_balancer&#187;}}<\/p>\n<p>2023\/12\/06 22:05:47 Greeting: Hello OzonTech<\/p>\n<p>2023\/12\/06 22:05:49 Greeting: Hello OzonTech<\/p>\n<p>2023\/12\/06 22:05:51 Greeting: Hello OzonTech<\/p>\n<p>2023\/12\/06 22:05:52 resolver made request: {[{127.0.0.1:8080 v1} {127.0.0.1:8090 v2}] map[v1:10 v2:90] {&#171;loadBalancingPolicy&#187;: &#171;habr_balancer&#187;}}<\/p>\n<p>2023\/12\/06 22:05:53 Greeting: Hello OzonTech<\/p>\n<p>2023\/12\/06 22:05:55 Greeting: Hello OzonTech<\/p>\n<p>2023\/12\/06 22:05:57 resolver made request: {[{127.0.0.1:8080 v1} {127.0.0.1:8090 v2}] map[v1:10 v2:90] {&#171;loadBalancingPolicy&#187;: &#171;habr_balancer&#187;}}<\/p>\n<p>Exiting.<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>\u041b\u043e\u0433\u0438 \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u043d\u0430 \u043f\u043e\u0440\u0442\u0443 8080:<\/summary>\n<div class=\"spoiler__content\">\n<p>2023\/12\/06 22:03:45 server listening at [::]:8080<\/p>\n<p>2023\/12\/06 22:05:37 Received: OzonTech<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>\u041b\u043e\u0433\u0438 \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u043d\u0430 \u043f\u043e\u0440\u0442\u0443 8090:<\/summary>\n<div class=\"spoiler__content\">\n<p>2023\/12\/06 22:04:13 server listening at [::]:8090<\/p>\n<p>2023\/12\/06 22:05:39 Received: OzonTech<\/p>\n<p>2023\/12\/06 22:05:41 Received: OzonTech<\/p>\n<p>2023\/12\/06 22:05:43 Received: OzonTech<\/p>\n<p>2023\/12\/06 22:05:45 Received: OzonTech<\/p>\n<p>2023\/12\/06 22:05:47 Received: OzonTech<\/p>\n<p>2023\/12\/06 22:05:49 Received: OzonTech<\/p>\n<p>2023\/12\/06 22:05:51 Received: OzonTech<\/p>\n<p>2023\/12\/06 22:05:53 Received: OzonTech<\/p>\n<p>2023\/12\/06 22:05:55 Received: OzonTech<\/p>\n<\/div>\n<\/details>\n<p>\u041f\u043e \u043b\u043e\u0433\u0430\u043c \u043c\u043e\u0436\u043d\u043e \u0443\u0432\u0438\u0434\u0435\u0442\u044c, \u0447\u0442\u043e \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u043d\u0430 \u043f\u043e\u0440\u0442\u0443 8090, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u043c\u0435\u043b \u0432\u0435\u0440\u0441\u0438\u044e v2 \u0441 \u0432\u0435\u0441\u043e\u043c 90 &#8212; \u043f\u043e\u043b\u0443\u0447\u0438\u043b 9 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0438\u0437 10, \u0430 \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u043d\u0430 \u043f\u043e\u0440\u0442\u0443 8080, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u043c\u0435\u043b \u0432\u0435\u0440\u0441\u0438\u044e v1 \u0441 \u0432\u0435\u0441\u043e\u043c 10 &#8212; \u043f\u043e\u043b\u0443\u0447\u0438\u043b 1 \u0437\u0430\u043f\u0440\u043e\u0441 \u0438\u0437 10, \u0447\u0442\u043e \u043c\u044b \u0438 \u043e\u0436\u0438\u0434\u0430\u043b\u0438).<\/p>\n<h2>\u0421\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u043a\u0438<\/h2>\n<p>\u0418 \u043a\u0443\u0434\u0430 \u0436\u0435 \u0431\u0435\u0437 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u0432 \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u043a\u0438? \ud83d\ude42 \u041d\u0430\u0447\u043d\u0451\u043c \u0441 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u2014 \u0441 WRR (weighted round robin).<\/p>\n<p>\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u043c \u043e\u0442\u0432\u0435\u0442 \u043e\u0442 \u043c\u043e\u043a\u0430 DNS \u0432\u0435\u0441\u0430\u043c\u0438 \u043f\u043e \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u043f\u043e\u0434\u0443 \u0432 \u0440\u0435\u043b\u0438\u0437\u0435 v2:<\/p>\n<pre><code class=\"go\">var HelloWorldServerResponse = Response{    Endpoints: []Endpoint{       {          Address: \"127.0.0.1:8080\",          Version: \"v1\",       },       {          Address: \"127.0.0.1:8090\",          Version: \"v2\",          Weight:  33,       },       {          Address: \"127.0.0.1:8095\",          Version: \"v2\",          Weight:  67,       },    },    VersionWeights: map[string]int{       \"v1\": 10,       \"v2\": 90,    },    ServiceConfig: \"{\\\"loadBalancingPolicy\\\": \\\"habr_balancer\\\"}\", } <\/code><\/pre>\n<p>\u0421\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c \u0435\u0433\u043e \u0441 \u0443\u0436\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u043c Canary Picker:<\/p>\n<pre><code class=\"go\">for version, w := range weightsByVersion {    totalWeight += w    byVersionPickers = append(byVersionPickers, wrappedPicker{       weight: w,       picker: NewWRRPicker(base.PickerBuildInfo{ReadySCs: byVersion[version]}),    }) }<\/code><\/pre>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430 WRR \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 Random \u0432\u043e\u0437\u044c\u043c\u0435\u043c <a href=\"https:\/\/github.com\/grpc\/grpc-go\/blob\/v1.59.0\/internal\/wrr\/random.go\"><u>\u0433\u043e\u0442\u043e\u0432\u0443\u044e<\/u><\/a> \u0438\u0437 gRPC \u0438 \u043e\u0431\u0435\u0440\u043d\u0435\u043c \u0435\u0451 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043e\u0439 Picker\u2019\u0430:<\/p>\n<pre><code class=\"go\">type (    WRRPicker struct {       wrr *RandomWRR    } )   func NewWRRPicker(info base.PickerBuildInfo) balancer.Picker {    p := &amp;WRRPicker{       wrr: NewRandom(),    }      for subConn, connInfo := range info.ReadySCs {       w, ok := connInfo.Address.Attributes.Value(weightAttrKey).(int)       if !ok {          \/\/ \u0415\u0441\u043b\u0438 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u043d\u0435\u0442, \u0442\u043e \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c 0 \u0432\u0435\u0441          w = 0       }       \/\/ \u0412 \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u0443 \u0432\u0441\u0435\u0445 subConn \u0432\u0435\u0441 \u043d\u0443\u043b\u0435\u0432\u043e\u0439 - WRR \u0432\u044b\u0440\u043e\u0434\u0438\u0442\u0441\u044f \u0432 Random       p.wrr.Add(subConn, w)    }    return p }   func (p *WRRPicker) Pick(_ balancer.PickInfo) (balancer.PickResult, error) {    subConn, ok := p.wrr.Next().(balancer.SubConn)    if !ok {       return balancer.PickResult{}, errors.New(\"WRRPicker internal state error. Invalid item\")    }    return balancer.PickResult{SubConn: subConn}, nil }   \/\/ weightedItem is a wrapped weighted item that is used to implement weighted random algorithm. type weightedItem struct {    item              any    weight            int    accumulatedWeight int }   \/\/ RandomWRR is a struct that contains weighted items implement weighted random algorithm. type RandomWRR struct {    items []*weightedItem    \/\/ Are all item's weights equal    equalWeights bool }   \/\/ NewRandom creates a new WRR with random. func NewRandom() *RandomWRR {    return &amp;RandomWRR{} }   func (rw *RandomWRR) Next() (item any) {    if len(rw.items) == 0 {       return nil    }    if rw.equalWeights {       return rw.items[fastrand.Intn(len(rw.items))].item    }      sumOfWeights := rw.items[len(rw.items)-1].accumulatedWeight    \/\/ Random number in [0, sumOfWeights).    randomWeight := fastrand.Intn(sumOfWeights)    \/\/ Item's accumulated weights are in ascending order, because item's weight >= 0.    \/\/ Binary search rw.items to find first item whose accumulatedWeight > randomWeight    \/\/ The return i is guaranteed to be in range [0, len(rw.items)) because randomWeight &lt; last item's accumulatedWeight    i := sort.Search(len(rw.items), func(i int) bool { return rw.items[i].accumulatedWeight > randomWeight })    return rw.items[i].item }   func (rw *RandomWRR) Add(item any, weight int) {    accumulatedWeight := weight    equalWeights := true    if len(rw.items) > 0 {       lastItem := rw.items[len(rw.items)-1]       accumulatedWeight = lastItem.accumulatedWeight + weight       equalWeights = rw.equalWeights &amp;&amp; weight == lastItem.weight    }    rw.equalWeights = equalWeights    rItem := &amp;weightedItem{item: item, weight: weight, accumulatedWeight: accumulatedWeight}    rw.items = append(rw.items, rItem) } <\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u041b\u043e\u0433\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430:<\/summary>\n<div class=\"spoiler__content\">\n<p>2023\/12\/06 23:17:08 resolver made request: {[{127.0.0.1:8080 v1 0} {127.0.0.1:8090 v2 33} {127.0.0.1:8095 v2 67}] map[v1:10 v2:90] {&#171;loadBalancingPolicy&#187;: &#171;habr_balancer&#187;}}<\/p>\n<p>2023\/12\/06 23:17:08 Greeting: Hello OzonTech<\/p>\n<p>2023\/12\/06 23:17:10 Greeting: Hello OzonTech<\/p>\n<p>2023\/12\/06 23:17:12 Greeting: Hello OzonTech<\/p>\n<p>2023\/12\/06 23:17:13 resolver made request: {[{127.0.0.1:8080 v1 0} {127.0.0.1:8090 v2 33} {127.0.0.1:8095 v2 67}] map[v1:10 v2:90] {&#171;loadBalancingPolicy&#187;: &#171;habr_balancer&#187;}}<\/p>\n<p>2023\/12\/06 23:17:14 Greeting: Hello OzonTech<\/p>\n<p>2023\/12\/06 23:17:16 Greeting: Hello OzonTech<\/p>\n<p>2023\/12\/06 23:17:18 resolver made request: {[{127.0.0.1:8080 v1 0} {127.0.0.1:8090 v2 33} {127.0.0.1:8095 v2 67}] map[v1:10 v2:90] {&#171;loadBalancingPolicy&#187;: &#171;habr_balancer&#187;}}<\/p>\n<p>2023\/12\/06 23:17:18 Greeting: Hello OzonTech<\/p>\n<p>2023\/12\/06 23:17:20 Greeting: Hello OzonTech<\/p>\n<p>2023\/12\/06 23:17:22 Greeting: Hello OzonTech<\/p>\n<p>2023\/12\/06 23:17:23 resolver made request: {[{127.0.0.1:8080 v1 0} {127.0.0.1:8090 v2 33} {127.0.0.1:8095 v2 67}] map[v1:10 v2:90] {&#171;loadBalancingPolicy&#187;: &#171;habr_balancer&#187;}}<\/p>\n<p>2023\/12\/06 23:17:24 Greeting: Hello OzonTech<\/p>\n<p>2023\/12\/06 23:17:26 Greeting: Hello OzonTech<\/p>\n<p>2023\/12\/06 23:17:28 resolver made request: {[{127.0.0.1:8080 v1 0} {127.0.0.1:8090 v2 33} {127.0.0.1:8095 v2 67}] map[v1:10 v2:90] {&#171;loadBalancingPolicy&#187;: &#171;habr_balancer&#187;}}<\/p>\n<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>\u041b\u043e\u0433\u0438 \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u043d\u0430 \u043f\u043e\u0440\u0442\u0443 8080:<\/summary>\n<div class=\"spoiler__content\">\n<p>2023\/12\/06 23:17:04 server listening at [::]:8080<\/p>\n<p>2023\/12\/06 23:17:20 Received: OzonTech<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>\u041b\u043e\u0433\u0438 \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u043d\u0430 \u043f\u043e\u0440\u0442\u0443 8090:<\/summary>\n<div class=\"spoiler__content\">\n<p>2023\/12\/06 23:17:01 server listening at [::]:8090<\/p>\n<p>2023\/12\/06 23:17:08 Received: OzonTech<\/p>\n<p>2023\/12\/06 23:17:10 Received: OzonTech<\/p>\n<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>\u041b\u043e\u0433\u0438 \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u043d\u0430 \u043f\u043e\u0440\u0442\u0443 8095:<\/summary>\n<div class=\"spoiler__content\">\n<p>2023\/12\/06 23:17:06 server listening at [::]:8095<\/p>\n<p>2023\/12\/06 23:17:12 Received: OzonTech<\/p>\n<p>2023\/12\/06 23:17:14 Received: OzonTech<\/p>\n<p>2023\/12\/06 23:17:16 Received: OzonTech<\/p>\n<p>2023\/12\/06 23:17:18 Received: OzonTech<\/p>\n<p>2023\/12\/06 23:17:22 Received: OzonTech<\/p>\n<p>2023\/12\/06 23:17:24 Received: OzonTech<\/p>\n<p>2023\/12\/06 23:17:26 Received: OzonTech<\/p>\n<\/div>\n<\/details>\n<p>\u0418\u0442\u043e\u0433\u043e \u043d\u0430 \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u043d\u0430 \u043f\u043e\u0440\u0442\u0443 8090, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u043c\u0435\u043b \u0432\u0435\u0440\u0441\u0438\u044e v2 \u0441 \u0432\u0435\u0441\u043e\u043c 90 \u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0432\u0435\u0441 67 &#8212; \u043f\u043e\u043b\u0443\u0447\u0438\u043b 7 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0438\u0437 10, \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u043d\u0430 \u043f\u043e\u0440\u0442\u0443 8095, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u043c\u0435\u043b \u0432\u0435\u0440\u0441\u0438\u044e v2 \u0441 \u0432\u0435\u0441\u043e\u043c 90 \u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0432\u0435\u0441 33 &#8212; \u043f\u043e\u043b\u0443\u0447\u0438\u043b 2 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438\u0437 10, \u0430 \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u043d\u0430 \u043f\u043e\u0440\u0442\u0443 8080, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u043c\u0435\u043b \u0432\u0435\u0440\u0441\u0438\u044e v1 \u0441 \u0432\u0435\u0441\u043e\u043c 10 &#8212; \u0432\u0441\u0435 \u0442\u0430\u043a \u0436\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b 1 \u0437\u0430\u043f\u0440\u043e\u0441 \u0438\u0437 10. \u0421 \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0430\u043c\u0438 \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u0432\u0435\u0440\u0441\u0438\u0438 v2 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u043d\u0435 \u043f\u0440\u044f\u043c \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u043e (6 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432 \u043e\u0434\u0438\u043d \u0438 3 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432 \u0434\u0440\u0443\u0433\u043e\u0439), \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u044d\u0442\u043e \u0432\u0441\u0435 \u0436\u0435 \u0432\u0435\u043b\u0438\u043a\u0438\u0439 \u0440\u0430\u043d\u0434\u043e\u043c \ud83d\ude42<\/p>\n<p>\u041d\u0443 \u0438 \u0447\u0442\u043e-\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0435 \u2014 leastConn.<\/p>\n<pre><code class=\"go\">\/\/ leastConnItem is a wrapped weighted item that is used to implement least conn algorithm. type leastConnItem struct {    item        balancer.SubConn    inFlightReq atomic.Int64 }   type LeastConnPicker struct {    lc *leastConnections }   func NewLeastConnPicker(info base.PickerBuildInfo) balancer.Picker {    if len(info.ReadySCs) == 0 {       return NewErrPicker(errors.New(\"no subConn available\"))    }    var items []balancer.SubConn    for subConn := range info.ReadySCs {       items = append(items, subConn)    }      p := &amp;LeastConnPicker{       lc: New(items),    }      return p }   func (p *LeastConnPicker) Pick(_ balancer.PickInfo) (balancer.PickResult, error) {    subConn, doneFn := p.lc.Next()    if subConn == nil {       return balancer.PickResult{}, errors.New(\"LeastConnPicker internal state error. No subConns in leastConn state\")    }    return balancer.PickResult{SubConn: subConn, Done: doneFn}, nil }   type leastConnections struct {    conns []*leastConnItem }   func New(items []balancer.SubConn) *leastConnections {    conns := make([]*leastConnItem, 0, len(items))    for _, i := range items {       conns = append(conns, &amp;leastConnItem{          item:        i,          inFlightReq: atomic.Int64{},       })    }    return &amp;leastConnections{       conns: conns,    } }   func (lc *leastConnections) Next() (balancer.SubConn, func(info balancer.DoneInfo)) {    if len(lc.conns) == 0 {       return nil, nil    }      var (       minInFlightReq = int64(-1)       idx            int    )      for i, conn := range lc.conns {       inFlightReq := conn.inFlightReq.Load()       if minInFlightReq == -1 || inFlightReq &lt; minInFlightReq {          minInFlightReq = inFlightReq          idx = i       }    }      lc.conns[idx].inFlightReq.Add(1)      return lc.conns[idx].item, func(balancer.DoneInfo) {       lc.conns[idx].inFlightReq.Add(-1)    } } <\/code><\/pre>\n<p>\u0412\u0430\u0436\u043d\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c, \u0447\u0442\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043e\u0442 Resolver\u2019\u0430 \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043d\u043e\u0432\u043e\u0433\u043e Picker, \u0447\u0442\u043e \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u0442 \u043a \u043f\u043e\u0442\u0435\u0440\u0435 \u043d\u0430\u043a\u043e\u043f\u043b\u0435\u043d\u043d\u044b\u0445 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u0445\u0435\u043c\u0430 \u0441 \u043f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u0438\u043c lookup \u0438 \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u044b\u043c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043d\u0430\u043c \u0443\u0436\u0435 \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043b\u0438\u0431\u043e \u0432 Resolver \u043a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0448\u043b\u044b\u0439 \u043e\u0442\u0432\u0435\u0442, \u043b\u0438\u0431\u043e \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u0442\u044c \u0435\u0433\u043e \u043c\u043e\u0434\u0435\u043b\u044c \u043d\u0430 Push, \u043d\u043e \u044d\u0442\u043e \u0443\u0436\u0435 \u043d\u0435 \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438. \u0414\u043b\u044f \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u043c \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u0440\u0430\u0431\u043e\u0442\u044b lookup \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043e 50 \u0441\u0435\u043a\u0443\u043d\u0434, \u0447\u0442\u043e\u0431\u044b \u043e\u043d\u0430 \u043d\u0430\u043c \u043d\u0435 \u043c\u0435\u0448\u0430\u043b\u0430.<\/p>\n<p>\u0412 \u0431\u044d\u043a\u0435\u043d\u0434\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0437\u0430\u0434\u0430\u0432\u0430\u0435\u043c\u0443\u044e \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0443 \u043e\u0442\u0432\u0435\u0442\u0430 \u0438 \u043b\u043e\u0433 \u043e\u0431 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 \u043e\u0442\u0432\u0435\u0442\u0430. \u041f\u0443\u0441\u0442\u044c \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u0441 \u043f\u043e\u0440\u0442\u043e\u043c 8090 \u0431\u0443\u0434\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0443 \u043d\u0430 \u043e\u0442\u0432\u0435\u0442 \u0432 10 \u0441\u0435\u043a\u0443\u043d\u0434.\u00a0<\/p>\n<details class=\"spoiler\">\n<summary>\u041b\u043e\u0433\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430:<\/summary>\n<div class=\"spoiler__content\">\n<p>2023\/12\/07 00:25:34 resolver made request: {[{127.0.0.1:8080 v1 0} {127.0.0.1:8090 v2 33} {127.0.0.1:8095 v2 67}] map[v1:10 v2:90] {&#171;loadBalancingPolicy&#187;: &#171;habr_balancer&#187;}}<\/p>\n<p>2023\/12\/07 00:25:37 Greeting: Hello OzonTech<\/p>\n<p>2023\/12\/07 00:25:39 Greeting: Hello OzonTech<\/p>\n<p>2023\/12\/07 00:25:41 Greeting: Hello OzonTech<\/p>\n<p>2023\/12\/07 00:25:43 Greeting: Hello OzonTech<\/p>\n<p>2023\/12\/07 00:25:45 Greeting: Hello OzonTech<\/p>\n<p>2023\/12\/07 00:25:45 Greeting: Hello OzonTech<\/p>\n<p>2023\/12\/07 00:25:49 Greeting: Hello OzonTech<\/p>\n<p>2023\/12\/07 00:25:51 Greeting: Hello OzonTech<\/p>\n<p>2023\/12\/07 00:25:53 Greeting: Hello OzonTech<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>\u041b\u043e\u0433\u0438 \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u043d\u0430 \u043f\u043e\u0440\u0442\u0443 8080:<\/summary>\n<div class=\"spoiler__content\">\n<p>2023\/12\/07 00:25:15 server listening at [::]:8080<\/p>\n<p>2023\/12\/07 00:25:53 Received: OzonTech<\/p>\n<p>2023\/12\/07 00:25:53 Returned: OzonTech<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>\u041b\u043e\u0433\u0438 \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u043d\u0430 \u043f\u043e\u0440\u0442\u0443 8090:<\/summary>\n<div class=\"spoiler__content\">\n<p>2023\/12\/07 00:25:13 server listening at [::]:8090<\/p>\n<p>2023\/12\/07 00:25:35 Received: OzonTech<\/p>\n<p>2023\/12\/07 00:25:45 Returned: OzonTech<\/p>\n<p>2023\/12\/07 00:25:47 Received: OzonTech<\/p>\n<p>2023\/12\/07 00:25:57 Returned: OzonTech<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>\u041b\u043e\u0433\u0438 \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u043d\u0430 \u043f\u043e\u0440\u0442\u0443 8095:<\/summary>\n<div class=\"spoiler__content\">\n<p>2023\/12\/07 00:25:31 server listening at [::]:8095<\/p>\n<p>2023\/12\/07 00:25:37 Received: OzonTech<\/p>\n<p>2023\/12\/07 00:25:37 Returned: OzonTech<\/p>\n<p>2023\/12\/07 00:25:39 Received: OzonTech<\/p>\n<p>2023\/12\/07 00:25:39 Returned: OzonTech<\/p>\n<p>2023\/12\/07 00:25:41 Received: OzonTech<\/p>\n<p>2023\/12\/07 00:25:41 Returned: OzonTech<\/p>\n<p>2023\/12\/07 00:25:43 Received: OzonTech<\/p>\n<p>2023\/12\/07 00:25:43 Returned: OzonTech<\/p>\n<p>2023\/12\/07 00:25:45 Received: OzonTech<\/p>\n<p>2023\/12\/07 00:25:45 Returned: OzonTech<\/p>\n<p>2023\/12\/07 00:25:49 Received: OzonTech<\/p>\n<p>2023\/12\/07 00:25:49 Returned: OzonTech<\/p>\n<p>2023\/12\/07 00:25:51 Received: OzonTech<\/p>\n<p>2023\/12\/07 00:25:51 Returned: OzonTech<\/p>\n<p>2023\/12\/07 00:25:53 Received: OzonTech<\/p>\n<p>2023\/12\/07 00:25:53 Returned: OzonTech<\/p>\n<\/div>\n<\/details>\n<p>\u0412\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u043d\u0430 \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u0441 \u043f\u043e\u0440\u0442\u043e\u043c 8090 \u043f\u043e\u043a\u0430 \u043d\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043b\u0441\u044f \u043f\u0435\u0440\u0432\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441, \u043d\u043e\u0432\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043d\u0435 \u043b\u0435\u0442\u0435\u043b\u0438, \u043a\u043e\u0433\u0434\u0430 \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u0431\u0435\u0437 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0438 \u0441 \u043f\u043e\u0440\u0442\u043e\u043c 8095 \u043f\u043e\u043b\u0443\u0447\u0430\u043b \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b. \u041d\u0443 \u0430 \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u0441 \u043f\u043e\u0440\u0442\u043e\u043c 8080 \u0434\u043e \u0441\u0438\u0445 \u043f\u043e\u0440 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 10% \u0442\u0440\u0430\u0444\u0438\u043a\u0430 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043a\u0430\u043d\u0430\u0440\u0435\u0435\u0447\u043d\u043e\u0433\u043e Picker \ud83d\ude42<\/p>\n<h2>\u0413\u043e\u0442\u043e\u0432\u044b\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b<\/h2>\n<p>\u0412 gRPC \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0440\u044f\u0434 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0445 Resolver\u2019\u043e\u0432 \u0438 Balancer\u2019\u043e\u0432. \u041d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043d\u0430\u0437\u0430\u0434 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 <a href=\"https:\/\/grpc.github.io\/grpc\/core\/md_doc_grpc_xds_features.html\"><u>\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 xDS<\/u><\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u0431 \u0430\u0434\u0440\u0435\u0441\u0430\u0445 \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u043e\u0442 Istio \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 xDS-\u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u043e\u0432. \u0422\u0430\u043a\u0436\u0435 \u0435\u0441\u0442\u044c \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0439 <a href=\"https:\/\/github.com\/grpc\/grpc-go\/blob\/c2398ced0efdd5151b4322922b20459b3d37a0d4\/internal\/resolver\/dns\/dns_resolver.go#L103\"><u>DNS Resolver<\/u><\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0445\u043e\u0434\u0438\u0442 \u0432 DNS \u0438 \u043f\u043e RoundRobin \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043f\u043e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u043c \u0430\u0434\u0440\u0435\u0441\u0430\u043c (\u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 DNS Resolver \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 net.Transport, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u0435\u043b\u0430\u0435\u0442 Dial \u043d\u0430 \u0440\u0430\u043d\u0434\u043e\u043c\u043d\u044b\u0439 \u0430\u0434\u0440\u0435\u0441 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u0441\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0442\u0443\u0434\u0430). \u041d\u0430\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u044d\u0442\u0438 Resolver\u2019\u044b \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e xds \u0438 dns:<\/p>\n<pre><code class=\"go\">grpc.DialContext(context.Background(), \"xds:\/\/\/ozontech:grpc\") grpc.DialContext(context.Background(), \"dns:\/\/\/ozontech:grpc\")<\/code><\/pre>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 gRPC-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b\u0438 \u0441\u0432\u043e\u0438 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u043e\u043a \u0438 Service Discovery. \u0415\u0441\u043b\u0438 \u0432 \u0432\u0430\u0448\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0435\u0441\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432, \u043d\u0430\u043f\u043e\u043b\u043d\u0438\u0432 \u0435\u0433\u043e \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e, \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0435\u0449\u0451 \u043d\u0435\u0442 \u0432 \u00ab\u043a\u043e\u0440\u043e\u0431\u043e\u0447\u043d\u044b\u0445\u00bb \u0440\u0435\u0448\u0435\u043d\u0438\u044f\u0445, \u0442\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 gRPC \u043c\u043e\u0436\u0435\u0442 \u0432\u0430\u043c \u043f\u043e\u043c\u043e\u0447\u044c. \u041a\u0430\u043a, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u043e\u043c\u043e\u0433\u043b\u0430 \u043d\u0430\u043c \u0432 Ozon Tech \ud83d\ude42\u00a0<\/p>\n<p>\u041e\u043a\u043e\u043b\u043e 4 \u043b\u0435\u0442 \u043d\u0430\u0437\u0430\u0434 \u043d\u0430 \u0431\u0430\u0437\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0445 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u043e\u0432 \u0432 Ozon Tech \u0431\u044b\u043b \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 Service Mesh \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c Warden, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u043c \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u043c\u0435\u0436\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u043e\u0433\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f. \u041f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 Resolver \u0443 \u043d\u0430\u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442 \u0434\u043b\u044f Service Discovery, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u043c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u0443\u044e \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043f\u0440\u043e \u043d\u0430\u0448\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u044b. \u041d\u0430 \u0431\u0430\u0437\u0435 Balancer \u0443 \u043d\u0430\u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043f\u0430\u0434\u0435\u043d\u0438\u044f \u0434\u0430\u0442\u0430-\u0446\u0435\u043d\u0442\u0440\u043e\u0432 \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430. \u041d\u0443 \u0430 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 Picker\u2019\u043e\u0432 \u043c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b\u0438 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u0438\u0441\u044c \u043d\u0430\u043c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u043c\u0438 \u0438 \u043f\u0435\u0440\u0441\u043f\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u043c\u0438 (\u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u0445 \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043f\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0449\u0435\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u2014 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 Warden).\u00a0<\/p>\n<p>\u041d\u0430\u0434\u0435\u044e\u0441\u044c, \u0432\u0430\u043c \u0431\u044b\u043b\u0430 \u043f\u043e\u043b\u0435\u0437\u043d\u0430 \u044d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u0438 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0445 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u0432 \u0432\u044b \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0441\u0432\u043e\u0438 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443\u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u0441\u0442\u0432\u0443\u044e\u0442 \u0432\u0430\u0448\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u044b \ud83d\ude42<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0441\u0442\u0430\u0442\u044c\u044f \u043f\u043e\u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u043c\u043d\u043e\u0433\u0438\u043c (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043d\u0430\u0431\u0435\u0440\u0451\u0442 \u0431\u043e\u043b\u044c\u0448\u0435 101 \u043f\u043b\u044e\u0441\u0430 :D), \u0442\u043e \u044f \u043d\u0430\u043f\u0438\u0448\u0443 \u0432\u0442\u043e\u0440\u0443\u044e \u0447\u0430\u0441\u0442\u044c, \u0433\u0434\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u044e \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u044b \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0442\u0440\u0430\u0444\u0438\u043a\u0430 \u043c\u0435\u0436\u0434\u0443 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0433\u0440\u0443\u043f\u043f\u0430\u043c\u0438 \u0430\u0434\u0440\u0435\u0441\u043e\u0432, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0442\u044c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043e\u0448\u0438\u0431\u043e\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0442 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0430\u0431\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u044b, \u0438 \u0438\u0441\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0438\u0445 \u0438\u0437 \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u043a\u0438.<\/p>\n<p>\u0412\u0441\u0435 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0435 \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u0438 \u043d\u0430\u0448\u0435\u0439 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043d\u0430\u0439\u0442\u0438 \u043d\u0430 <a href=\"http:\/\/job.ozon.ru\">job.ozon.ru<\/a>. \u0421\u0435\u0439\u0447\u0430\u0441 \u0432 \u043e\u0442\u0434\u0435\u043b\u0435 Service Mesh, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043a\u043e\u0432\u044b\u0440\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c gRPC \u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 Warden, \u0435\u0441\u0442\u044c \u043e\u0442\u043a\u0440\u044b\u0442\u0430\u044f \u0432\u0430\u043a\u0430\u043d\u0441\u0438\u044f \ud83d\ude42 \u0411\u043e\u043b\u044c\u0448\u0435 \u043f\u0440\u043e Warden \u043c\u043e\u0436\u043d\u043e \u0443\u0437\u043d\u0430\u0442\u044c \u0438\u0437 <a href=\"https:\/\/youtu.be\/kcgPNh8eQXg?t=3230\"><u>\u0434\u043e\u043a\u043b\u0430\u0434\u0430<\/u><\/a>.<strong>\u00a0<\/strong><\/p>\n<p>P.S. \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043f\u043e <a href=\"https:\/\/github.com\/nezhibitskiy\/habr_grpc\"><u>\u0441\u0441\u044b\u043b\u043a\u0435<\/u><\/a>. \u041e\u043d \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u043c. \u041d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0435\u0433\u043e \u0432 \u043f\u0440\u043e\u0434\u0435 \ud83d\ude42<\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/779266\/\"> https:\/\/habr.com\/ru\/articles\/779266\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0418\u043b\u044c\u044f\u0441. \u041c\u044b \u0441 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 \u0434\u0435\u043b\u0430\u0435\u043c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 Service Mesh \u0432 Ozon Tech, \u0438 \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0437\u0430 \u0432\u0435\u0447\u0435\u0440 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0435 \u0441\u0443\u043f\u0435\u0440 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0435 \u043c\u0435\u0436\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u043e\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435. \u041a \u043a\u043e\u043d\u0446\u0443 \u0441\u0442\u0430\u0442\u044c\u0438 \u043c\u044b \u0441 \u0432\u0430\u043c\u0438 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u043a\u0438, \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u043a\u0430\u043d\u0430\u0440\u0435\u0435\u0447\u043d\u044b\u0435 \u0434\u0435\u043f\u043b\u043e\u0438, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0443\u0437\u043d\u0430\u0435\u043c, \u043a\u0430\u043a \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u0443\u0447\u0443 \u0434\u0440\u0443\u0433\u0438\u0445 \u0441\u0443\u043f\u0435\u0440\u043d\u0435\u043e\u0431\u044b\u0447\u043d\u044b\u0445 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u043e\u0432 \u043c\u0435\u0436\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u043e\u0433\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435, \u043d\u0435 \u043f\u043e\u0432\u0435\u0440\u0438\u0442\u0435, \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 gRPC :D. \u0418 \u0434\u0430, \u043c\u044b \u0441 \u043c\u043e\u0435\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 \u0443\u0436\u0435 \u0440\u0430\u0441\u043a\u0430\u0442\u0438\u043b\u0438 \u044d\u0442\u043e \u043d\u0430 \u0432\u0435\u0441\u044c Ozon Tech, \u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0438\u0439 \u0438\u0437 5000 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u041f\u0440\u0438\u0441\u0442\u0435\u0433\u043d\u0438\u0442\u0435\u0441\u044c \u2014 \u043c\u044b \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u043c\u2026 \ud83d\ude42<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u2026 \u043f\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0443.<\/p>\n<h2>\u041c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u0438 \u0435\u0451 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438<\/h2>\n<p>\u0421 \u043f\u0440\u0438\u0445\u043e\u0434\u043e\u043c \u0432 \u043d\u0430\u0448 \u043c\u0438\u0440 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0431\u0435\u043b \u043c\u0435\u0436\u0434\u0443 \u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b \u043e\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043f\u043e \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0432\u044f\u0437\u043d\u043e\u0441\u0442\u0438 \u044d\u0442\u0438\u0445 \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u0421\u0430\u043c\u044b\u043c \u043f\u0440\u043e\u0441\u0442\u044b\u043c \u0438 \u043b\u043e\u0433\u0438\u0447\u043d\u044b\u043c \u0431\u044b\u043b\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u0442 \u0436\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0442\u0440\u0430\u0444\u0438\u043a \u043e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e \u2014 HTTP. \u041d\u043e \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441 \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u043d\u0430 \u043c\u0435\u0441\u0442\u0435. \u0414\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u043b\u0438 \u0442\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434, \u043a\u0430\u043a RPC (remote procedure call, \u0438\u043b\u0438 \u043d\u0430 \u0432\u0435\u043b\u0438\u043a\u043e\u043c \u0438 \u043c\u043e\u0433\u0443\u0447\u0435\u043c \u2013 \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u044b\u0439 \u0432\u044b\u0437\u043e\u0432 \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u044b). \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0439 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u2014 \u043a\u0430\u043a \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 JSON \u0432 \u043f\u0440\u0438\u0432\u044b\u0447\u043d\u044b\u0445 HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445, \u0442\u0430\u043a \u0438 \u0443\u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0431\u043e\u043b\u0435\u0435 \u0441\u0436\u0430\u0442\u043e\u043c \u0432\u0438\u0434\u0435. \u0421\u0430\u043c\u044b\u0439 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0439 \u0438 \u0443\u0432\u0430\u0436\u0430\u0435\u043c\u044b\u0439 \u0432 Ozon Tech \u2014 gRPC. \u0411\u043e\u043b\u044c\u0448\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0433\u043e \u043c\u0435\u0436\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u043e\u0433\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0432 \u043d\u0430\u0448\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430.\u00a0<\/p>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0440\u0435\u0447\u044c \u043f\u043e\u0439\u0434\u0451\u0442 \u043d\u0435 \u043f\u0440\u043e \u00ab\u0440\u0435\u043a\u043b\u0430\u043c\u043d\u044b\u0435\u00bb \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430 gRPC, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a \u0432\u044b\u0441\u043e\u043a\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c, \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u043e \u0438 \u0442. \u0434., \u0430 \u043a\u043e\u0435 \u043e \u0447\u0451\u043c \u043d\u0435\u043e\u0431\u044b\u0447\u043d\u043e\u043c, \u0447\u0442\u043e \u043a\u043e\u0433\u0434\u0430-\u0442\u043e \u043b\u0438\u0447\u043d\u043e \u043c\u0435\u043d\u044f \u043f\u043e\u0440\u0430\u0437\u0438\u043b\u043e, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e \u2014 \u043e \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u043e\u043c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u0435 \u043f\u043e\u0438\u0441\u043a\u0430 \u0430\u0434\u0440\u0435\u0441\u043e\u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0441\u043e\u0432\u0435\u0440\u0448\u0430\u044e\u0442\u0441\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u044b, \u043e \u043c\u0435\u043d\u0435\u0434\u0436\u043c\u0435\u043d\u0442\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 \u043a \u0440\u0430\u0437\u043d\u044b\u043c \u0435\u0433\u043e \u0430\u0434\u0440\u0435\u0441\u0430\u043c, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u043a\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043c\u0435\u0436\u0434\u0443 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u043a\u043e\u043f\u0438\u044f\u043c\u0438 \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041d\u0443 \u0438\u043b\u0438, \u0435\u0441\u043b\u0438 \u043a\u043e\u0440\u043e\u0442\u043a\u043e, &#8212; \u0440\u0435\u0447\u044c \u043f\u0440\u043e Resolver, Balancer \u0438 Picker \u0432 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 gRPC-go \ud83d\ude42<\/p>\n<p>\u041c\u044b \u043f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u043c\u0441\u044f \u0441\u043e \u0432\u0441\u0435\u043c\u0438 \u044d\u0442\u0438\u043c\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438, \u043f\u0440\u0435\u043f\u0430\u0440\u0438\u0440\u0443\u0435\u043c \u0438\u0445 \u0438 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u0430\u0436\u0434\u043e\u0439 \u0438\u0437 \u043d\u0438\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0442 \u043d\u0430\u043c \u043a \u043a\u043e\u043d\u0446\u0443 \u0441\u0442\u0430\u0442\u044c\u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f\u043c\u0438 \u043c\u0435\u0436\u0434\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438. \u0421\u0442\u0430\u0442\u044c\u044f \u043d\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0430 \u043a\u043e\u0434\u043e\u043c, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u043c \u043d\u0430 Go, \u043d\u043e \u0432 \u0446\u0435\u043b\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043c\u0430 \u0438 \u043a \u0434\u0440\u0443\u0433\u0438\u043c \u044f\u0437\u044b\u043a\u0430\u043c, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0435\u0441\u0442\u044c \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f gRPC \u043e\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 Google (\u0421#, Java, C++, JavaScript, Swift \u0438 <a href=\"https:\/\/grpc.io\/docs\/languages\/\"><u>\u0434\u0440\u0443\u0433\u0438\u0445<\/u><\/a>). \u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f\u0437\u044b\u043a\u0438 \u0438\u043c\u0435\u044e\u0442 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e, \u0430 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u2014 \u043e\u0431\u0451\u0440\u0442\u043a\u0443 \u043d\u0430\u0434 \u0433\u043b\u0430\u0432\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430 \u043d\u0430 \u0421.\u00a0<\/p>\n<h2>\u041a\u043e\u0433\u0434\u0430 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430?<\/h2>\n<p>\u041a\u043e\u0433\u0434\u0430 \u043c\u043e\u043d\u043e\u043b\u0438\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0442 \u0440\u0430\u0441\u043f\u0438\u043b\u0438\u0432\u0430\u0442\u044c \u043d\u0430 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0438\u043b\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442 \u043d\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442, \u0432\u0441\u044f \u0438\u043d\u0441\u0442\u0430\u043b\u043b\u044f\u0446\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0447\u0430\u0441\u0442\u0435\u0439 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0447\u0430\u0442\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0438\u0437 \u043e\u0434\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0432 \u0434\u0440\u0443\u0433\u043e\u0439, \u043c\u043e\u0436\u043d\u043e \u043b\u0438\u0431\u043e \u0437\u0430\u0445\u0430\u0440\u0434\u043a\u043e\u0434\u0438\u0442\u044c \u0430\u0434\u0440\u0435\u0441\u0430 \u0441\u0435\u0440\u0432\u0430\u043a\u043e\u0432 \u0438\u043b\u0438 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u043e\u043a, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0445\u043e\u0441\u0442\u0438\u0442\u0441\u044f \u043d\u0443\u0436\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c, \u043b\u0438\u0431\u043e \u043f\u043e\u0434\u0442\u044e\u043d\u0438\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 DNS, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0442\u0443\u0434\u0430 \u0437\u0430\u043f\u0438\u0441\u0438 \u0441 \u0430\u0434\u0440\u0435\u0441\u0430\u043c\u0438 \u044d\u0442\u0438\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432, \u0438 \u0440\u0435\u0437\u043e\u043b\u0432\u0438\u0442\u044c \u0430\u0434\u0440\u0435\u0441\u0430 \u0447\u0435\u0440\u0435\u0437 \u043d\u0435\u0433\u043e. \u041d\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u044d\u0442\u043e\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 Service Discovery (\u0434\u0430-\u0434\u0430, \u043f\u043e\u0438\u0441\u043a \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 :)). \u041d\u043e, \u043a\u043e\u0433\u0434\u0430 \u044d\u0442\u0438 \u0435\u0434\u0438\u043d\u0438\u0446\u044b \u0438 \u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u044e\u0442\u0441\u044f \u0432 \u0441\u043e\u0442\u043d\u0438 \u0438 \u0442\u044b\u0441\u044f\u0447\u0438, \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0442\u0441\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b. \u0410 \u0435\u0441\u043b\u0438 \u0435\u0449\u0451 \u0432\u0441\u0435 \u044d\u0442\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0437\u0430\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u044e\u0442 \u0432 Kubernetes, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0438\u043c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u0435\u0440\u0435\u0435\u0437\u0436\u0430\u0442\u044c \u0441 \u043e\u0434\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043d\u0430 \u0434\u0440\u0443\u0433\u043e\u0439, \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441\u0443\u0449\u0438\u0439 \u0430\u0434. \u041d\u043e \u0435\u0441\u0442\u044c \u00ab\u043a\u043e\u0440\u043e\u0431\u043e\u0447\u043d\u043e\u0435\u00bb \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u2014 Service Mesh, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c\u044b\u0439 \u0441\u0430\u0439\u0434\u043a\u0430\u0440\u043e\u043c (\u043f\u0440\u0438\u0432\u0435\u0442, Envoy \u0438 Linkerd :)).<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u0442\u043e \u0442\u0430\u043a\u043e\u0439 \u044d\u0442\u043e\u0442 \u0432\u0430\u0448 Service Mesh???<\/summary>\n<div class=\"spoiler__content\">\n<p>Service Mesh \u2014 \u044d\u0442\u043e <a href=\"https:\/\/istio.io\/latest\/about\/service-mesh\/#what-is-a-service-mesh\"><u>\u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043d\u044b\u0439 \u0441\u043b\u043e\u0439<\/u><\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432 \u043e\u0431\u0449\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u043f\u043e\u0438\u0441\u043a IP-\u0430\u0434\u0440\u0435\u0441\u043e\u0432 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432, \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439, \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u043a\u0443 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438, \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u0435 \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0440\u0430\u0444\u0438\u043a\u0430 \u0438 \u043f\u0440\u043e\u0447\u0438\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u0442\u043e\u043c \u043f\u0440\u043e\u0431\u0435\u043b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0438 \u043c\u043e\u043d\u043e\u043b\u0438\u0442\u0430 \u043d\u0430 \u0447\u0430\u0441\u0442\u0438.\u00a0<\/p>\n<p>\u041e\u0431\u044b\u0447\u043d\u043e \u0432\u0441\u0435 \u043e\u043d\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0442\u0441\u044f \u043f\u0443\u0442\u0451\u043c \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043a \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e \u043d\u0435\u043a\u043e\u0435\u0433\u043e \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u043e\u0433\u043e \u0441\u0430\u0439\u0434\u043a\u0430\u0440\u043e\u043c, \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u0440\u043e\u043a\u0441\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432\u0435\u0441\u044c \u0442\u0440\u0430\u0444\u0438\u043a. \u041e\u043d\u043e \u043a\u0443\u0434\u0430-\u0442\u043e \u0441\u043e\u0432\u0435\u0440\u0448\u0430\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u044b, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u0430\u0434\u0440\u0435\u0441\u043e\u0432, \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u043a\u043e\u043d\u043d\u0435\u043a\u0442\u044b \u0438 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430 \u043d\u0438\u0445 \u0442\u0440\u0430\u0444\u0438\u043a (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, Envoy \u0434\u0435\u043b\u0430\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 Istio, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0432\u0441\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043f\u0440\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0432\u044b\u043a\u0430\u0447\u0438\u0432\u0430\u0435\u0442 \u0438\u0437 Kubernetes API). \u0418 \u044f \u043d\u0430\u0437\u0432\u0430\u043b \u044d\u0442\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u00ab\u043a\u043e\u0440\u043e\u0431\u043e\u0447\u043d\u044b\u043c\u00bb, \u0442\u0430\u043a \u043a\u0430\u043a \u0435\u0433\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043b\u0435\u0433\u043a\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043a \u0432\u0430\u0448\u0435\u043c\u0443 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0443 Kubernetes, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u043f\u0440\u0430\u0432\u0438\u043b\u043e \u043d\u0430 \u0438\u043d\u044a\u0435\u043a\u0446\u0438\u044e \u0441\u0430\u0439\u0434\u043a\u0430\u0440\u0430 \u043a \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u0432 Kubernetes.\u00a0<\/p>\n<\/div>\n<\/details>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f gRPC \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u0442\u0435\u043c, \u0447\u0442\u043e \u0432\u0441\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u0438, \u043f\u043e \u0441\u0443\u0442\u0438, \u0432\u0448\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u0431\u0438\u043d\u0430\u0440\u044c \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0422\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u0445\u043e\u0440\u043e\u0448 \u0442\u0435\u043c, \u0447\u0442\u043e \u043e\u043d \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432, \u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u0441\u0430\u0439\u0434\u043a\u0430\u0440\u043e\u0432 (\u0442\u0430\u043a \u043a\u0430\u043a \u0441\u0430\u0439\u0434\u043a\u0430\u0440 \u2014 \u044d\u0442\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f). \u041d\u043e, \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435, \u0435\u0441\u0442\u044c \u043d\u044e\u0430\u043d\u0441\u044b, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441 \u0443\u0441\u043b\u043e\u0436\u043d\u0435\u043d\u0438\u0435\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e, \u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u0441\u0430\u0439\u0434\u043a\u0430\u0440\u0430, \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u0435\u0440\u0441\u0438\u0438 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u0432\u0441\u0451 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u0435\u0435 \u0438 \u0434\u043e\u043b\u044c\u0448\u0435, \u0447\u0435\u043c \u0437\u0430\u043c\u0435\u043d\u0430 \u0431\u0438\u043d\u0430\u0440\u044f \u0432 \u0441\u0430\u0439\u0434\u043a\u0430\u0440\u0435. \u0421\u0435\u0440\u0435\u0431\u0440\u044f\u043d\u043e\u0439 \u043f\u0443\u043b\u0438 \u0432\u0441\u0451 \u0435\u0449\u0451 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \ud83d\ude41<\/p>\n<h2>\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<details class=\"spoiler\">\n<summary>\u041d\u0435\u043c\u043d\u043e\u0433\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0439<\/summary>\n<div class=\"spoiler__content\">\n<p>\u041f\u0430\u0440\u0430 \u0441\u043b\u043e\u0432 \u043e\u0431 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u0445. \u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043d\u0435\u043a\u0438\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 1, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043d\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u041a\u041b\u0418\u0415\u041d\u0422\u041e\u041c, \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0432\u0435\u0440\u0448\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a \u043d\u0435\u043a\u043e\u0435\u043c\u0443 \u0441\u0435\u0440\u0432\u0438\u0441\u0443 2, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043d\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0411\u042d\u041a\u0415\u041d\u0414\u041e\u041c.\u00a0<\/p>\n<\/div>\n<\/details>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0451\u043c \u043e\u0442 \u0441\u043b\u043e\u0432 \u043a \u0434\u0435\u043b\u0443. \u041a\u043e\u0433\u0434\u0430 \u043c\u044b \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a \u043d\u0443\u0436\u043d\u043e\u043c\u0443 \u043d\u0430\u043c \u0431\u044d\u043a\u0435\u043d\u0434\u0443 \u0447\u0435\u0440\u0435\u0437 gRPC, \u043c\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e <a href=\"https:\/\/github.com\/grpc\/grpc-go\/blob\/c2398ced0efdd5151b4322922b20459b3d37a0d4\/clientconn.go#L105\"><u>grpc.Dial<\/u><\/a>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f, \u043f\u043e\u043c\u0438\u043c\u043e \u043e\u0448\u0438\u0431\u043a\u0438 (\u0432\u0441\u0451 \u0432 \u0436\u0438\u0437\u043d\u0438 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0439\u0442\u0438 \u043d\u0435 \u0442\u0430\u043a :D), \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043d\u0435\u043a\u0438\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 ClientConn. \u042d\u0442\u043e \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u0432 gRPC, \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0430, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0438\u0440\u0443\u044e\u0442 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b Service Discovery, Load Balancing \u0438 \u0434\u0440\u0443\u0433\u0438\u0435. \u0422\u0430\u043a\u0436\u0435 ClientConn \u043f\u0440\u043e\u043a\u0441\u0438\u0440\u0443\u0435\u0442 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u044d\u0442\u0438\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 (\u0447\u0443\u0442\u044c \u043f\u043e\u0437\u0436\u0435 \u0443\u0432\u0438\u0434\u0438\u043c).<\/p>\n<figure class=\"full-width\">\n<div><figcaption><em>\u041d\u0430 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0430\u0445 \u043d\u0438\u0436\u0435 \u043e\u0431\u044a\u0435\u043a\u0442 \u041a\u041b\u0418\u0415\u041d\u0422 (\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430) \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f<\/em><\/figcaption><\/div>\n<\/figure>\n<h2>Resolver<\/h2>\n<h3>\u0421 \u0447\u0435\u0433\u043e \u043d\u0430\u0447\u0430\u0442\u044c?<\/h3>\n<p>\u0427\u0442\u043e\u0431\u044b \u043d\u0430\u043c \u043d\u0430\u0447\u0430\u0442\u044c \u0441\u043e\u0432\u0435\u0440\u0448\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b, \u043d\u0430\u0434\u043e \u043f\u043e\u043d\u044f\u0442\u044c, \u043a\u0443\u0434\u0430 \u0438\u0445 \u0441\u043e\u0432\u0435\u0440\u0448\u0430\u0442\u044c. \u041e\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u043d\u0438\u0436\u0435 \u0441\u0435\u0442\u0435\u0432\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f \u043f\u043e \u043c\u043e\u0434\u0435\u043b\u0438 OSI \u043c\u044b \u043d\u0435 \u0431\u0443\u0434\u0435\u043c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u0442\u0432\u0435\u0442\u043e\u043c \u043d\u0430 \u0432\u043e\u043f\u0440\u043e\u0441 \u00ab\u043a\u0443\u0434\u0430?\u00bb \u0431\u0443\u0434\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a IP-\u0430\u0434\u0440\u0435\u0441\u043e\u0432. \u041c\u044b \u0437\u043d\u0430\u0435\u043c, \u0447\u0442\u043e \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u0435\u043a\u0438\u0439 \u0431\u044d\u043a\u0435\u043d\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043a\u0430\u043a-\u0442\u043e \u0441\u0435\u0431\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u0442 (\u043f\u0443\u0441\u0442\u044c \u0443 \u043d\u0435\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u043a\u0430\u043a\u043e\u0435-\u0442\u043e \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0435 \u0438\u043c\u044f, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043d\u0430\u043c \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e, \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u044d\u0442\u043e \u0438\u043c\u044f \u0435\u043c\u0443 \u0434\u0430\u043b\u0438 \u043b\u0438\u0431\u043e \u043c\u044b, \u043b\u0438\u0431\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0438\u0437 \u0441\u043e\u0441\u0435\u0434\u043d\u0435\u0433\u043e \u043e\u0442\u0434\u0435\u043b\u0430. \u041c\u043e\u0436\u043d\u043e \u0441\u0445\u043e\u0434\u0438\u0442\u044c \u043a \u043d\u0438\u043c \u0438 \u0441\u043f\u0440\u043e\u0441\u0438\u0442\u044c :)).<\/p>\n<p>\u0412\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u043c <a href=\"https:\/\/github.com\/grpc\/grpc-go\/blob\/master\/examples\/helloworld\/greeter_server\/main.go\"><u>gRPC hello-\u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/u><\/a>. \u041d\u0430 \u0434\u0430\u043d\u043d\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u043d\u0430\u043c \u043d\u0430\u0434\u043e \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u0442\u044c \u043d\u0435\u043a\u0438\u0439 \u043e\u0431\u044a\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u043b\u043e\u0433\u0438\u043a\u043e\u0439 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0430\u0434\u0440\u0435\u0441\u043e\u0432 \u0431\u044d\u043a\u0435\u043d\u0434\u0430, \u0442\u043e \u0435\u0441\u0442\u044c \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u0442\u044c \u0438\u043c\u044f \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u0430\u0434\u0440\u0435\u0441\u043e\u0432. \u0412 gRPC \u043e\u043d \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f Resolver. \u0415\u0433\u043e \u0437\u0430\u0434\u0430\u0447\u0435\u0439 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0432\u0435\u0440\u0448\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u0432 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0430\u0434\u0440\u0435\u0441\u043e\u0432, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0432 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438. \u041d\u0443 \u0430 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, DNS-\u0441\u043b\u0443\u0436\u0431\u0430. \u0415\u0451 IP-\u0430\u0434\u0440\u0435\u0441 \u0432\u0441\u0435\u0433\u0434\u0430 \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435.\u00a0<\/p>\n<h3>\u041d\u0430\u0433\u043b\u044f\u0434\u043d\u044b\u0439 \u043c\u043e\u043a DNS-\u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/h3>\n<p>\u0414\u043b\u044f \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u043e\u0441\u0442\u0438 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043c\u043e\u043a DNS-\u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u2014 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043d\u0430 HTTP GET-\u0437\u0430\u043f\u0440\u043e\u0441 \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a IP-\u0430\u0434\u0440\u0435\u0441\u043e\u0432 \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0431\u044d\u043a\u0435\u043d\u0434\u0430. \u041d\u0430 \u043f\u043e\u0440\u0442\u0443 8081 \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u043c HTTP-\u0441\u0435\u0440\u0432\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430 GET \u0437\u0430\u043f\u0440\u043e\u0441 <code>\u201c\/endpoints\u201d<\/code> \u0441 query-\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c target \u0432\u0435\u0440\u043d\u0451\u0442 \u0430\u0434\u0440\u0435\u0441 \u0441 \u043f\u043e\u0440\u0442\u043e\u043c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u044e\u0449\u0435\u0433\u043e \u043d\u0430\u0441 \u0441\u0435\u0440\u0432\u0438\u0441\u0430. \u0412\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043e\u043d\u043e \u043a\u0430\u043a-\u0442\u043e \u0442\u0430\u043a:\u00a0<\/p>\n<pre><code class=\"go\">func main() { http.HandleFunc(\"\/endpoints\", HandleEndpointRequest) err := http.ListenAndServe(\"localhost:8081\", nil) if err != nil { log.Fatal(err) } } func HandleEndpointRequest(w http.ResponseWriter, req *http.Request) { log.Println(\"new request with query:\", req.URL.RawQuery) target := req.URL.Query().Get(\"target\") switch target { case \"helloworld_server\": _, err := w.Write([]byte(\"127.0.0.1:8080\")) if err != nil { log.Println(err) } default: w.WriteHeader(http.StatusNotFound) } } <\/code><\/pre>\n<h3>\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f Resolver<\/h3>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a Resolver\u2019\u0443 \u0438 \u0443\u0436\u0435 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043a gRPC. \u0414\u043b\u044f \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f <a href=\"https:\/\/github.com\/grpc\/grpc-go\/blob\/1b05500d8019885575a37efa2e961e278d680ee9\/resolver\/resolver.go#L51\"><u>\u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0431\u0438\u043b\u0434\u0435\u0440 Resolver<\/u><\/a>\u2019\u0430 \u0432 gRPC.<\/p>\n<pre><code class=\"go\">rb := &amp;ResolverBuilder{} resolver.Register(rb)<\/code><\/pre>\n<p>\u0421\u0430\u043c \u0431\u0438\u043b\u0434\u0435\u0440 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 <a href=\"https:\/\/github.com\/grpc\/grpc-go\/blob\/1b05500d8019885575a37efa2e961e278d680ee9\/resolver\/resolver.go#L290\"><u>\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441<\/u><\/a> \u2014 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 Build \u0438 Scheme. Build \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u0438\u043d\u0441\u0442\u0430\u043d\u0441 Resolver, \u0430 Scheme \u2014 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u0443 \u0441 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c \u043d\u0430\u0448\u0435\u0433\u043e Resolver. \u041c\u044b \u043f\u043e\u0437\u0436\u0435 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a \u0441\u0435\u0440\u0432\u0438\u0441\u0443. ClientConn, \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0442\u043e\u0442 Resolver, \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f (<a href=\"https:\/\/github.com\/grpc\/grpc\/blob\/master\/doc\/naming.md\"><u>\u0440\u0435\u0437\u043e\u043b\u044e\u0446\u0438\u044f \u0438\u043c\u0451\u043d<\/u><\/a>).\u00a0<\/p>\n<pre><code class=\"go\">type Builder interface { Build(target Target, cc ClientConn, opts BuildOptions) (Resolver, error) Scheme() string } <\/code><\/pre>\n<p>\u041d\u0430\u0437\u043e\u0432\u0451\u043c \u043d\u0430\u0448 Resolver <strong>habr<\/strong>. <\/p>\n<pre><code class=\"go\">func (b *ResolverBuilder) Scheme() string { return \"habr\" } <\/code><\/pre>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043a\u043e\u0433\u0434\u0430 \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f grpc.Dial, \u044d\u0442\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043d\u0430 \u0432\u0445\u043e\u0434 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0430\u0434\u0440\u0435\u0441, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f:<\/p>\n<p> <code>grpc.Dial(\u201cozon.ru\u201d, opts...)<\/code><\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0432\u044b\u0431\u0440\u0430\u0442\u044c Resolver, \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434 \u0430\u0434\u0440\u0435\u0441\u043e\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e \u0441\u0445\u0435\u043c\u0443:<\/p>\n<p>\u00a0<code>grpc.Dial(\u201chabr:\/\/\/ozon.ru\u201d, opts...)<\/code><\/p>\n<p>\u041f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 Dial \u044d\u0442\u0430 \u0441\u0442\u0440\u043e\u043a\u0430 \u0440\u0430\u0441\u043f\u0430\u0440\u0441\u0438\u0442\u0441\u044f \u2014 \u0438 \u0438\u0437 \u043c\u0430\u043f\u044b \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0431\u0438\u043b\u0434\u0435\u0440\u043e\u0432 Resolver\u2019\u043e\u0432 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0431\u0440\u0430\u043d \u043d\u0443\u0436\u043d\u044b\u0439, \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d Resolver:<\/p>\n<figure class=\"full-width\"><\/figure>\n<h3>\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0441\u0430\u043c\u043e\u0433\u043e Resolver<\/h3>\n<p><a href=\"https:\/\/github.com\/grpc\/grpc-go\/blob\/c2398ced0efdd5151b4322922b20459b3d37a0d4\/resolver\/resolver.go#L308\"><u>\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 Resolver<\/u><\/a> \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u043e\u0441\u0442. \u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f Resolver (Close) \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f ResolveNow. \u0421 \u0444\u0443\u043a\u043d\u0446\u0438\u0435\u0439 Close \u0432\u0441\u0451 \u043f\u043e\u043d\u044f\u0442\u043d\u043e: \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0433\u043e\u0432\u043e\u0440\u0438\u0442 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043f\u0440\u0438 \u0435\u0451 \u0432\u044b\u0437\u043e\u0432\u0435 Resolver \u0434\u043e\u043b\u0436\u0435\u043d \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u0441\u0432\u043e\u044e \u0440\u0430\u0431\u043e\u0442\u0443. \u041d\u0443 \u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f ResolveNow \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432\u044b\u0437\u0432\u0430\u043d\u0430 ClientConn \u0434\u043b\u044f \u0444\u043e\u0440\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0440\u0435\u0437\u043e\u043b\u0432\u0438\u043d\u0433\u0430 \u0430\u0434\u0440\u0435\u0441\u043e\u0432 \u0432 \u0440\u044f\u0434\u0435 \u044d\u043a\u0441\u0442\u0440\u0435\u043d\u043d\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0438\u0436\u0435 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u043b\u0438 \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f \u043d\u0438 \u043a \u043e\u0434\u043d\u043e\u043c\u0443 \u0438\u0437 \u0440\u0430\u043d\u0435\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u0430\u0434\u0440\u0435\u0441\u043e\u0432; \u043f\u043b\u044e\u0441 \u043e\u043d\u0430 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432\u044b\u0437\u0432\u0430\u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437 \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u043d\u043e). \u041f\u0440\u043e\u0441\u0442\u043e\u0439 Resolver \u043c\u043e\u0436\u0435\u0442 \u044d\u0442\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c. \u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u044b Resolver \u0434\u043e\u043b\u0436\u043d\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u0435\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432 \u0444\u043e\u043d\u0435 (\u0442\u043e \u0435\u0441\u0442\u044c \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0433\u043e\u0440\u0443\u0442\u0438\u043d\u0435), \u043d\u0430\u043f\u043e\u043b\u043d\u044f\u044f ClientConn \u0430\u0434\u0440\u0435\u0441\u0430\u043c\u0438.<\/p>\n<pre><code class=\"go\">type Resolver interface {    ResolveNow(ResolveNowOptions)    Close() } <\/code><\/pre>\n<p>\u0412 \u0444\u0443\u043d\u043a\u0446\u0438\u044e Build \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e \u0442\u0430\u0440\u0433\u0435\u0442\u0435 (\u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u0430, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f, \u0432 \u0432\u0438\u0434\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b URL \u0438\u0437 std \u043f\u0430\u043a\u0435\u0442\u0430 <code>net\/url<\/code>), \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 ClientConn (\u043e\u0431\u0451\u0440\u043d\u0443\u0442\u044b\u0439 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u043f\u0440\u043e\u043a\u0441\u0438\u0440\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u0434\u043b\u044f Resolver) \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0432 \u043d\u0435\u0433\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 BuildOptions.\u00a0<\/p>\n<pre><code class=\"go\">func (b *ResolverBuilder) Build(target resolver.Target, cc resolver.ClientConn, _ resolver.BuildOptions) (resolver.Resolver, error) { ctx, cancel := context.WithCancel(context.Background()) r := &amp;Resolv<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-362376","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/362376","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=362376"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/362376\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=362376"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=362376"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=362376"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}