{"id":346318,"date":"2023-03-06T09:02:02","date_gmt":"2023-03-06T09:02:02","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=346318"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=346318","title":{"rendered":"<span>\u0428\u0430\u0431\u043b\u043e\u043d backend \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043d\u0430 Golang \u2014 \u0447\u0430\u0441\u0442\u044c 5 \u2014 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f Worker pool<\/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-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><a href=\"https:\/\/habr.com\/ru\/post\/720286\/\"># \u0428\u0430\u0431\u043b\u043e\u043d backend \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043d\u0430 Golang \u2014 \u0447\u0430\u0441\u0442\u044c 5 \u2014 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f Worker pool<\/a><\/p>\n<p>  <\/p>\n<p><a href=\"https:\/\/habr.com\/ru\/post\/720286\/\">\u041f\u044f\u0442\u0430\u044f \u0447\u0430\u0441\u0442\u044c<\/a> \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u0430 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 Worker pool \u0438 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044f\u043c \u0435\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u044b \u0432 \u0441\u043e\u0441\u0442\u0430\u0432\u0435 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0430, \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u043e\u0433\u043e \u0432 Kubernetes.<\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 Worker pool \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u0434\u0432\u0443\u043c\u044f \u0442\u0438\u043f\u0430\u043c\u0438 \u0437\u0430\u0434\u0430\u0447<\/p>\n<p>  <\/p>\n<ul>\n<li>&#171;\u041a\u043e\u0440\u043e\u0442\u043a\u0438\u0435&#187; \u2014 \u043d\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0435\u0434\u0435\u043b\u044c\u043d\u044b\u0439 timeout \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0438 \u0438\u0445 \u043d\u0435\u043b\u044c\u0437\u044f \u043f\u0440\u0435\u0440\u0432\u0430\u0442\u044c<\/li>\n<li>&#171;\u0414\u043b\u0438\u043d\u043d\u044b\u0435&#187; \u2014 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0435\u0434\u0435\u043b\u044c\u043d\u044b\u0439 timeout \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0438 \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u0440\u0432\u0430\u0442\u044c<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u041d\u0430\u043a\u043b\u0430\u0434\u043d\u044b\u0435 \u0440\u0430\u0441\u0445\u043e\u0434\u044b Worker pool \u043d\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c \u043e\u0447\u0435\u0440\u0435\u0434\u0438, \u0437\u0430\u043f\u0443\u0441\u043a \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 task, \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f task:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0414\u043b\u044f &#171;\u043a\u043e\u0440\u043e\u0442\u043a\u0438\u0445&#187; task \u2014 \u043e\u0442 300 ns\/op, 0 B\/op, 0 allocs\/op<\/li>\n<li>\u0414\u043b\u044f &#171;\u0434\u043b\u0438\u043d\u043d\u044b\u0445&#187; task \u2014 \u043e\u0442 1400 ns\/op, 16 B\/op, 1 allocs\/op<\/li>\n<\/ul>\n<p>  <\/p>\n<p><em>\u0414\u043b\u044f task, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0431\u044b\u0441\u0442\u0440\u0435\u0435 200 ns\/op \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 Worker pool \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e<\/em><\/p>\n<p>  <\/p>\n<p>\u0421\u043e\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043c\u0435\u0442\u0440\u0438\u043a\u0438 <a href=\"https:\/\/prometheus.io\/\" rel=\"nofollow noopener noreferrer\">prometheus<\/a>:<\/p>\n<p>  <\/p>\n<ul>\n<li>wp_worker_process_count_vec \u2014 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e worker \u0432 \u0440\u0430\u0431\u043e\u0442\u0435<\/li>\n<li>wp_task_process_duration_ms_by_name \u2014 \u0433\u0438\u0441\u0442\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f task \u0432 ms \u0441 \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u043e\u0439 \u043f\u043e task.name<\/li>\n<li>wp_task_queue_buffer_len_vec \u2014 \u0442\u0435\u043a\u0443\u0449\u0430\u044f \u0434\u043b\u0438\u043d\u0430 \u043a\u0430\u043d\u0430\u043b\u0430-\u043e\u0447\u0435\u0440\u0435\u0434\u0438 task \u2014 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u043a\u0430\u043d\u0430\u043b\u0430<\/li>\n<li>wp_add_task_wait_count_vec \u2014 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u0434\u0430\u0447, \u043e\u0436\u0438\u0434\u0430\u044e\u0449\u0438\u0445 \u043f\u043e\u043f\u0430\u0434\u0430\u043d\u0438\u044f \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 <a href=\"https:\/\/github.com\/romapres2010\/goapp\" rel=\"nofollow noopener noreferrer\">\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/a>.<\/p>\n<p>  <\/p>\n<p>\u0428\u0430\u0431\u043b\u043e\u043d goapp \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0433\u043e\u0442\u043e\u0432 \u043a \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044e \u0432 Docker, Docker Compose, Kubernetes (kustomize), Kubernetes (helm).<\/p>\n<p>  <\/p>\n<p>\u0421\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u0447\u0430\u0441\u0442\u0438:<\/p>\n<p>  <\/p>\n<ul>\n<li><a href=\"https:\/\/habr.com\/ru\/post\/492062\/\">\u041f\u0435\u0440\u0432\u0430\u044f \u0447\u0430\u0441\u0442\u044c<\/a> \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u0431\u044b\u043b\u0430 \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u0430 HTTP \u0441\u0435\u0440\u0432\u0435\u0440\u0443.<\/li>\n<li><a href=\"https:\/\/habr.com\/ru\/post\/500554\/\">\u0412\u0442\u043e\u0440\u0430\u044f \u0447\u0430\u0441\u0442\u044c<\/a> \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u0431\u044b\u043b\u0430 \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u0430 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e REST API.<\/li>\n<li><a href=\"https:\/\/habr.com\/ru\/post\/716634\/\">\u0422\u0440\u0435\u0442\u044c\u044f \u0447\u0430\u0441\u0442\u044c<\/a> \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u0430 \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044e \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u0432 Docker, Docker Compose, Kubernetes (kustomize).<\/li>\n<li>\u0427\u0435\u0442\u0432\u0435\u0440\u0442\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u0430 \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044e \u0432 Kubernetes \u0441 Helm chart \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 Horizontal Autoscaler.<\/li>\n<\/ul>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<h2 id=\"soderzhanie\">\u0421\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435<\/h2>\n<p>  <\/p>\n<ol>\n<li>\u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0440\u0430\u0431\u043e\u0442\u044b worker pool \u0432 \u0441\u043e\u0441\u0442\u0430\u0432\u0435 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0432 Kubernetes<\/li>\n<li>\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 Worker pool<\/li>\n<li>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 Task<\/li>\n<li>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 Worker<\/li>\n<li>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 Pool<\/li>\n<li>\u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f Worker pool<\/li>\n<li>\u041d\u0430\u0433\u0440\u0443\u0437\u043e\u0447\u043d\u043e\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 Worker pool<\/li>\n<li>\u041f\u0440\u043e\u0444\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 Worker pool<\/li>\n<\/ol>\n<p>  <\/p>\n<h2 id=\"1-osobennosti-raboty-worker-pool-v-sostave-mikroservisa-v-kubernetes\">1. \u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0440\u0430\u0431\u043e\u0442\u044b worker pool \u0432 \u0441\u043e\u0441\u0442\u0430\u0432\u0435 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0432 Kubernetes<\/h2>\n<p>  <\/p>\n<p>\u041f\u0440\u0438 \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432 Kubernetes \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0438\u0441\u044c \u0441 \u0442\u0430\u043a\u0438\u043c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/716634\/\">\u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044f\u043c\u0438<\/a>.<\/p>\n<p>  <\/p>\n<ul>\n<li>\u043f\u0440\u0438 \u0440\u043e\u0441\u0442\u0435 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438 Horizontal Autoscaler (HA) \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0435 Pod c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u0438 \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0430 \u043d\u0435\u0433\u043e \u0447\u0430\u0441\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.<\/li>\n<li>\u043f\u0440\u0438 \u0441\u043d\u0438\u0436\u0435\u043d\u0438\u0438 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438 (\u043f\u043e \u043f\u0430\u043c\u044f\u0442\u0438 \u0438\u043b\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430), Horizontal Autoscaler \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 Pod c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0412 \u043d\u0430\u0448\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 Worker pool, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0441\u044f \u0434\u043b\u044f \u0434\u0432\u0443\u0445 \u0442\u0438\u043f\u043e\u0432 \u0437\u0430\u0434\u0430\u0447:<\/p>\n<p>  <\/p>\n<ul>\n<li>&#171;\u041a\u043e\u0440\u043e\u0442\u043a\u0438\u0435&#187; \u2014 100-500 mc \u2014 \u0432\u044b\u0441\u043e\u043a\u043e\u043d\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0435 \u0440\u0430\u0441\u0447\u0435\u0442\u044b<\/li>\n<li>&#171;\u0414\u043b\u0438\u043d\u043d\u044b\u0435&#187; \u2014 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u043b\u0438\u0441\u044c 1-30 s, \u043e\u0431\u044b\u0447\u043d\u043e \u2014 \u044d\u0442\u043e \u0441\u043b\u0430\u0431\u043e\u043d\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u0432\u043d\u0435\u0448\u043d\u0438\u043c\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c\u0438. \u0421\u0435\u0440\u0432\u0438\u0441\u044b-\u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0438 \u0442\u0430\u043a\u0438\u0445 &#171;\u0434\u043b\u0438\u043d\u043d\u044b\u0445&#187; task \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u043c\u0438.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0412 \u043f\u0435\u0440\u0438\u043e\u0434\u044b \u0432\u044b\u0441\u043e\u043a\u043e\u0439 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438, Horizontal Autoscaler \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u043b 2-5 \u043d\u043e\u0432\u044b\u0445 Pod, \u0430 \u0447\u0435\u0440\u0435\u0437 30-60 \u043c\u0438\u043d\u0443\u0442 \u0443\u0434\u0430\u043b\u044f\u043b \u043d\u0435\u043d\u0443\u0436\u043d\u044b\u0435. Pod \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u043b\u0438 \u043e\u0431\u0440\u044b\u0432\u044b \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u0438 \u043e\u0442\u043a\u0430\u0437 \u0432 \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u0438 \u0434\u043b\u044f \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438.<\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0442\u0430\u043a\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u2014 \u044d\u0442\u043e \u0440\u0430\u0437\u043d\u0435\u0441\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 \u0437\u0430\u0434\u0430\u0447 \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0435 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u044b. <\/p>\n<p>  <\/p>\n<p>\u041d\u043e \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u044d\u0442\u0438\u043c, \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0441\u0435\u0440\u044c\u0435\u0437\u043d\u043e \u043f\u0435\u0440\u0435\u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c Worker pool \u0434\u043b\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0439 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0438 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0430\u043c\u044f\u0442\u0438 \u0438 cpu.<\/p>\n<p>  <\/p>\n<p>\u0423\u0441\u043b\u043e\u0432\u043d\u043e, \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u044b \u043a \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435 Worker pool:<\/p>\n<p>  <\/p>\n<ul>\n<li>&#171;Light&#187; \u2014 \u0432\u0441\u0435 \u043d\u0430\u0447\u0430\u0442\u044b\u0435 \u043a \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0438 \u0432\u0441\u0435 \u0432\u0437\u044f\u0442\u044b\u0435 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0437\u0430\u0434\u0430\u0447\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u044b, \u043d\u043e\u0432\u044b\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u043d\u0435 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0442\u0441\u044f. \u041f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0438 \u043f\u043e \u043d\u043e\u0432\u044b\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c \u043f\u043e\u043b\u0443\u0447\u0430\u044e\u0442 \u043e\u0442\u043a\u0430\u0437 \u0432 \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u0438.<\/li>\n<li>&#171;Soft&#187; \u2014 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0447\u0430\u0442\u044b\u0435 \u043a \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u044b, \u043d\u043e\u0432\u044b\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u043d\u0435 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0442\u0441\u044f, \u043e\u0441\u0442\u0430\u0432\u0448\u0438\u0435\u0441\u044f \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0437\u0430\u0434\u0430\u0447\u0438 \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439. \u041f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0438 \u043f\u043e \u043d\u043e\u0432\u044b\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c \u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c \u043d\u0435 \u043d\u0430\u0447\u0430\u0442\u044b\u043c \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u043b\u0443\u0447\u0430\u044e\u0442 \u043e\u0442\u043a\u0430\u0437 \u0432 \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u0438.<\/li>\n<li>&#171;Soft + timeout&#187; \u2014 \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u0442\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 &#171;Soft&#187;, \u0435\u0441\u043b\u0438 \u043d\u0435 \u0443\u043b\u043e\u0436\u0438\u043b\u0438\u0441\u044c \u0432 timeout, \u0442\u043e \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 &#171;Hard&#187;.<\/li>\n<li>&#171;Hard&#187; \u2014 \u044d\u043a\u0441\u0442\u0440\u0435\u043d\u043d\u043e \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0432\u0441\u0435\u0445 \u0437\u0430\u0434\u0430\u0447, \u043a\u0430\u043a \u043d\u0430\u0447\u0430\u0442\u044b\u0445, \u0442\u0430\u043a \u0438 \u043d\u0430\u0445\u043e\u0434\u044f\u0449\u0438\u0445\u0441\u044f \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u0438. \u041f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u044e\u0442 \u043e\u0442\u043a\u0430\u0437 \u0432 \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u0438.<\/li>\n<li>&#171;Crash&#187; \u2014 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0443\u0434\u0430\u043b\u044f\u0435\u0442\u0441\u044f KILL -9. \u0421\u0435\u0442\u0435\u0432\u044b\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u0440\u044b\u0432\u0430\u044e\u0442\u0441\u044f. \u041f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0438 \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u044e\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043a\u0440\u043e\u043c\u0435 \u0440\u0430\u0437\u0440\u044b\u0432\u0430 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 stateless, \u0442\u043e, \u0436\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0434\u0445\u043e\u0434 &#171;Crash&#187; \u0438\u043b\u0438 &#171;Hard&#187;. \u041f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0438 \u0432\u0441\u0435\u0433\u0434\u0430 \u0441\u043c\u043e\u0433\u0443\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0438 \u0438\u0445 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0434\u0440\u0443\u0433\u043e\u0439 Pod.<\/p>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 stateful, \u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u043d\u0430\u0447\u0430\u0442\u044b\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 &#171;soft&#187; \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u043e\u043c\u0435\u0442\u043a\u0443 \u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043a\u043e\u043c\u043f\u0435\u043d\u0441\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0433\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f. \u041a\u043e\u043c\u043f\u0435\u043d\u0441\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0441\u0430\u043c\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0435, \u043b\u0438\u0431\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u043b\u0443\u0436\u0435\u0431\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441.<\/p>\n<p>  <\/p>\n<p>\u0428\u0430\u0431\u043b\u043e\u043d Worker pool \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 &#171;Light&#187;, &#171;Soft&#187;, &#171;Soft + timeout&#187;, &#171;Hard&#187;. \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d \u0440\u0435\u0436\u0438\u043c &#171;Soft + timeout&#187;.<\/p>\n<p>  <\/p>\n<h2 id=\"2-arhitektura-worker-pool\">2. \u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 Worker pool<\/h2>\n<p>  <\/p>\n<p>\u0412 \u043e\u0441\u043d\u043e\u0432\u0435 Worker pool \u043b\u0435\u0436\u0438\u0442 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u044f \u0438\u0437 \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/hackernoon.com\/concurrency-in-golang-and-workerpool-part-2-l3w31q7\" rel=\"nofollow noopener noreferrer\">Ahad Hasan<\/a>. <\/p>\n<p>  <\/p>\n<ul>\n<li>task \u2014 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u0445\u043e\u0434\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0437\u0430\u0434\u0430\u0447\u0438, \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a, \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f, \u043a\u0430\u043d\u0430\u043b\u044b \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0438 \u0442\u0430\u0439\u043c\u0435\u0440 \u0434\u043b\u044f \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044f timeout.<\/li>\n<li>worker \u2014 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u0443\u0435\u0442 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0437\u0430\u0434\u0430\u0447 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 task \u0432 \u0441\u0432\u043e\u0435\u0439 goroutine <\/li>\n<li>pool \u2014 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0437\u0430\u0434\u0430\u0447, \u0441\u043e\u0437\u0434\u0430\u0435\u0442 worker \u0438 \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u0442 \u0438\u0445 \u0441\u0442\u0430\u0442\u0443\u0441, \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u043c \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 <a href=\"https:\/\/github.com\/romapres2010\/goapp\/blob\/master\/pkg\/common\/workerpool\/task.go\" rel=\"nofollow noopener noreferrer\">Task<\/a>:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e-\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0435\u0439 \u0432\u0445\u043e\u0434\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435<\/li>\n<li>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438-\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430<\/li>\n<li>\u0418\u043d\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c &#171;\u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u043c\u0438\u0440&#187; \u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438-\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430<\/li>\n<li>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438-\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u043f\u043e timeout, \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u0440\u0435\u0440\u0432\u0430\u0442\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435<\/li>\n<li>\u041f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0438\u0442\u044c panic \u043e\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u0438-\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0443<\/li>\n<li>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u043d\u0430 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b Worker pool<\/li>\n<li>\u0418\u043d\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e-\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0441\u0440\u043e\u0447\u043d\u043e\u0439 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 <a href=\"https:\/\/github.com\/romapres2010\/goapp\/blob\/master\/pkg\/common\/workerpool\/worker.go\" rel=\"nofollow noopener noreferrer\">Worker<\/a>:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u041e\u0436\u0438\u0434\u0430\u0442\u044c \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u0432 \u043a\u0430\u043d\u0430\u043b\u0435-\u043e\u0447\u0435\u0440\u0435\u0434\u0438 task \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0435\u0435 \u043d\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435<\/li>\n<li>\u041e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u043f\u0440\u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u0438 \u043a\u0430\u043d\u0430\u043b\u0430-\u043e\u0447\u0435\u0440\u0435\u0434\u0438 task<\/li>\n<li>\u041f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0438\u0442\u044c panic, \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0443 \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u043a\u0430\u043d\u0430\u043b \u043e\u0448\u0438\u0431\u043e\u043a \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0432 pool<\/li>\n<li>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u043d\u0430 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b Worker pool<\/li>\n<li>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u0435 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b Worker pool<\/li>\n<li>\u041f\u0440\u0438 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 worker, \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u0443\u044e task<\/li>\n<li>Worker \u043c\u043e\u0436\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432 \u0441\u043e\u0441\u0442\u0430\u0432\u0435 \u043e\u0431\u0449\u0435\u0433\u043e sync.WaitGroup, \u0442\u0430\u043a \u0438 \u0438\u0437\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e \u0432 \u0444\u043e\u043d\u0435<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 <a href=\"https:\/\/github.com\/romapres2010\/goapp\/blob\/master\/pkg\/common\/workerpool\/pool.go\" rel=\"nofollow noopener noreferrer\">Pool<\/a>:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0432 \u043a\u0430\u043d\u0430\u043b-\u043e\u0447\u0435\u0440\u0435\u0434\u044c<\/li>\n<li>\u0423\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u043c worker<\/li>\n<li>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 worker \u0447\u0435\u0440\u0435\u0437 \u043a\u0430\u043d\u0430\u043b \u043e\u0448\u0438\u0431\u043e\u043a, \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0441\u0431\u043e\u0439\u043d\u044b\u0435 worker<\/li>\n<li>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u043d\u0430 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b &#171;\u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u043c\u0438\u0440\u0430&#187;<\/li>\n<li>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u0435 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b &#171;\u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u043c\u0438\u0440\u0430&#187;<\/li>\n<li>\u041e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 &#171;Light&#187;, &#171;Soft&#187;, &#171;Soft + timeout&#187;, &#171;Hard&#187;<\/li>\n<\/ul>\n<p>  <\/p>\n<h2 id=\"3-struktura-task\">3. \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 Task<\/h2>\n<p>  <\/p>\n<pre><code class=\"go\">type Task struct {     parentCtx context.Context    \/\/ \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442, \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 task - \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438-\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0435     ctx       context.Context    \/\/ \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442, \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e task - \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438-\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0435 \u043a\u0430\u043a \u0441\u0438\u0433\u043d\u0430\u043b \u0434\u043b\u044f \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438     cancel    context.CancelFunc \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u0434\u043b\u044f task      externalId  uint64             \/\/ \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 task - \u0434\u043b\u044f \u0446\u0435\u043b\u0435\u0439 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f     doneCh      chan&lt;- interface{} \/\/ \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u043a\u0430\u043d\u0430\u043b \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u0432\u043e \"\u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u043c\u0438\u0440\" \u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438-\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0435     stopCh      chan interface{}   \/\/ \u043a\u0430\u043d\u0430\u043b \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043d\u0430 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 task \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \"\u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u043c\u0438\u0440\u0430\"     localDoneCh chan interface{}   \/\/ \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u0430\u043d\u0430\u043b task - \u0441\u0438\u0433\u043d\u0430\u043b \u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438-\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0435 \u0434\u043b\u044f \"\u0434\u043b\u0438\u043d\u043d\u044b\u0445\" task      id      uint64        \/\/ \u043d\u043e\u043c\u0435\u0440 task - \u0434\u043b\u044f \u0446\u0435\u043b\u0435\u0439 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f     state   TaskState     \/\/ \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u043e\u0433\u043e \u0446\u0438\u043a\u043b\u0430 task     name    string        \/\/ \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 task \u0434\u043b\u044f \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\u0430     timeout time.Duration \/\/ \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0434\u043b\u044f \"\u0434\u043b\u0438\u043d\u043d\u044b\u0445\" task     timer   *time.Timer   \/\/ \u0442\u0430\u0439\u043c\u0435\u0440 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043f\u043e timeout \u0434\u043b\u044f \"\u0434\u043b\u0438\u043d\u043d\u044b\u0445\" task      requests  []interface{} \/\/ \u0432\u0445\u043e\u0434\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 - \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e-\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a     responses []interface{} \/\/ \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438-\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0435     err       error         \/\/ \u043e\u0448\u0438\u0431\u043a\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438-\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0435      duration time.Duration \/\/ \u0440\u0435\u0430\u043b\u044c\u043d\u0430\u044f \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f task      f func(context.Context, context.Context, ...interface{}) (error, []interface{}) \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f-\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a      mx sync.RWMutex }<\/code><\/pre>\n<p>  <\/p>\n<p>Task \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u0443\u0441\u043d\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u044c\u044e.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">type TaskState int  const (     TASK_STATE_NEW                    TaskState = iota \/\/ task \u0441\u043e\u0437\u0434\u0430\u043d     TASK_STATE_IN_PROCESS                              \/\/ task \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f     TASK_STATE_DONE_SUCCESS                            \/\/ task \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043b\u0441\u044f     TASK_STATE_RECOVER_ERR                             \/\/ task \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0441\u044f \u0438\u0437-\u0437\u0430 \u043f\u0430\u043d\u0438\u043a\u0438     TASK_STATE_TERMINATED_STOP_SIGNAL                  \/\/ task \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u043f\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u043e\u0431 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435     TASK_STATE_TERMINATED_CTX_CLOSED                   \/\/ task \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u043f\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0435 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430     TASK_STATE_TERMINATED_TIMEOUT                      \/\/ task \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u043f\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0435 \u043f\u0440\u0435\u0432\u044b\u0448\u0435\u043d\u0438\u044f timeout )<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"zapusk-task\">\u0417\u0430\u043f\u0443\u0441\u043a task<\/h3>\n<p>  <\/p>\n<p>Task \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0438\u0437 goroutine worker<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0417\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u043c task \u043d\u0430 \u0432\u0440\u0435\u043c\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f task<\/li>\n<li>\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u043c, \u0447\u0442\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043c\u043e\u0436\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e task \u0441 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u043c TASK_STATE_NEW<\/li>\n<li>C\u0442\u0430\u0440\u0442\u0443\u0435\u043c defer \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043f\u0430\u043d\u0438\u043a\u0438 task \u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f &#171;\u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u043c\u0438\u0440\u0430&#187; \u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0438 \u0440\u0430\u0431\u043e\u0442\u044b task \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u0430\u043d\u0430\u043b doneCh<\/li>\n<li>&#171;\u041a\u043e\u0440\u043e\u0442\u043a\u0438\u0435&#187; task (timeout &lt; 0) \u043d\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u0443\u0435\u043c \u043f\u043e timeout. \u0418\u0445 \u043d\u0435\u043b\u044c\u0437\u044f \u043f\u0440\u0435\u0440\u0432\u0430\u0442\u044c. \u0424\u0443\u043d\u043a\u0446\u0438\u044f-\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0432 goroutine worker<\/li>\n<li>&#171;\u0414\u043b\u0438\u043d\u043d\u044b\u0435&#187; task (timeout >= 0) \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0432 \u0444\u043e\u043d\u0435 \u0438 \u043e\u0436\u0438\u0434\u0430\u0435\u043c \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u0430\u043d\u0430\u043b localDoneCh. \u0424\u0443\u043d\u043a\u0446\u0438\u044f-\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0438 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 task. \u041b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 task \u043d\u0443\u0436\u043d\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0435 \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438. \u041e\u0436\u0438\u0434\u0430\u0435\u043c \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430, \u043d\u0430\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u044f timeout \u0438\u043b\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043d\u0430 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u0435 task<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f task \u0447\u0435\u0440\u0435\u0437 sunc.Pool \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 time.Timer \u0434\u043b\u044f \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044f timeout \u043e\u043f\u0438\u0441\u0430\u043d\u044b \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 &#171;\u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430\u043a\u043b\u0430\u0434\u043d\u044b\u0445 \u0440\u0430\u0441\u0445\u043e\u0434\u043e\u0432 Worker pool&#187;<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">func (ts *Task) process(workerID uint, workerTimeout time.Duration) {     if ts == nil || ts.f == nil { return }      \/\/ \u0417\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u043c task \u043d\u0430 \u0432\u0440\u0435\u043c\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f     if ts.mx.TryLock() { \/\/ \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 TryLock \u043d\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f, \u043d\u043e \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u043d\u043e         defer ts.mx.Unlock()     } else {         ts.err = _err.NewTyped(_err.ERR_WORKER_POOL_TASK_ALREADY_LOCKED, ts.externalId, ts.name, ts.state).PrintfError()         return     }      \/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u0438\u043c, \u0447\u0442\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043c\u043e\u0436\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u043e\u0432\u044b\u0439 task     if ts.state == TASK_STATE_NEW {         ts.setStateUnsafe(TASK_STATE_IN_PROCESS)     } else {         ts.err = _err.NewTyped(_err.ERR_WORKER_POOL_TASK_INCORRECT_STATE, ts.externalId, ts.name, ts.state, \"NEW\").PrintfError()         return     }      \/\/ \u041e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u043f\u0430\u043d\u0438\u043a\u0443 task \u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \"\u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u043c\u0438\u0440\" \u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0438 \u0440\u0430\u0431\u043e\u0442\u044b task \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u0430\u043d\u0430\u043b     defer func() {         if r := recover(); r != nil {             ts.err = _recover.GetRecoverError(r, ts.externalId, ts.name)             ts.setStateUnsafe(TASK_STATE_RECOVER_ERR)         }          \/\/ \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u0430 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f, \u043a\u043e\u0433\u0434\u0430 \u043a\u0430\u043d\u0430\u043b \u0437\u0430\u043a\u0440\u044b\u0442, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u043b\u0438 \"\u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u043c\u0438\u0440\" \u043d\u0430\u0441 \u043d\u0435 \u0434\u043e\u0436\u0434\u0430\u043b\u0441\u044f \u043f\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0435 \u0441\u0432\u043e\u0435\u0433\u043e \u0442\u0430\u0439\u043c\u0430\u0443\u0442\u0430, \u0442\u043e\u0433\u0434\u0430 \u043a\u0430\u043d\u0430\u043b \u0443\u0436\u0435 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043a\u0440\u044b\u0442           if ts.doneCh != nil { ts.doneCh &lt;- struct{}{} }     }()      if ts.timeout &lt; 0 {         \/\/ \"\u041a\u043e\u0440\u043e\u0442\u043a\u0438\u0435\" task (timeout &lt; 0) \u043d\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u0443\u0435\u043c \u043f\u043e timeout. \u0418\u0445 \u043d\u0435\u043b\u044c\u0437\u044f \u043f\u0440\u0435\u0440\u0432\u0430\u0442\u044c. \u0424\u0443\u043d\u043a\u0446\u0438\u044f-\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0432 goroutine worker         ts.err, ts.responses = ts.f(ts.parentCtx, nil, ts.requests...)         ts.setStateUnsafe(TASK_STATE_DONE_SUCCESS)         return     } else {         \/\/ \"\u0414\u043b\u0438\u043d\u043d\u044b\u0435\" task \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0432 \u0444\u043e\u043d\u0435 \u0438 \u043e\u0436\u0438\u0434\u0430\u0435\u043c \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u0430\u043d\u0430\u043b. \u041a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u0443\u0435\u043c timeout         var tic = time.Now() \/\/ \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u043c\u0435\u0442\u043a\u0430 \u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 task          go func() {             defer func() {                 if r := recover(); r != nil {                     ts.err = _recover.GetRecoverError(r, ts.externalId, ts.name)                 }                  \/\/ \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u0438\u0433\u043d\u0430\u043b \u0438 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u043a\u0430\u043d\u0430\u043b, task \u043d\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u0443\u0435\u0442, \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0438\u043b\u0438 \u043d\u0435\u0442 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043b\u0441\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a                 if ts.localDoneCh != nil { ts.localDoneCh &lt;- struct{}{} }             }()              \/\/ \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0438 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 task.             \/\/ \u041b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 task \u043d\u0443\u0436\u043d\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0435 \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438             ts.err, ts.responses = ts.f(ts.parentCtx, ts.ctx, ts.requests...)         }()          \/\/ \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c, \u043d\u0443\u0436\u043d\u043e \u043b\u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c timeout, ts.timeout \u0438\u043c\u0435\u0435\u0442 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442 \u043d\u0430\u0434 workerTimeout         var timeout time.Duration \/\/ \u043f\u0440\u0435\u0434\u0435\u043b\u044c\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0431\u043e\u0442\u044b task         if ts.timeout > 0 {             timeout = ts.timeout         } else if workerTimeout > 0 {             timeout = workerTimeout         }          \/\/ \u0415\u0441\u043b\u0438 timeout == 0, \u0442\u043e \u043d\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c timeout         if timeout > 0 {             \/\/ Task \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0442\u0430\u0439\u043c\u0435\u0440 \u0432\u0441\u0435\u0433\u0434\u0430 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u043c, \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0442\u044c \u043a\u0430\u043d\u0430\u043b \u0442\u0430\u0439\u043c\u0435\u0440\u0430 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d \u043d\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b             ts.timer.Reset(timeout) \/\/ \u041f\u0435\u0440\u0435\u0441\u0442\u0430\u0432\u0438\u043c \u0442\u0430\u0439\u043c\u0435\u0440 \u043d\u0430 \u043d\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435         }          \/\/ \u041e\u0436\u0438\u0434\u0430\u0435\u043c \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430, \u043d\u0430\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u044f timeout \u0438\u043b\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043d\u0430 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u0435 task         select {         case &lt;-ts.localDoneCh:             if !ts.timer.Stop() { \/\/ \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c \u0442\u0430\u0439\u043c\u0435\u0440                  &lt;-ts.timer.C \/\/ \u0412\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u044c, \u0447\u0442\u043e \u043e\u043d \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b \u0432 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043a\u0435 \u043c\u0435\u0436\u0434\u0443 select \u0438\u0437 localDoneCh \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c ts.timer.Stop() \u043a\u0440\u0430\u0439\u043d\u0435 \u043c\u0430\u043b\u0430             }              ts.duration = time.Now().Sub(tic)             ts.setStateUnsafe(TASK_STATE_DONE_SUCCESS)             return         case _, ok := &lt;-ts.stopCh:             if ok {                 \/\/ \u043a\u0430\u043d\u0430\u043b \u0431\u044b\u043b \u043e\u0442\u043a\u0440\u044b\u0442 \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u043d\u0430 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443                 ts.err = _err.NewTyped(_err.ERR_WORKER_POOL_STOP_SIGNAL, ts.externalId, fmt.Sprintf(\"[WorkerId='%v', TaskExternalId='%v', TaskName='%v', WorkerTimeout='%v']\", workerID, ts.externalId, ts.name, workerTimeout))                 ts.setStateUnsafe(TASK_STATE_TERMINATED_STOP_SIGNAL)             } else {                 _log.Error(\"Task - INTERRUPT - stop chanel closed: WorkerId, TaskExternalId, TaskName, WorkerTimeout\", workerID, ts.externalId, ts.name, workerTimeout)             }             \/\/ \u0417\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 task - \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u044d\u0442\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043a\u043e\u043c\u043f\u0435\u043d\u0441\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u0432\u043e\u0437\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f             if ts.cancel != nil { ts.cancel() }             close(ts.localDoneCh)             return         case &lt;-ts.timer.C:             ts.err = _err.NewTyped(_err.ERR_WORKER_POOL_TIMEOUT_ERROR, ts.externalId, ts.id, timeout).PrintfError()             ts.setStateUnsafe(TASK_STATE_TERMINATED_TIMEOUT)             \/\/ \u0417\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 task - \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u044d\u0442\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043a\u043e\u043c\u043f\u0435\u043d\u0441\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u0432\u043e\u0437\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f             if ts.cancel != nil { ts.cancel() }             close(ts.localDoneCh)             return         }     } }<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"ostanovka-task\">\u041e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 task<\/h3>\n<p>  <\/p>\n<p>\u041f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c &#171;\u0434\u043b\u0438\u043d\u043d\u044b\u0435&#187; task \u043c\u043e\u0436\u043d\u043e \u0447\u0435\u0440\u0435\u0437 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u0430\u043d\u0430\u043b. \u0414\u043b\u044f &#171;\u043a\u043e\u0440\u043e\u0442\u043a\u0438\u0445&#187; task \u044d\u0442\u043e\u0442 \u043a\u0430\u043d\u0430\u043b \u043d\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u2014 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0438\u0445 \u043f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0435\u043b\u044c\u0437\u044f. <\/p>\n<p>  <\/p>\n<pre><code class=\"go\">func (ts *Task) Stop() {     \/\/ \u041e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u043c\u043e\u0436\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u0441\u0442\u0430\u0442\u0443\u0441\u0430\u0445     if ts.state == TASK_STATE_NEW || ts.state == TASK_STATE_IN_PROCESS || ts.state == TASK_STATE_DONE_SUCCESS {         \/\/ \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u0438\u0433\u043d\u0430\u043b \u0438 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u043a\u0430\u043d\u0430\u043b         if ts.stopCh != nil {             ts.stopCh &lt;- true             close(ts.stopCh)         }     } }<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"funkciya-obrabotchik-task\">\u0424\u0443\u043d\u043a\u0446\u0438\u044f-\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a task<\/h3>\n<p>  <\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 <a href=\"https:\/\/github.com\/romapres2010\/goapp\/blob\/master\/pkg\/app\/httphandler\/handler_wp.go\" rel=\"nofollow noopener noreferrer\">\u0444\u0443\u043a\u043d\u0446\u0438\u0438-\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0434\u043b\u044f \u0440\u0430\u0441\u0447\u0435\u0442\u0430 \u0444\u0430\u043a\u0442\u043e\u0440\u0438\u0430\u043b\u0430 n!<\/a>. <\/p>\n<p>  <\/p>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c Worker pool \u0434\u043b\u044f &#171;\u043a\u0440\u043e\u0442\u043a\u0438\u0445&#187; task.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">func calculateFactorialFn(parentCtx context.Context, ctx context.Context, data ...interface{}) (error, []interface{}) {     var factVal uint64 = 1     var cnt uint64 = 1      \/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432     if len(data) == 1 {         \/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0442\u0438\u043f \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432         if value, ok := data[0].(uint64); ok {             for cnt = 1; cnt &lt;= value; cnt++ {                 factVal *= cnt             }             return nil, []interface{}{factVal}         } else {             return _err.NewTyped(_err.ERR_INCORRECT_TYPE_ERROR, _err.ERR_UNDEFINED_ID, \"calculateFactorialFn\", \"0 - uint64\", reflect.ValueOf(data[0]).Type().String(), reflect.ValueOf(uint64(1)).Type().String()).PrintfError(), nil         }     }     return _err.NewTyped(_err.ERR_INCORRECT_ARG_NUM_ERROR, _err.ERR_UNDEFINED_ID, data).PrintfError(), nil }<\/code><\/pre>\n<p>  <\/p>\n<h2 id=\"4-struktura-worker\">4. \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 Worker<\/h2>\n<p>  <\/p>\n<pre><code class=\"go\">type Worker struct {     pool *Pool \/\/ pool, \u0432 \u0441\u043e\u0441\u0442\u0430\u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0432\u0445\u043e\u0434\u0438\u0442 worker      parentCtx context.Context \/\/ \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 pool, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 worker      externalId uint64           \/\/ \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 worker - \u0434\u043b\u044f \u0446\u0435\u043b\u0435\u0439 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f     stopCh     chan interface{} \/\/ \u043a\u0430\u043d\u0430\u043b \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043d\u0430 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 worker \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \"\u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u043c\u0438\u0440\u0430\"      id      uint                \/\/ \u043d\u043e\u043c\u0435\u0440 worker - \u0434\u043b\u044f \u0446\u0435\u043b\u0435\u0439 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f     state   WorkerState         \/\/ \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u043e\u0433\u043e \u0446\u0438\u043a\u043b\u0430 worker     errCh   chan&lt;- *WorkerError \/\/ \u043a\u0430\u043d\u0430\u043b \u0438\u043d\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043e \u043a\u0440\u0438\u0442\u0438\u0447\u043d\u044b\u0445 \u043e\u0448\u0438\u0431\u043a\u0430\u0445 worker \u0432 pool     timeout time.Duration       \/\/ \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0432\u0440\u0435\u043c\u044f \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f task, \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u0432 task \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435      taskQueueCh   &lt;-chan *Task \/\/ \u043a\u0430\u043d\u0430\u043b \u043e\u0447\u0435\u0440\u0435\u0434\u0438 task     taskInProcess *Task        \/\/ \u0442\u0435\u043a\u0443\u0449\u0430\u044f \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c\u0430\u044f task      mx sync.RWMutex }<\/code><\/pre>\n<p>  <\/p>\n<p>Worker \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u0443\u0441\u043d\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u044c\u044e.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">type WorkerState int  const (     WORKER_STATE_NEW                           WorkerState = iota \/\/ worker \u0441\u043e\u0437\u0434\u0430\u043d     WORKER_STATE_WORKING                                          \/\/ worker \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0437\u0430\u0434\u0430\u0447\u0443     WORKER_STATE_IDLE                                             \/\/ worker \u043f\u0440\u043e\u0441\u0442\u0430\u0438\u0432\u0430\u0435\u0442     WORKER_STATE_TERMINATING_PARENT_CTX_CLOSED                    \/\/ worker \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0435 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430     WORKER_STATE_TERMINATING_STOP_SIGNAL                          \/\/ worker \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u043e\u0431 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435     WORKER_STATE_TERMINATING_TASK_CH_CLOSED                       \/\/ worker \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0435 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f \u043a\u0430\u043d\u0430\u043b\u0430 \u0437\u0430\u0434\u0430\u0447     WORKER_STATE_TERMINATED                                       \/\/ worker \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d     WORKER_STATE_RECOVER_ERR                                      \/\/ worker \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0441\u044f \u0438\u0437-\u0437\u0430 \u043f\u0430\u043d\u0438\u043a\u0438 )<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"zapusk-worker\">\u0417\u0430\u043f\u0443\u0441\u043a worker<\/h3>\n<p>  <\/p>\n<p>Worker \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 goroutine \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043d\u0430 \u0432\u0445\u043e\u0434 sync.WaitGroup, \u0432 \u0441\u043e\u0441\u0442\u0430\u0432\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043e\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442: <\/p>\n<p>  <\/p>\n<ul>\n<li>\u0417\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u043c worker \u043d\u0430 \u0432\u0440\u0435\u043c\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f<\/li>\n<li>\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u043c, \u0447\u0442\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043c\u043e\u0436\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u043e\u0432\u044b\u0439 worker \u0438\u043b\u0438 \u043f\u043e\u0441\u043b\u0435 \u043f\u0430\u043d\u0438\u043a\u0438<\/li>\n<li>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 \u043a\u0430\u043d\u0430\u043b \u0434\u043b\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f worker \u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0441\u0440\u043e\u0447\u043d\u043e\u0439 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b &#171;\u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u043c\u0438\u0440\u0430&#187;. \u0417\u0430\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u043a\u0430\u043d\u0430\u043b \u0431\u0443\u0434\u0435\u043c \u0432 \u0442\u043e\u043c \u043c\u0435\u0441\u0442\u0435, \u0433\u0434\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0438\u0433\u043d\u0430\u043b.<\/li>\n<li>\u041e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u043f\u0430\u043d\u0438\u043a\u0443 worker, \u0435\u0441\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 WaitGroup, \u0442\u043e \u0443\u043c\u0435\u043d\u044c\u0448\u0438\u043c \u0441\u0447\u0435\u0442\u0447\u0438\u043a wg.Done()<\/li>\n<li>\u0416\u0434\u0435\u043c task \u0438\u0437 \u043a\u0430\u043d\u0430\u043b\u0430-\u043e\u0447\u0435\u0440\u0435\u0434\u0438 taskQueueCh (\u043f\u0443\u0441\u0442\u044b\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u043c), \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u043e\u0431 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0438\u043b\u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 pool<\/li>\n<li>\u0415\u0441\u043b\u0438 \u043a\u0430\u043d\u0430\u043b-\u043e\u0447\u0435\u0440\u0435\u0434\u0438 task \u0437\u0430\u043a\u0440\u044b\u0442 \u2014 \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0443<\/li>\n<li>\u041f\u0440\u0438 \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u0438 \u043d\u043e\u0432\u043e\u0439 task \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0432 \u0441\u0432\u043e\u0435\u0439 goroutine.<\/li>\n<li>\u0421\u043e\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043c\u0435\u0442\u0440\u0438\u043a\u0438 <a href=\"https:\/\/prometheus.io\/\" rel=\"nofollow noopener noreferrer\">prometheus<\/a>:<br \/> \n<ul>\n<li>wp_worker_process_count_vec \u2014 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e worker \u0432 \u0440\u0430\u0431\u043e\u0442\u0435<\/li>\n<li>wp_task_process_duration_ms_by_name \u2014 \u0433\u0438\u0441\u0442\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f task \u0432 ms \u0441 \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u043e\u0439 \u043f\u043e task.name<\/li>\n<li>wp_task_queue_buffer_len_vec \u2014 \u0434\u043b\u0438\u043d\u0430 \u043a\u0430\u043d\u0430\u043b\u0430-\u043e\u0447\u0435\u0440\u0435\u0434\u0438 task \u2014 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e worker pool \u0441\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u043e\u0439<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>  <\/p>\n<p><strong>\u0414\u043b\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u044b select \u043d\u0435\u0442 \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0438, \u0447\u0442\u043e \u043a\u0430\u043d\u0430\u043b\u044b \u0431\u0443\u0434\u0443\u0442 \u043e\u043f\u0440\u043e\u0448\u0435\u043d\u044b \u0438\u043c\u0435\u043d\u043d\u043e \u0432 \u0442\u043e\u0439 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043e\u043d\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u044b. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 \u043a\u0430\u0436\u0434\u043e\u0439 \u043d\u043e\u0432\u043e\u0439 \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0438 \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e worker \u043d\u0435 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d<\/strong><\/p>\n<p>  <\/p>\n<pre><code class=\"go\">func (wr *Worker) run(wg *sync.WaitGroup) {      \/\/ \u0417\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u043c worker \u043d\u0430 \u0432\u0440\u0435\u043c\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f     if wr.mx.TryLock() { \/\/ \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 TryLock \u043d\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f, \u043d\u043e \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044d\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u043d\u043e         defer wr.mx.Unlock()     } else {         err := _err.NewTyped(_err.ERR_WORKER_POOL_ALREADY_LOCKED, wr.externalId, wr.id, wr.state).PrintfError()          wr.errCh &lt;- &amp;WorkerError{ \/\/ \u043e\u0448\u0438\u0431\u043a\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u043e\u0431\u0449\u0438\u0439 \u043a\u0430\u043d\u0430\u043b \u043e\u0448\u0438\u0431\u043e\u043a pool             err:    err,             worker: wr,         }         return     }      \/\/ \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043c\u043e\u0436\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u043e\u0432\u044b\u0439 worker \u0438\u043b\u0438 \u043f\u043e\u0441\u043b\u0435 \u043f\u0430\u043d\u0438\u043a\u0438     if wr.state == WORKER_STATE_NEW || wr.state == WORKER_STATE_RECOVER_ERR {         wr.setStateUnsafe(WORKER_STATE_IDLE) \/\/ worker \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u0438 \u043f\u0440\u043e\u0441\u0442\u0430\u0438\u0432\u0430\u0435\u0442     } else {         err := _err.NewTyped(_err.ERR_WORKER_POOL_RUN_INCORRECT_STATE, wr.externalId, wr.id, wr.state, \"NEW', 'RECOVER_ERR\").PrintfError()          wr.errCh &lt;- &amp;WorkerError{ \/\/ \u043e\u0448\u0438\u0431\u043a\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u043e\u0431\u0449\u0438\u0439 \u043a\u0430\u043d\u0430\u043b \u043e\u0448\u0438\u0431\u043e\u043a pool             err:    err,             worker: wr,         }         return     }      \/\/ \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 \u043a\u0430\u043d\u0430\u043b \u0434\u043b\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f worker \u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0441\u0440\u043e\u0447\u043d\u043e\u0439 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \"\u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u043c\u0438\u0440\u0430\"     wr.stopCh = make(chan interface{}, 1)     \/\/defer close(wr.stopCh) !!! \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u043a\u0430\u043d\u0430\u043b \u0431\u0443\u0434\u0435\u043c \u0432 \u0442\u043e\u043c \u043c\u0435\u0441\u0442\u0435, \u0433\u0434\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0438\u0433\u043d\u0430\u043b      \/\/ \u041e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u043f\u0430\u043d\u0438\u043a\u0443 worker, \u0435\u0441\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 WaitGroup, \u0442\u043e \u0443\u043c\u0435\u043d\u044c\u0448\u0438\u043c \u0441\u0447\u0435\u0442\u0447\u0438\u043a     defer func() {         if r := recover(); r != nil {             err := _recover.GetRecoverError(r, wr.externalId)             if err != nil {                 wr.setStateUnsafe(WORKER_STATE_RECOVER_ERR)                  \/\/ \u043e\u0448\u0438\u0431\u043a\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u043e\u0431\u0449\u0438\u0439 \u043a\u0430\u043d\u0430\u043b \u043e\u0448\u0438\u0431\u043e\u043a pool                 wr.errCh &lt;- &amp;WorkerError{                     err:    err,                     worker: wr,                 }             }         } else {             wr.setStateUnsafe(WORKER_STATE_TERMINATED)         }          \/\/ \u0415\u0441\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 WaitGroup, \u0442\u043e \u0443\u043c\u0435\u043d\u044c\u0448\u0438\u043c \u0441\u0447\u0435\u0442\u0447\u0438\u043a         if wg != nil { wg.Done() }     }()      \/\/ \u0416\u0434\u0435\u043c task \u0438\u0437 \u043a\u0430\u043d\u0430\u043b\u0430-\u043e\u0447\u0435\u0440\u0435\u0434\u0438 taskQueueCh (\u043f\u0443\u0441\u0442\u044b\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u043c), \u0441\u0438\u0433\u043d\u0430\u043b\u0430 \u043e\u0431 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0438\u043b\u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 pool     for {         \/\/ \u0414\u043b\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u044b select \u043d\u0435\u0442 \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0438, \u0447\u0442\u043e \u043a\u0430\u043d\u0430\u043b\u044b \u0431\u0443\u0434\u0443\u0442 \u043e\u043f\u0440\u043e\u0449\u0435\u043d\u044b \u0438\u043c\u0435\u043d\u043d\u043e \u0432 \u0442\u043e\u0439 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043e\u043d\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u044b.          \/\/ \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 \u043a\u0430\u0436\u0434\u043e\u0439 \u043d\u043e\u0432\u043e\u0439 \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0438 \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e worker \u043d\u0435 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d         select {         case _, ok := &lt;-wr.stopCh:             if ok { \/\/ \u043a\u0430\u043d\u0430\u043b \u0431\u044b\u043b \u043e\u0442\u043a\u0440\u044b\u0442 \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u043d\u0430 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443                 wr.setStateUnsafe(WORKER_STATE_TERMINATING_STOP_SIGNAL)             } else {                 \/\/ \u041d\u0435 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u0430\u044f \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f \u0441 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0439 \u043b\u043e\u0433\u0438\u043a\u043e\u0439 - \u043b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u0434\u043b\u044f \u0430\u043d\u0430\u043b\u0438\u0437\u0430                 _log.Error(\"Worker - STOP - stop chanel closed: PoolName, WorkerId, WorkerExternalId\", wr.pool.name, wr.id, wr.externalId)             }             return         case &lt;-wr.parentCtx.Done():             \/\/ \u0437\u0430\u043a\u0440\u044b\u0442 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442             wr.setStateUnsafe(WORKER_STATE_TERMINATING_PARENT_CTX_CLOSED)             return         default:         }          \/\/ \u0415\u0441\u043b\u0438 worker \u043d\u0435 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d, \u0442\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043a\u0430\u043d\u0430\u043b-\u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0437\u0430\u0434\u0430\u0447         select {         case task, ok := &lt;-wr.taskQueueCh:             if ok { \/\/ \u043a\u0430\u043d\u0430\u043b \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0437\u0430\u0434\u0430\u0447 \u043e\u0442\u043a\u0440\u044b\u0442                 if task != nil { \/\/ \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u043c \u043f\u0443\u0441\u0442\u044b\u0435 \u0437\u0430\u0434\u0430\u0447\u0438                     _metrics.IncWPWorkerProcessCountVec(wr.pool.name)                               \/\/ \u041c\u0435\u0442\u0440\u0438\u043a\u0430 - \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e worker \u0432 \u0440\u0430\u0431\u043e\u0442\u0435                     _metrics.SetWPTaskQueueBufferLenVec(wr.pool.name, float64(len(wr.taskQueueCh))) \/\/ \u041c\u0435\u0442\u0440\u0438\u043a\u0430 - \u0434\u043b\u0438\u043d\u0430 \u043d\u0435\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u043e\u0439 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0437\u0430\u0434\u0430\u0447                      wr.setStateUnsafe(WORKER_STATE_WORKING)                     wr.taskInProcess = task                      \/\/_log.Debug(\"Worker - start to process task: PoolName, WorkerId, WorkerExternalId, TaskName\", wr.pool.name, wr.id, wr.externalId, task.name)                     task.process(wr.id, wr.timeout)                      wr.taskInProcess = nil                     wr.setStateUnsafe(WORKER_STATE_IDLE)                      _metrics.DecWPWorkerProcessCountVec(wr.pool.name)                            \/\/ \u041c\u0435\u0442\u0440\u0438\u043a\u0430 - \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e worker \u0432 \u0440\u0430\u0431\u043e\u0442\u0435                     _metrics.IncWPTaskProcessDurationVec(wr.pool.name, task.name, task.duration) \/\/ \u041c\u0435\u0442\u0440\u0438\u043a\u0430 - \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0437\u0430\u0434\u0430\u0447\u0438 \u043f\u043e \u0438\u043c\u0435\u043d\u0438                 }             } else { \/\/ \u0415\u0441\u043b\u0438 \u043a\u0430\u043d\u0430\u043b-\u043e\u0447\u0435\u0440\u0435\u0434\u0438 task \u0437\u0430\u043a\u0440\u044b\u0442 - \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0443                 wr.setStateUnsafe(WORKER_STATE_TERMINATING_TASK_CH_CLOSED)                 return             }         case _, ok := &lt;-wr.stopCh:             if ok { \/\/ \u043a\u0430\u043d\u0430\u043b \u0431\u044b\u043b \u043e\u0442\u043a\u0440\u044b\u0442 \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u043d\u0430 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443                 wr.setStateUnsafe(WORKER_STATE_TERMINATING_STOP_SIGNAL)             } else {                 \/\/ \u041d\u0435 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u0430\u044f \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f \u0441 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0439 \u043b\u043e\u0433\u0438\u043a\u043e\u0439 - \u043b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u0434\u043b\u044f \u0430\u043d\u0430\u043b\u0438\u0437\u0430                 _log.Error(\"Worker - STOP - stop chanel closed: PoolName, WorkerId, WorkerExternalId\", wr.pool.name, wr.id, wr.externalId)             }             return         case &lt;-wr.parentCtx.Done():             \/\/ \u0437\u0430\u043a\u0440\u044b\u0442 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442             wr.setStateUnsafe(WORKER_STATE_TERMINATING_PARENT_CTX_CLOSED)             return         }     } }<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"ostanovka-worker\">\u041e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 worker<\/h3>\n<p>  <\/p>\n<p>\u041f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c worker \u043c\u043e\u0436\u043d\u043e \u0447\u0435\u0440\u0435\u0437 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u0430\u043d\u0430\u043b stopCh.<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 &#171;Hard&#187; \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u0435 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 &#171;\u0434\u043b\u0438\u043d\u043d\u043e\u0439&#187; task<\/li>\n<li>\u0432\u043e \u0432\u0441\u0435\u0445 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u0440\u0435\u0436\u0438\u043c\u0430\u0445 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438, \u0442\u0435\u043a\u0443\u0449\u0430\u044f task \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u0430 \u0434\u043e \u043a\u043e\u043d\u0446\u0430<\/li>\n<\/ul>\n<p>  <\/p>\n<pre><code class=\"go\">func (wr *Worker) Stop(shutdownMode PoolShutdownMode) {     if wr == nil { return }      \/\/ \u041e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u043c\u043e\u0436\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u0441\u0442\u0430\u0442\u0443\u0441\u0430\u0445     if wr.state == WORKER_STATE_NEW || wr.state == WORKER_STATE_WORKING || wr.state == WORKER_STATE_IDLE {          \/\/ \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u0438\u0433\u043d\u0430\u043b \u0438 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u043a\u0430\u043d\u0430\u043b - \u0435\u0441\u043b\u0438 worker \u043d\u0438 \u0440\u0430\u0437\u0443 \u043d\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043b\u0441\u044f, \u0442\u043e wr.stopCh \u0431\u0443\u0434\u0435\u0442 nil         if wr.stopCh != nil {             wr.stopCh &lt;- true             close(wr.stopCh)         }          \/\/ \u0412 \u0440\u0435\u0436\u0438\u043c\u0435 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \"Hard\" \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u0435 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 task         if shutdownMode == POOL_SHUTDOWN_HARD {             if wr.taskInProcess != nil {                 wr.taskInProcess.Stop()             }         }     } }<\/code><\/pre>\n<p>  <\/p>\n<h2 id=\"5-struktura-pool\">5. \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 Pool<\/h2>\n<p>  <\/p>\n<pre><code class=\"go\">type Pool struct {     cfg *Config \/\/ \u043a\u043e\u043d\u0444\u0438\u0433 pool      parentCtx context.Context    \/\/ \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0441\u043e\u0437\u0434\u0430\u043b\u0438 pool     ctx       context.Context    \/\/ \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 pool     cancel    context.CancelFunc \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u0434\u043b\u044f pool      externalId   uint64           \/\/ \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440, \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 pool - \u0434\u043b\u044f \u0446\u0435\u043b\u0435\u0439 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f     name         string           \/\/ \u0438\u043c\u044f pool \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u0430 \u043c\u0435\u0442\u0440\u0438\u043a \u0438 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f     state        PoolState        \/\/ \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u043e\u0433\u043e \u0446\u0438\u043a\u043b\u0430 pool     stopCh       chan interface{} \/\/ \u043a\u0430\u043d\u0430\u043b \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043d\u0430 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 pool \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \"\u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u043c\u0438\u0440\u0430\"     isBackground bool             \/\/ pool \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u0432 background \u0440\u0435\u0436\u0438\u043c\u0435      workers           map[int]*Worker   \/\/ \u043d\u0430\u0431\u043e\u0440 worker     workerConcurrency int               \/\/ \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u0438\u0437\u043c\u0430 - \u0435\u0441\u043b\u0438 0, \u0442\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u044f\u0434\u0435\u0440 \u0445 2     workerTimeout     time.Duration     \/\/ \u0442\u0430\u0439\u043c\u0430\u0443\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0437\u0430\u0434\u0430\u0447\u0438 \u043e\u0434\u043d\u0438\u043c worker     workerErrCh       chan *WorkerError \/\/ \u043a\u0430\u043d\u0430\u043b \u043e\u0448\u0438\u0431\u043e\u043a workers, \u0440\u0430\u0437\u043c\u0435\u0440 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c worker      taskQueueCh   chan *Task \/\/ \u043a\u0430\u043d\u0430\u043b \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0437\u0430\u0434\u0430\u0447, \u043e\u0436\u0438\u0434\u0430\u044e\u0449\u0438\u0445 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f     taskQueueSize int        \/\/ \u0440\u0430\u0437\u043c\u0435\u0440 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0437\u0430\u0434\u0430\u0447 - \u0435\u0441\u043b\u0438 0, \u0442\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u044f\u0434\u0435\u0440 \u0445 1000      mx sync.RWMutex }<\/code><\/pre>\n<p>  <\/p>\n<p>Pool \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u0443\u0441\u043d\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u044c\u044e.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">type PoolState int  const (     POOL_STATE_NEW               PoolState = iota \/\/ pool \u0441\u043e\u0437\u0434\u0430\u043d, \u0435\u0449\u0435 \u043d\u0438 \u0440\u0430\u0437\u0443 \u043d\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043b\u0441\u044f     POOL_STATE_ONLINE_RUNNING                     \/\/ pool \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 online, \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u043e\u0432\u044b\u0445 \u0437\u0430\u0434\u0430\u0447 \u0437\u0430\u043f\u0440\u0435\u0449\u0435\u043d\u043e     POOL_STATE_ONLINE_DONE                        \/\/ pool \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u044b\u0439 \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 online, \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0432\u0441\u0435\u0445 \u0437\u0430\u0434\u0430\u0447     POOL_STATE_INCOMPLETE_DONE                    \/\/ pool \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u044b\u0439 \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 online, \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u041d\u0415 \u0432\u0441\u0435\u0445 \u0437\u0430\u0434\u0430\u0447     POOL_STATE_RECOVER_ERR                        \/\/ pool \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u043f\u043e \u043f\u0430\u043d\u0438\u043a\u0435, \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0438\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043d\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b     POOL_STATE_BG_RUNNING                         \/\/ pool \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 background, \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u043e\u0432\u044b\u0445 \u0437\u0430\u0434\u0430\u0447 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u043e     POOL_STATE_SHUTTING_DOWN                      \/\/ pool \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438, \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u043e\u0432\u044b\u0445 \u0437\u0430\u0434\u0430\u0447 \u0437\u0430\u043f\u0440\u0435\u0449\u0435\u043d\u043e     POOL_STATE_TERMINATE_TIMEOUT                  \/\/ pool \u043f\u0440\u0435\u0432\u044b\u0448\u0435\u043d\u043e \u0432\u0440\u0435\u043c\u044f \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438     POOL_STATE_SHUTDOWN                           \/\/ pool \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d )<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"zapusk-pool\">\u0417\u0430\u043f\u0443\u0441\u043a Pool<\/h3>\n<p>  <\/p>\n<p><a href=\"https:\/\/github.com\/romapres2010\/goapp\/blob\/master\/pkg\/common\/workerpool\/pool.go\" rel=\"nofollow noopener noreferrer\">Pool<\/a> \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u0432 \u0434\u0432\u0443\u0445 \u0440\u0435\u0436\u0438\u043c\u0430\u0445<\/p>\n<p>  <\/p>\n<ul>\n<li>online \u2014 \u0432 \u044d\u0442\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435 pool \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043d\u0430 \u0432\u0445\u043e\u0434 \u043f\u043e\u043b\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 task \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f, \u043f\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u0441\u0435\u0445 task \u043e\u043d \u0443\u0434\u0430\u043b\u044f\u0435\u0442\u0441\u044f. \u042d\u0442\u043e\u0442 \u0440\u0435\u0436\u0438\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0432 \u0441\u0442\u0430\u0442\u044c\u0435 \u043d\u0435 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u2014 \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430.<\/li>\n<li>background \u2014 \u0432 \u044d\u0442\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435 pool \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0432 \u0444\u043e\u043d\u0435, \u0441\u0442\u0430\u0440\u0442\u0443\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u0438 \u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u043f\u043e\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u0434\u0430\u0447 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c <\/li>\n<\/ul>\n<p>  <\/p>\n<p>Background Pool \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 goroutine:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0411\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u043c pool \u043d\u0430 \u0432\u0440\u0435\u043c\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u0438\u043d\u0430\u0447\u0435 task \u043c\u043e\u0433\u0443\u0442 \u043d\u0430\u0447\u0430\u0442\u044c \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u0442\u044c \u0440\u0430\u043d\u044c\u0448\u0435, \u0447\u0435\u043c \u043e\u043d \u0441\u0442\u0430\u0440\u0442\u0443\u0435\u0442<\/li>\n<li>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0443\u0436\u0435 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u044b\u0439 pool \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u043d\u0435\u043b\u044c\u0437\u044f<\/li>\n<li>\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0432\u0441\u0435\u0445 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0445 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440<\/li>\n<li>\u0421\u0442\u0430\u0440\u0442\u0443\u0435\u043c \u0432 \u0444\u043e\u043d\u0435 workers, \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0438\u043c \u043a\u0430\u043d\u0430\u043b \u043e\u0448\u0438\u0431\u043e\u043a \u0438 \u043a\u0430\u043d\u0430\u043b-\u043e\u0447\u0435\u0440\u0435\u0434\u044c task<\/li>\n<li>\u0420\u0430\u0437\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u043c pool, \u043e\u043d \u0433\u043e\u0442\u043e\u0432 \u043a \u0440\u0430\u0431\u043e\u0442\u0435 \u2014 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 task \u0432 \u043a\u0430\u043d\u0430\u043b-\u043e\u0447\u0435\u0440\u0435\u0434\u044c<\/li>\n<li>\u041e\u0436\u0438\u0434\u0430\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0438 \u043e\u0442 worker, \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u0438\u043b\u0438 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 pool<\/li>\n<\/ul>\n<p>  <\/p>\n<pre><code class=\"go\">func (p *Pool) RunBG(externalId uint64, shutdownTimeout time.Duration) (err error) {     if p == nil {         return _err.NewTyped(_err.ERR_INCORRECT_CALL_ERROR, externalId, \"Nil Pool pointer\").PrintfError()     }      \/\/ \u0411\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u043c pool \u043d\u0430 \u0432\u0440\u0435\u043c\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u0438\u043d\u0430\u0447\u0435 task \u043c\u043e\u0433\u0443\u0442 \u043d\u0430\u0447\u0430\u0442\u044c \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u0442\u044c \u0440\u0430\u043d\u044c\u0448\u0435, \u0447\u0435\u043c \u043e\u043d \u0441\u0442\u0430\u0440\u0442\u0443\u0435\u0442     p.mx.Lock()      \/\/ \u0423\u0436\u0435 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u044b\u0439 pool \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u043d\u0435\u043b\u044c\u0437\u044f     if p.state == POOL_STATE_NEW {         p.setStateUnsafe(POOL_STATE_BG_RUNNING)         p.isBackground = true         p.externalId = externalId     } else {         err = _err.NewTyped(_err.ERR_WORKER_POOL_RUN_INCORRECT_STATE, p.externalId, p.name, p.state, \"NEW\").PrintfError()         p.mx.Unlock()         return err     }      \/\/ \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0432\u0441\u0435\u0445 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0445 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440     p.ctx, p.cancel = context.WithCancel(context.Background())   \/\/ \u0420\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u0432 \u0438\u0437\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c \u043e\u0442 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435     p.workers = make(map[int]*Worker, p.workerConcurrency)       \/\/ \u041d\u0430\u0431\u043e\u0440 worker     p.workerErrCh = make(chan *WorkerError, p.workerConcurrency) \/\/ \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u043e \u043e\u0434\u043d\u043e\u0439 \u043e\u0448\u0438\u0431\u043a\u0435 \u043d\u0430 worker     p.taskQueueCh = make(chan *Task, p.taskQueueSize)            \/\/ \u041a\u0430\u043d\u0430\u043b-\u043e\u0447\u0435\u0440\u0435\u0434\u044c task     p.stopCh = make(chan interface{}, 1)                         \/\/ \u0412\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 \u043a\u0430\u043d\u0430\u043b \u0434\u043b\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f pool \u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0441\u0440\u043e\u0447\u043d\u043e\u0439 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \"\u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u043c\u0438\u0440\u0430\"     \/\/defer close(p.stopCh) \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u043a\u0430\u043d\u0430\u043b \u0431\u0443\u0434\u0435\u043c \u0432 \u0442\u043e\u043c \u043c\u0435\u0441\u0442\u0435, \u0433\u0434\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0438\u0433\u043d\u0430\u043b      \/\/ \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u043b\u0435 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u0430\u043d\u0438\u043a\u0438 \u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430     defer func() {         if r := recover(); r != nil {             err = _recover.GetRecoverError(r, p.externalId)             p.mx.Lock()             defer p.mx.Unlock()             p.setStateUnsafe(POOL_STATE_RECOVER_ERR)             _ = p.shutdownUnsafe(POOL_SHUTDOWN_HARD, shutdownTimeout) \/\/ \u044d\u043a\u0441\u0442\u0440\u0435\u043d\u043d\u0430\u044f \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430, \u043e\u0448\u0438\u0431\u043a\u0443 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u043c         }          if p.cancel != nil { p.cancel() }     }()      \/\/ \u0421\u0442\u0430\u0440\u0442\u0443\u0435\u043c \u0432 \u0444\u043e\u043d\u0435 workers, \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0438\u043c \u043a\u0430\u043d\u0430\u043b \u043e\u0448\u0438\u0431\u043e\u043a \u0438 \u043a\u0430\u043d\u0430\u043b-\u043e\u0447\u0435\u0440\u0435\u0434\u044c task     for workerId := 1; workerId &lt;= p.workerConcurrency; workerId++ {         worker := newWorker(p.ctx, p, p.taskQueueCh, uint(workerId), p.externalId, p.workerErrCh, p.workerTimeout)          p.workers[workerId] = worker          go worker.run(nil) \/\/ \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0432 \u0444\u043e\u043d\u0435 \u0431\u0435\u0437 WaitGroup     }      \/\/ Pool \u0433\u043e\u0442\u043e\u0432 \u043a \u0440\u0430\u0431\u043e\u0442\u0435 - \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 task \u0432 \u043a\u0430\u043d\u0430\u043b-\u043e\u0447\u0435\u0440\u0435\u0434\u044c     p.mx.Unlock()      \/\/ \u041e\u0436\u0438\u0434\u0430\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0438 \u043e\u0442 worker, \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u0438\u043b\u0438 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 pool     for {         select {         case workerErr, ok := &lt;-p.workerErrCh:             if ok { \/\/ \u043a\u0430\u043d\u0430\u043b \u043e\u0442\u043a\u0440\u044b\u0442 - \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430 pool                 _ = _err.WithCauseTyped(_err.ERR_WORKER_POOL_WORKER_ERROR, p.externalId, workerErr.err, p.name, workerErr.worker.id, workerErr.err.Error()).PrintfError()                 if workerErr.worker != nil {                     go workerErr.worker.run(nil) \/\/ \u0441\u0442\u0430\u0440\u0442\u0443\u0435\u043c worker \u0437\u0430\u043d\u043e\u0432\u043e                 }             } else { \/\/ \u043a\u0430\u043d\u0430\u043b \u0437\u0430\u043a\u0440\u044b\u0442 - \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f \u043f\u0440\u0438 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435 pool                 return nil             }         case &lt;-p.stopCh:             \/\/ \u041d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438             return nil         case &lt;-p.parentCtx.Done():             \/\/ \u0417\u0430\u043a\u0440\u044b\u043b\u0441\u044f \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 - \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0432\u0441\u0435 worker             p.mx.Lock()             \/\/ \u043e\u0448\u0438\u0431\u043a\u0438 \u0431\u0443\u0434\u0443\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u044b \u0447\u0435\u0440\u0435\u0437 \u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u043d\u0443\u044e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u0430             err = p.shutdownUnsafe(POOL_SHUTDOWN_HARD, shutdownTimeout)             p.mx.Unlock()             return err         }     } }<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"dobavlenie-novyh-task-v-ochered\">\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u043e\u0432\u044b\u0445 task \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c<\/h3>\n<p>  <\/p>\n<ul>\n<li>\u0411\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u043c pool \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u0438 \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 task \u0434\u043e \u043f\u043e\u043b\u043d\u043e\u0439 \u0438\u043d\u0438\u0446\u0438\u0430\u0446\u0438\u0438 pool<\/li>\n<li>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f \u043a\u0430\u043d\u0430\u043b\u0430-\u043e\u0447\u0435\u0440\u0435\u0434\u0438 task<\/li>\n<li>\u041e\u0447\u0435\u0440\u0435\u0434\u044c \u0438\u043c\u0435\u0435\u0442 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u2014 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u0435, \u043f\u043e\u043a\u0430 \u043d\u0435 \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e. <\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u041a\u0430\u043d\u0430\u043b-\u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0437\u0430\u0434\u0430\u0447 \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u0442\u0441\u044f \u0434\u0432\u0443\u043c\u044f \u043c\u0435\u0442\u0440\u0438\u043a\u0430\u043c\u0438: <\/p>\n<p>  <\/p>\n<ul>\n<li>wp_add_task_wait_count_vec \u2014 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u0434\u0430\u0447, \u043e\u0436\u0438\u0434\u0430\u044e\u0449\u0438\u0445 \u043f\u043e\u043f\u0430\u0434\u0430\u043d\u0438\u044f \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c<\/li>\n<li>wp_task_queue_buffer_len_vec \u2014 \u0442\u0435\u043a\u0443\u0449\u0430\u044f \u0434\u043b\u0438\u043d\u0430 \u043a\u0430\u043d\u0430\u043b\u0430-\u043e\u0447\u0435\u0440\u0435\u0434\u0438 task \u2014 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u043a\u0430\u043d\u0430\u043b\u0430<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0417\u0430\u0447\u0435\u043c \u0438\u043c\u0435\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0440 \u043a\u0430\u043d\u0430\u043b\u0430-\u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0431\u043e\u043b\u044c\u0448\u0435 \u0447\u0435\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432? <\/p>\n<p>  <\/p>\n<p>\u042d\u0442\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0435\u0441\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 \u0440\u0435\u0436\u0438\u043c \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0432\u043d\u0435\u0448\u043d\u0438\u043c\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u044f\u043c\u0438 Worker pool. \u041f\u0435\u0440\u0432\u0430\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u2014 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f task \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0431\u044b\u0441\u0442\u0440\u043e\u0439 \u2014 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e. \u0420\u043e\u0441\u0442 \u043c\u0435\u0442\u0440\u0438\u043a\u0438 wp_add_task_wait_count_vec \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0446\u0435\u043d\u0438\u0442\u044c \u0443\u0437\u043a\u043e\u0435 \u043c\u0435\u0441\u0442\u043e \u0438, \u043d\u0430\u0440\u043f\u0438\u043c\u0435\u0440, \u0441\u0442\u0430\u0440\u0442\u043e\u0432\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 Pod (\u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 Kubernetes \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432). <\/p>\n<p>  <\/p>\n<pre><code class=\"go\">func (p *Pool) AddTask(task *Task) (err error) {     if p == nil { return _err.NewTyped(_err.ERR_INCORRECT_CALL_ERROR, _err.ERR_UNDEFINED_ID, \"Nil Pool pointer\").PrintfError() }      if task == nil { return nil } \/\/ \u041f\u0443\u0441\u0442\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u043c      \/\/ \u0411\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u043c pool \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u0438 \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 task \u0434\u043e \u043f\u043e\u043b\u043d\u043e\u0439 \u0438\u043d\u0438\u0446\u0438\u0430\u0446\u0438\u0438 pool     p.mx.RLock()      \/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 task \u0437\u0430\u043f\u0440\u0435\u0449\u0435\u043d\u043e     if p.state != POOL_STATE_BG_RUNNING {         err = _err.NewTyped(_err.ERR_WORKER_POOL_ADD_TASK_INCORRECT_STATE, p.externalId, p.state, \"NEW, RUNNING_BG, PAUSED_BG\").PrintfError()         p.mx.RUnlock()         return err     }      p.mx.RUnlock()      \/\/ \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f \u043a\u0430\u043d\u0430\u043b\u0430-\u043e\u0447\u0435\u0440\u0435\u0434\u0438 task     defer func() {         if r := recover(); r != nil {             err = _recover.GetRecoverError(r, p.externalId)         }     }()      _metrics.IncWPAddTaskWaitCountVec(p.name) \/\/ \u0421\u0447\u0435\u0442\u0447\u0438\u043a \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u0439 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c - \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u044c     p.taskQueueCh &lt;- task                     \/\/ \u041e\u0447\u0435\u0440\u0435\u0434\u044c \u0438\u043c\u0435\u0435\u0442 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 - \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u0435, \u043f\u043e\u043a\u0430 \u043d\u0435 \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e     _metrics.DecWPAddTaskWaitCountVec(p.name) \/\/ \u0421\u0447\u0435\u0442\u0447\u0438\u043a \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u0439 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c - \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u043b\u0438 - \u0443\u043c\u0435\u043d\u044c\u0448\u0438\u0442\u044c      return nil }<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"ostanovka-pool\">\u041e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 pool<\/h3>\n<p>  <\/p>\n<ul>\n<li>\u0417\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u043a\u0430\u043d\u0430\u043b \u0437\u0430\u0434\u0430\u0447 \u0434\u043b\u044f Background pool, \u0434\u043b\u044f Online \u043e\u043d \u0443\u0436\u0435 \u0437\u0430\u043a\u0440\u044b\u0442<\/li>\n<li>\u0412 \u0440\u0435\u0436\u0438\u043c\u0435 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 &#171;hard&#187; \u0438 &#171;soft&#187;, \u0432\u044b\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c task \u0438\u0437 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0438 \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0438\u0445<\/li>\n<li>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 worker \u0438 \u043e\u0436\u0438\u0434\u0430\u0435\u043c \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0439 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0438\u043b\u0438 shutdownTimeout, \u0435\u0441\u043b\u0438 shutdownTimeout == 0, \u0442\u043e \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0435 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u0435<\/li>\n<li>\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u043e\u0448\u0438\u0431\u043a\u0438 \u043e\u0442 worker, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u043a\u043e\u043f\u0438\u043b\u0438\u0441\u044c \u0432 \u043a\u0430\u043d\u0430\u043b\u0435 workerErrCh<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0421\u0443\u0444\u0444\u0438\u043a\u0441\u043e\u043c Unsafe \u043f\u043e\u043c\u0435\u0447\u0435\u043d\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u043d\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438 sync.RWMutex. \u0422\u0430\u043a \u0436\u0435 \u0432 \u043d\u0438\u0445 \u0437\u0430\u043f\u0440\u0435\u0449\u0435\u043d\u044b \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0430 sync.RWMutex. <\/p>\n<p>  <\/p>\n<pre><code class=\"go\">func (p *Pool) shutdownUnsafe(shutdownMode PoolShutdownMode, shutdownTimeout time.Duration) (err error) {      \/\/ \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u0443\u044e \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443     if p.state != POOL_STATE_SHUTDOWN &amp;&amp; p.state != POOL_STATE_SHUTTING_DOWN {         \/\/_log.Debug(\"Pool - SHUTTING DOWN : ExternalId, PoolName, ActiveTaskCount, State\", p.externalId, p.name, len(p.taskQueueCh), p.state)          \/\/ \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u043b\u0435 \u043f\u0430\u043d\u0438\u043a\u0438         defer func() {             if r := recover(); r != nil {                 err = _recover.GetRecoverError(r, p.externalId)             }              p.setStateUnsafe(POOL_STATE_SHUTDOWN) \/\/ \u041e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0437\u0430\u043a\u043e\u043d\u0447\u0435\u043d\u0430         }()          p.setStateUnsafe(POOL_STATE_SHUTTING_DOWN) \/\/ \u041d\u0430\u0447\u0430\u043b\u043e \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 - \u0432 \u044d\u0442\u043e\u043c \u0441\u0442\u0430\u0442\u0443\u0441\u0435 \u0437\u0430\u043f\u0440\u0435\u0449\u0435\u043d\u043e \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0435 task          \/\/ \u0417\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u043a\u0430\u043d\u0430\u043b \u0437\u0430\u0434\u0430\u0447 \u0434\u043b\u044f Background pool, \u0434\u043b\u044f Online \u043e\u043d \u0443\u0436\u0435 \u0437\u0430\u043a\u0440\u044b\u0442         if p.isBackground { close(p.taskQueueCh) }          \/\/ \u0412 \u0440\u0435\u0436\u0438\u043c\u0435 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \"hard\" \u0438 \"soft\", \u0432\u044b\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c task \u0438\u0437 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0438 \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0438\u0445         if shutdownMode == POOL_SHUTDOWN_HARD || shutdownMode == POOL_SHUTDOWN_SOFT {             for task := range p.taskQueueCh {                 if task != nil { task.Stop() }             }         }          \/\/ \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 worker \u0438 \u043e\u0436\u0438\u0434\u0430\u0435\u043c \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0439 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0438\u043b\u0438 shutdownTimeout, \u0435\u0441\u043b\u0438 shutdownTimeout == 0, \u0442\u043e \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0435 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u0435         p.stopWorkersUnsafe(shutdownMode, shutdownTimeout)          close(p.workerErrCh) \/\/ \u0417\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u043a\u0430\u043d\u0430\u043b \u043e\u0448\u0438\u0431\u043e\u043a worker          \/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u043e\u0448\u0438\u0431\u043a\u0438 \u043e\u0442 worker, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u043a\u043e\u043f\u0438\u043b\u0438\u0441\u044c \u0432 \u043a\u0430\u043d\u0430\u043b\u0435         if len(p.workerErrCh) != 0 {             \/\/ \u041d\u0430\u043a\u043e\u043f\u043b\u0435\u043d\u043d\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 worker \u0437\u0430\u043b\u043e\u0433\u0438\u0440\u0443\u0435\u043c, \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u043f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c \u043d\u0430 \u0432\u0435\u0440\u0445             for workerErr := range p.workerErrCh {                 \/\/_log.Debug(\"Pool online - DONE - Worker error: error\", workerErr.err.Error())                 err = _err.WithCauseTyped(_err.ERR_WORKER_POOL_WORKER_ERROR, p.externalId, workerErr.err, p.name, workerErr.worker.id, workerErr.err.Error()).PrintfError()             }         }     }      return err }<\/code><\/pre>\n<p>  <\/p>\n<h2 id=\"6-optimizaciya-worker-pool\">6. \u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f Worker pool<\/h2>\n<p>  <\/p>\n<h3 id=\"optimizaciya-rashoda-pamyati-na-sozdanie-task\">\u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u0440\u0430\u0441\u0445\u043e\u0434\u0430 \u043f\u0430\u043c\u044f\u0442\u0438 \u043d\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 task<\/h3>\n<p>  <\/p>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0440\u0430\u0441\u0445\u043e\u0434\u044b \u043f\u0430\u043c\u044f\u0442\u0438 \u043f\u0440\u0438\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u043d\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043d\u043e\u0432\u043e\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b task \u043f\u0440\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u0437\u0430\u0434\u0430\u0447\u0438 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c. \u041f\u043e\u0441\u043b\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f task \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0431\u0440\u0430\u043d\u0430 GC.<\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u044d\u0442\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u043e\u0442\u043b\u0438\u0447\u043d\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 sync.Pool. \u0412\u043c\u0435\u0441\u0442\u043e, \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b &#171;\u0432\u044b\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0442\u044c&#187; task \u043f\u043e\u0441\u043b\u0435 \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0431\u0443\u0434\u0435\u0442 \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u0438\u0445 \u0432 sync.Pool, \u0430 \u043f\u0440\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u043d\u043e\u0432\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u0431\u0440\u0430\u0442\u044c \u0438\u0445 \u0438\u0437 sync.Pool.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">    \/\/ \u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0434\u0430\u0447 \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430     for i, value := range *wpFactorialReqResp.NumArray {         task := _wp.NewTask(ctx, \"\", nil, uint64(i), requestID, -1*time.Second, calculateEmptyFn, value)         tasks = append(tasks, task)     }      \/\/ \u0432 \u043a\u043e\u043d\u0446\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c task \u0432 \u043a\u044d\u0448 \u0434\u043b\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f     defer func() {         for _, task := range tasks {             task.Delete()         }     }()<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"optimizaciya-raboty-s-timetimer\">\u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 time.Timer<\/h3>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438-\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 task, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f time.Timer.<\/p>\n<p>  <\/p>\n<p>\u0412 \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u043a\u0443\u044e \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044e \u0441 time.After(ts.timeout) \u0432 task.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">    select {     case &lt;-ts.localDoneCh:       ...     case _, ok := &lt;-ts.stopCh:       ...     case &lt;-time.After(ts.timeout):         ts.err = _err.NewTyped(_err.ERR_WORKER_POOL_TIMEOUT_ERROR, ts.externalId, ts.timeout).PrintfError()         ts.setState(TASK_STATE_TERMINATED_TIMEOUT)         return     }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u0442\u044c \u043e\u0434\u043d\u043e &#171;\u043d\u043e&#187;, time.After \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043d\u043e\u0432\u044b\u0439 \u043a\u0430\u043d\u0430\u043b \u0434\u043b\u044f \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0438 \u044d\u0442\u043e\u0442 \u043a\u0430\u043d\u0430\u043b \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0443\u0434\u0430\u043b\u0435\u043d CG, \u043f\u043e\u043a\u0430 \u0442\u0430\u0439\u043c\u0435\u0440 \u043d\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442.<br \/>  \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0435 \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0440\u0430\u0441\u0445\u043e\u0434 \u043f\u0430\u043c\u044f\u0442\u0438 \u0438 \u043f\u043e\u0442\u0435\u0440\u0438 \u043f\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0432 2-3 \u0440\u0430\u0437\u0430 \u043d\u0430 \u0438\u043d\u0442\u0435\u043d\u0441\u0438\u0432\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u0445 \u0441 task. <\/p>\n<p>  <\/p>\n<p>\u0412\u043c\u0435\u0441\u0442\u043e time.After, \u0432 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u043e\u043c \u0448\u0430\u0431\u043b\u043e\u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u044f\u0432\u043d\u043e\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435\u043c, \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u043e\u0439 \u0438 \u0441\u0431\u0440\u043e\u0441\u043e\u043c time.Timer.<\/p>\n<p>  <\/p>\n<ul>\n<li>time.Timer \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043d\u043e\u0432\u043e\u0439 task \u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 (\u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0430 workerpool\u044e.POOL_MAX_TIMEOUT) <\/li>\n<li>\u043f\u043e\u0441\u043b\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f time.Timer \u0441\u0440\u0430\u0437\u0443 \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f timer.Stop(). \u041f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 task.process \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043d\u0430 \u0432\u0445\u043e\u0434 \u0432\u0441\u0435\u0433\u0434\u0430 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0439 time.Timer<\/li>\n<li>\u043f\u0440\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 task.process \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 timeout, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0443\u0436\u043d\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 time.Timer. \u0415\u0441\u043b\u0438 timeout == 0, \u0442\u043e time.Timer \u043d\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f<\/li>\n<li>\u043f\u0440\u0438 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438-\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430, task \u0441\u0440\u0430\u0437\u0443 \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 time.Timer. \u0412\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u044c, \u0447\u0442\u043e Timer \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b \u0432 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043a\u0435 \u043c\u0435\u0436\u0434\u0443 select \u0438\u0437 localDoneCh \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c ts.timer.Stop() \u043a\u0440\u0430\u0439\u043d\u0435 \u043c\u0430\u043b\u0430, \u043d\u043e \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0434\u0441\u0442\u0440\u0430\u0445\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0438 \u043e\u0447\u0438\u0441\u0442\u0438\u0442\u044c \u043a\u0430\u043d\u0430\u043b. <\/li>\n<\/ul>\n<p>  <\/p>\n<pre><code class=\"go\">    if !ts.timer.Stop() {         &lt;-ts.timer.C \/\/ \u0412\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u044c, \u0447\u0442\u043e \u043e\u043d \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b \u0432 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043a\u0435 \u043c\u0435\u0436\u0434\u0443 select \u0438\u0437 localDoneCh \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c ts.timer.Stop() \u043a\u0440\u0430\u0439\u043d\u0435 \u043c\u0430\u043b\u0430     }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 time.Timer.<\/p>\n<p>  <\/p>\n<h3 id=\"realizaciya-taskpool\">\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f TaskPool<\/h3>\n<p>  <\/p>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f <a href=\"https:\/\/github.com\/romapres2010\/goapp\/blob\/master\/pkg\/common\/workerpool\/taskpool.go\" rel=\"nofollow noopener noreferrer\">TaskPool<\/a><\/p>\n<p>  <\/p>\n<ul>\n<li>\u041f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043d\u043e\u0432\u043e\u0439 task \u0441\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043a\u0430\u043d\u0430\u043b\u044b, \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0438 \u0442\u0430\u0439\u043c\u0435\u0440<\/li>\n<li>\u041f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 task \u0438\u0437 sync.Pool \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f<\/li>\n<li>\u041f\u0440\u0438 \u043f\u043e\u043c\u0435\u0449\u0435\u043d\u0438\u0438 task \u0432 sync.Pool \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u0435\u0435 \u0441\u0442\u0430\u0442\u0443\u0441. <br \/> \n<ul>\n<li>\u0415\u0441\u043b\u0438 task \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043b\u0441\u044f, \u0442\u043e \u043a\u0430\u043d\u0430\u043b\u044b \u043e\u0441\u0442\u0430\u043b\u0438\u0441\u044c \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c\u0438, \u0442\u0430\u0439\u043c\u0435\u0440 \u043d\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b \u0438 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u043d\u0435 \u0437\u0430\u043a\u0440\u044b\u0442. \u0422\u0430\u043a\u043e\u0439 task \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u2014 \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0432 sync.Pool<\/li>\n<li>\u0412 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 task \u043d\u0435 \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u0442\u0441\u044f \u0432 sync.Pool \u0438 \u043f\u043e\u0437\u0436\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u043e\u0431\u0440\u0430\u043d CG<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>  <\/p>\n<pre><code class=\"go\">\/\/ TaskPool represent pooling of Task type TaskPool struct {     pool sync.Pool }  \/\/ Represent a pool statistics for benchmarking var (     countGet uint64 \/\/ \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a\u044d\u0448\u0430     countPut uint64 \/\/ \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u043e\u0432 \u0432 \u043a\u044d\u0448\u0430     countNew uint64 \/\/ \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430 )  \/\/ newTaskPool create new TaskPool func newTaskPool() *TaskPool {     p := &amp;TaskPool{         pool: sync.Pool{             New: func() interface{} {                 atomic.AddUint64(&amp;countNew, 1)                 task := new(Task)                 task.stopCh = make(chan interface{}, 1)                          \/\/ \u043a\u0430\u043d\u0430\u043b \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043d\u0430 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 task                 task.localDoneCh = make(chan interface{}, 1)                     \/\/ \u043a\u0430\u043d\u0430\u043b \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 timeout \u0438 \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043d\u0430 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 task                 task.timer = time.NewTimer(POOL_MAX_TIMEOUT)                     \/\/ \u043d\u043e\u0432\u044b\u0439 \u0442\u0430\u0439\u043c\u0435\u0440 - \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f                 task.timer.Stop()                                                \/\/ \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c \u0442\u0430\u0439\u043c\u0435\u0440, \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0442\u044c \u043a\u0430\u043d\u0430\u043b \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d \u043d\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b                 task.ctx, task.cancel = context.WithCancel(context.Background()) \/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0441 \u043e\u0442\u043c\u0435\u043d\u043e\u0439                 return task             },         },     }     return p }  \/\/ getTask allocates a new Task func (p *TaskPool) getTask() *Task {     atomic.AddUint64(&amp;countGet, 1)     task := p.pool.Get().(*Task)     return task }  \/\/ putTask return Task to pool func (p *TaskPool) putTask(task *Task) {     \/\/ \u0415\u0441\u043b\u0438 task \u043d\u0435 \u0431\u044b\u043b \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d, \u0442\u043e \u0432 \u043d\u0435\u043c \u043c\u043e\u0433\u043b\u0438 \u0431\u044b\u0442\u044c \u0437\u0430\u043a\u0440\u044b\u0442\u044b \u043a\u0430\u043d\u0430\u043b\u044b \u0438\u043b\u0438 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b \u0442\u0430\u0439\u043c\u0435\u0440 - \u0442\u0430\u043a\u0438\u0435 \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0442 \u0434\u043b\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f     if task.state == TASK_STATE_NEW || task.state == TASK_STATE_DONE_SUCCESS {         atomic.AddUint64(&amp;countPut, 1)         task.requests = nil  \/\/ \u043e\u0431\u043d\u0443\u043b\u0438\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c, \u0447\u0442\u043e\u0431\u044b \u043e\u0441\u0432\u043e\u0431\u043e\u0434\u0438\u0442\u044c \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u0430 \u043c\u0443\u0441\u043e\u0440\u0430         task.responses = nil \/\/ \u043e\u0431\u043d\u0443\u043b\u0438\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c, \u0447\u0442\u043e\u0431\u044b \u043e\u0441\u0432\u043e\u0431\u043e\u0434\u0438\u0442\u044c \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u0430 \u043c\u0443\u0441\u043e\u0440\u0430         p.pool.Put(task)     \/\/ \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0432 pool     } }  \/\/ \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0439 TaskPool var gTaskPool = newTaskPool()  \/\/ PrintTaskPoolStats print statistics about task pool func (p *Pool) PrintTaskPoolStats() {     if p != nil {         _log.Info(\"Usage task pool: countGet, countPut, countNew\", countGet, countPut, countNew)     } }<\/code><\/pre>\n<p>  <\/p>\n<h2 id=\"7-nagruzochnoe-testirovanie-worker-pool\">7. \u041d\u0430\u0433\u0440\u0443\u0437\u043e\u0447\u043d\u043e\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 Worker pool<\/h2>\n<p>  <\/p>\n<h3 id=\"scenariy-testirovaniya\">\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f<\/h3>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u044b\u0431\u0440\u0430\u043b \u043a\u0440\u0430\u0439\u043d\u0435 \u043d\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 &#171;\u043a\u043e\u0440\u043e\u0442\u043a\u0438\u0445&#187; task \u2014 \u0431\u0443\u0434\u0435\u043c \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u0441\u0443\u043c\u043c\u0443 \u0444\u0430\u043a\u0442\u043e\u0440\u0438\u0430\u043b\u043e\u0432 \u0432 \u0433\u0440\u0443\u043f\u043f\u0435 task.<\/p>\n<p>  <\/p>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439 task \u0438\u0437 \u0433\u0440\u0443\u043f\u043f\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u0438 \u043f\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044e \u0432\u0441\u0435\u0439 \u0433\u0440\u0443\u043f\u043f\u044b \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0441\u0443\u043c\u043c\u0438\u0440\u0443\u044e\u0442\u0441\u044f.<\/p>\n<p>  <\/p>\n<p><a href=\"https:\/\/github.com\/romapres2010\/goapp\/blob\/master\/pkg\/app\/httphandler\/handler_wp.go\" rel=\"nofollow noopener noreferrer\">\u0424\u0443\u043a\u043d\u0446\u0438\u044f-\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0434\u043b\u044f \u0440\u0430\u0441\u0447\u0435\u0442\u0430 \u0444\u0430\u043a\u0442\u043e\u0440\u0438\u0430\u043b\u0430 n!<\/a>.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">func calculateFactorialFn(parentCtx context.Context, ctx context.Context, data ...interface{}) (error, []interface{}) {     var factVal uint64 = 1     var cnt uint64 = 1      \/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432     if len(data) == 1 {         \/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0442\u0438\u043f \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432         if value, ok := data[0].(uint64); ok {             for cnt = 1; cnt &lt;= value; cnt++ {                 factVal *= cnt             }             return nil, []interface{}{factVal}         } else {             return _err.NewTyped(_err.ERR_INCORRECT_TYPE_ERROR, _err.ERR_UNDEFINED_ID, \"calculateFactorialFn\", \"0 - uint64\", reflect.ValueOf(data[0]).Type().String(), reflect.ValueOf(uint64(1)).Type().String()).PrintfError(), nil         }     }     return _err.NewTyped(_err.ERR_INCORRECT_ARG_NUM_ERROR, _err.ERR_UNDEFINED_ID, data).PrintfError(), nil }<\/code><\/pre>\n<p>  <\/p>\n<p><a href=\"https:\/\/github.com\/romapres2010\/goapp\/blob\/master\/pkg\/app\/httphandler\/handler_wp.go\" rel=\"nofollow noopener noreferrer\">\u0424\u0443\u043a\u043d\u0446\u0438\u044f-\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0434\u043b\u044f \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0433\u0440\u0443\u043f\u043f\u044b task \u0438 \u0441\u0443\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432<\/a>.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">\/\/ calculateFactorial \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0440\u0430\u0441\u0447\u0435\u0442\u0430 Factorial func calculateFactorial(ctx context.Context, wpService *_wpservice.Service, requestID uint64, wpFactorialReqResp *WpFactorialReqResp, wpTipe string, tasks []*_wp.Task) (err error) {     \/\/ \u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0434\u0430\u0447 \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430     for i, value := range *wpFactorialReqResp.NumArray {         task := _wp.NewTask(ctx, \"CalculateFactorial\", nil, uint64(i), requestID, -1*time.Second, calculateFactorialFn, value)         tasks = append(tasks, task)     }      \/\/ \u0432 \u043a\u043e\u043d\u0446\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c task \u0432 \u043a\u044d\u0448 \u0434\u043b\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f     defer func() {         for _, task := range tasks {             task.Delete()         }     }()      \/\/ \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0432 \u043e\u0431\u0449\u0438\u0439 background pool     err = wpService.RunTasksGroupWG(requestID, tasks, \"Calculate - background\")      \/\/ \u0410\u043d\u0430\u043b\u0438\u0437 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432     if err == nil {         \/\/ \u0421\u0443\u043c\u043c\u0438\u0440\u0443\u0435\u043c \u0432\u0441\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b         for _, task := range tasks {             if task.GetError() == nil {                 result := task.GetResponses()[0] \/\/ \u043e\u0436\u0438\u0434\u0430\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u043e\u0442\u0432\u0435\u0442                  \/\/ \u041f\u0440\u0438\u0432\u0435\u0434\u0435\u043c \u043a \u043d\u0443\u0436\u043d\u043e\u043c\u0443 \u0442\u0438\u043f\u0443                 if factorial, ok := result.(uint64); ok {                     wpFactorialReqResp.SumFactorial += factorial                 } else {                     return _err.NewTyped(_err.ERR_INCORRECT_TYPE_ERROR, _err.ERR_UNDEFINED_ID, \"WpHandlerFactorial\", \"0 - uint\", reflect.ValueOf(factorial).Type().String(), reflect.ValueOf(uint64(1)).Type().String()).PrintfError()                 }             } else {                 _log.Error(\"Task error\", requestID, task.GetError())                 return task.GetError()             }         }     } else {         _log.Error(\"RunTasksGroupWG error\", requestID, err)     }      return err }<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"benchmark-dlya-testirovaniya\">Benchmark \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f<\/h3>\n<p>  <\/p>\n<p>\u0421\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043d\u0430\u0431\u043e\u0440\u044b task \u0432 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0435 \u043e\u0442 1 \u0434\u043e 4096. \u0417\u0430\u043f\u0443\u0441\u043a \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443. \u0427\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0440\u0435\u043f\u0440\u0435\u0437\u0435\u043d\u0442\u0430\u0442\u0438\u0432\u043d\u0443\u044e \u0432\u044b\u0431\u043e\u0440\u043a\u0443, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c 5 \u0442\u0435\u0441\u0442\u043e\u0432 <\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">go.exe test -benchmem -run=^$ -bench ^BenchmarkCalculateFactorial$ github.com\/romapres2010\/goapp\/pkg\/app\/httphandler -count 5 -v<\/code><\/pre>\n<p>  <\/p>\n<p><a href=\"https:\/\/github.com\/romapres2010\/goapp\/blob\/master\/pkg\/app\/httphandler\/handler_wp_test.go\" rel=\"nofollow noopener noreferrer\">BenchmarkCalculateFactorial<\/a><\/p>\n<p>  <\/p>\n<ul>\n<li>\u0421\u043e\u0437\u0434\u0430\u0435\u043c Worker pool service<\/li>\n<li>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c Worker pool service \u0432 \u0444\u043e\u043d\u0435 \u0438 \u0434\u0435\u043b\u0430\u0435\u043c \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u0443\u044e \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0443 \u0434\u043b\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u0446\u0438\u0438 pool<\/li>\n<li>\u0414\u0430\u043b\u0435\u0435 \u0432 \u0446\u0438\u043a\u043b\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043d\u0443\u0436\u043d\u044b\u0439 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u043e\u0442 1 \u0434\u043e 4096 task<\/li>\n<li>\u041e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a Worker pool service<\/li>\n<\/ul>\n<p>  <\/p>\n<pre><code class=\"go\">func BenchmarkCalculateFactorial(b *testing.B) {      \/\/ \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043b\u044f Worker pool service, \u0432\u0441\u0435 timeout \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0432 \u0437\u0430\u0432\u0435\u0434\u043e\u043c\u043e \u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043b\u0438.     var wpServiceCfg = &amp;_wpservice.Config{         TotalTimeout:    100000 * time.Millisecond,         ShutdownTimeout: 30 * time.Second,         WPCfg: _wp.Config{             TaskQueueSize:     0,             TaskTimeout:       20000 * time.Millisecond,             WorkerConcurrency: 4,             WorkerTimeout:     30000 * time.Millisecond,         },     }      var wpService *_wpservice.Service                                           \/\/ \u0441\u0435\u0440\u0432\u0438\u0441 worker pool     var wpServiceErrCh = make(chan error, wpServiceCfg.WPCfg.WorkerConcurrency) \/\/ \u043a\u0430\u043d\u0430\u043b \u043e\u0448\u0438\u0431\u043e\u043a \u0434\u043b\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u0430 worker pool     var err error     var parentCtx = context.Background()      \/\/ \u0421\u043e\u0437\u0434\u0430\u0435\u043c Worker pool service     if wpService, err = _wpservice.New(parentCtx, \"WorkerPool - background\", wpServiceErrCh, wpServiceCfg); err != nil {         return     }      \/\/ \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c Worker pool service \u0432 \u0444\u043e\u043d\u0435 \u0438 \u0434\u0435\u043b\u0430\u0435\u043c \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u0443\u044e \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0443 \u0434\u043b\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u0446\u0438\u0438 pool     go func() { wpServiceErrCh &lt;- wpService.Run() }()     time.Sleep(1 * time.Microsecond)      b.ResetTimer()     for i := 0; i &lt; b.N; i++ {         wpFactorialReqResp := &amp;WpFactorialReqResp{             NumArray: NumArray1024,         }         _ = calculateFactorial(parentCtx, wpService, 0, wpFactorialReqResp, \"bg\", tasks)     }      \/\/ \u041e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a Worker pool service     if err = wpService.Shutdown(false, wpServiceCfg.ShutdownTimeout); err != nil {         _log.ErrorAsInfo(err) \/\/ \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438     } }<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"rezultaty-testirovaniya-dlya-1-task\">\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043b\u044f 1 task<\/h3>\n<p>  <\/p>\n<ol>\n<li>\n<p>\u0422\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c \u043d\u0435\u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 worker pool. \u0411\u0435\u0437 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f sync.Pool \u0438 \u0441 time.After<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">2023-03-05 20:51:23.730300    info    workerpool\/taskpool.go:68    (*Pool).PrintTaskPoolStats() - Usage task pool: countGet, countPut, countNew['993524', '0', '993524'] 2023-03-05 20:51:23.746665    info    workerpool\/taskpool.go:68    (*Pool).PrintTaskPoolStats() - Usage task pool: countGet, countPut, countNew['993624', '0', '993624'] 2023-03-05 20:51:23.881707    info    workerpool\/taskpool.go:68    (*Pool).PrintTaskPoolStats() - Usage task pool: countGet, countPut, countNew['1003624', '0', '1003624'] 2023-03-05 20:51:24.686886    info    workerpool\/taskpool.go:68    (*Pool).PrintTaskPoolStats() - Usage task pool: countGet, countPut, countNew['1095245', '0', '1095245'] 2023-03-05 20:51:25.880455    info    workerpool\/taskpool.go:68    (*Pool).PrintTaskPoolStats() - Usage task pool: countGet, countPut, countNew['1233606', '0', '1233606'] BenchmarkCalculateFactorial-4             138361              8553 ns\/op            1209 B\/op         21 allocs\/op PASS ok      github.com\/romapres2010\/goapp\/pkg\/app\/httphandler       11.171s<\/code><\/pre>\n<p>  <\/li>\n<li>\n<p>\u0422\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 worker pool. \u0412\u043a\u043b\u044e\u0447\u0435\u043d sync.Pool \u0438 \u0441 time.timer<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">2023-03-05 20:59:06.661061    info    workerpool\/taskpool.go:68    (*Pool).PrintTaskPoolStats() - Usage task pool: countGet, countPut, countNew['1026975', '1026975', '26'] 2023-03-05 20:59:06.678355    info    workerpool\/taskpool.go:68    (*Pool).PrintTaskPoolStats() - Usage task pool: countGet, countPut, countNew['1027075', '1027075', '27'] 2023-03-05 20:59:06.863869    info    workerpool\/taskpool.go:68    (*Pool).PrintTaskPoolStats() - Usage task pool: countGet, countPut, countNew['1036025', '1036025', '28'] 2023-03-05 20:59:07.613347    info    workerpool\/taskpool.go:68    (*Pool).PrintTaskPoolStats() - Usage task pool: countGet, countPut, countNew['1130840', '1130840', '30'] 2023-03-05 20:59:08.893377    info    workerpool\/taskpool.go:68    (*Pool).PrintTaskPoolStats() - Usage task pool: countGet, countPut, countNew['1284189', '1284189', '32'] BenchmarkCalculateFactorial-4             153349              8331 ns\/op             464 B\/op         11 allocs\/op PASS<\/code><\/pre>\n<p>  <\/li>\n<\/ol>\n<p>  <\/p>\n<h3 id=\"rezultaty-testirovaniya-dlya-100-task\">\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043b\u044f 100 task<\/h3>\n<p>  <\/p>\n<ol>\n<li>\n<p>\u0422\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c \u043d\u0435\u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 worker pool. \u0411\u0435\u0437 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f sync.Pool \u0438 \u0441 time.After<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">2023-03-05 20:54:31.642079    info    workerpool\/taskpool.go:68    (*Pool).PrintTaskPoolStats() - Usage task pool: countGet, countPut, countNew['3431200', '0', '3431200'] 2023-03-05 20:54:31.706946    info    workerpool\/taskpool.go:68    (*Pool).PrintTaskPoolStats() - Usage task pool: countGet, countPut, countNew['3440400', '0', '3440400'] 2023-03-05 20:54:32.041946    info    workerpool\/taskpool.go:68    (*Pool).PrintTaskPoolStats() - Usage task pool: countGet, countPut, countNew['3618100', '0', '3618100'] 2023-03-05 20:54:33.230567    info    workerpool\/taskpool.go:68    (*Pool).PrintTaskPoolStats() - Usage task pool: countGet, countPut, countNew['4277500', '0', '4277500'] BenchmarkCalculateFactorial-4               6594            179944 ns\/op           80624 B\/op       1308 allocs\/op PASS ok      github.com\/romapres2010\/goapp\/pkg\/app\/httphandler       8.237s<\/code><\/pre>\n<p>  <\/li>\n<li>\n<p>\u0422\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 worker pool. \u0412\u043a\u043b\u044e\u0447\u0435\u043d sync.Pool \u0438 \u0441 time.timer<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">2023-03-05 20:58:13.493850    info    workerpool\/taskpool.go:68    (*Pool).PrintTaskPoolStats() - Usage task pool: countGet, countPut, countNew['5921000', '5921000', '138'] 2023-03-05 20:58:13.513097    info    workerpool\/taskpool.go:68    (*Pool).PrintTaskPoolStats() - Usage task pool: countGet, countPut, countNew['5931000', '5931000', '139'] 2023-03-05 20:58:14.268227    info    workerpool\/taskpool.go:68    (*Pool).PrintTaskPoolStats() - Usage task pool: countGet, countPut, countNew['6591200', '6591200', '144'] 2023-03-05 20:58:15.388267    info    workerpool\/taskpool.go:68    (*Pool).PrintTaskPoolStats() - Usage task pool: countGet, countPut, countNew['7658300', '7658300', '149'] BenchmarkCalculateFactorial-4              10671            103819 ns\/op            6246 B\/op        308 allocs\/op PASS ok      github.com\/romapres2010\/goapp\/pkg\/app\/httphandler       8.513s<\/code><\/pre>\n<p>  <\/li>\n<\/ol>\n<p>  <\/p>\n<h3 id=\"rezultaty-testirovaniya-dlya-1024-task\">\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043b\u044f 1024 task<\/h3>\n<p>  <\/p>\n<ol>\n<li>\n<p>\u0422\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c \u043d\u0435\u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 worker pool. \u0411\u0435\u0437 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f sync.Pool \u0438 \u0441 time.After<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">2023-03-05 20:55:16.861903    info    workerpool\/taskpool.go:68    (*Pool).PrintTaskPoolStats() - Usage task pool: countGet, countPut, countNew['5306368', '0', '5306368'] 2023-03-05 20:55:17.041430    info    workerpool\/taskpool.go:68    (*Pool).PrintTaskPoolStats() - Usage task pool: countGet, countPut, countNew['5374976', '0', '5374976'] 2023-03-05 20:55:17.884380    info    workerpool\/taskpool.go:68    (*Pool).PrintTaskPoolStats() - Usage task pool: countGet, countPut, countNew['5868544', '0', '5868544'] 2023-03-05 20:55:19.021540    info    workerpool\/taskpool.go:68    (*Pool).PrintTaskPoolStats() - Usage task pool: countGet, countPut, countNew['6581248', '0', '6581248'] BenchmarkCalculateFactorial-4                696           1623650 ns\/op          819853 B\/op      13321 allocs\/op PASS ok      github.com\/romapres2010\/goapp\/pkg\/app\/httphandler       11.370s<\/code><\/pre>\n<p>  <\/li>\n<li>\n<p>\u0422\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 worker pool. \u0412\u043a\u043b\u044e\u0447\u0435\u043d sync.Pool \u0438 \u0441 time.timer<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">2023-03-05 20:57:24.753063    info    workerpool\/taskpool.go:68    (*Pool).PrintTaskPoolStats() - Usage task pool: countGet, countPut, countNew['10350592', '10350592', '2080'] 2023-03-05 20:57:24.863404    info    workerpool\/taskpool.go:68    (*Pool).PrintTaskPoolStats() - Usage task pool: countGet, countPut, countNew['10422272', '10422272', '2082'] 2023-03-05 20:57:25.523164    info    workerpool\/taskpool.go:68    (*Pool).PrintTaskPoolStats() - Usage task pool: countGet, countPut, countNew['11227136', '11227136', '2085'] 2023-03-05 20:57:26.738321    info    workerpool\/taskpool.go:68    (*Pool).PrintTaskPoolStats() - Usage task pool: countGet, countPut, countNew['12699648', '12699648', '2089'] BenchmarkCalculateFactorial-4               1438            837543 ns\/op           61221 B\/op       3082 allocs\/op PASS ok      github.com\/romapres2010\/goapp\/pkg\/app\/httphandler       10.800s<\/code><\/pre>\n<p>  <\/li>\n<\/ol>\n<p>  <\/p>\n<h3 id=\"sravnenie-rezultatov\">\u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432<\/h3>\n<p>  <\/p>\n<p>\u0421\u0440\u0430\u0432\u043d\u0438\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0432 \u043f\u0435\u0440\u0435\u0441\u0447\u0435\u0442\u0435 \u043d\u0430 \u043e\u0434\u043d\u0443 task<\/p>\n<p>  <\/p>\n<ol>\n<li>1 task<br \/> \n<ul>\n<li>\u043d\u0435\u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u2014 8553 ns\/op 1209 B\/op 21 allocs\/op<\/li>\n<li>\u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u2014 8331 ns\/op 464 B\/op 11 allocs\/op<\/li>\n<\/ul>\n<\/li>\n<li>100 task<br \/> \n<ul>\n<li>\u043d\u0435\u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u2014 1799 ns\/op 806 B\/op 13 allocs\/op<\/li>\n<li>\u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u2014 1038 ns\/op 62 B\/op 3 allocs\/op<\/li>\n<\/ul>\n<\/li>\n<li>1024 task<br \/> \n<ul>\n<li>\u043d\u0435\u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u2014 1620 ns\/op 810 B\/op 13 allocs\/op<\/li>\n<li>\u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u2014 830 ns\/op 61 B\/op 3 allocs\/op<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p>  <\/p>\n<p>\u041f\u0440\u0438 \u0431\u043e\u043b\u044c\u0448\u043e\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0435 task, \u043c\u0438\u043d\u0438\u043c\u0443\u043c \u0434\u0432\u0443\u0445\u043a\u0440\u0430\u0442\u043d\u044b\u0439 \u0432\u044b\u0438\u0433\u0440\u044b\u0448 \u043f\u043e cpu \u0438 \u0431\u043e\u043b\u0435\u0435 \u0447\u0435\u043c \u0434\u0435\u0441\u044f\u0442\u0438\u043a\u0440\u0430\u0442\u043d\u044b\u0439 \u043f\u043e \u043f\u0430\u043c\u044f\u0442\u0438.<\/p>\n<p>  <\/p>\n<p>\u041e\u0446\u0435\u043d\u0438\u0442\u044c \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u044b TaskPool \u043c\u043e\u0436\u043d\u043e \u043f\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0443 \u0437\u0430\u043f\u0440\u043e\u0448\u0435\u043d\u043d\u044b\u0445 \u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u043e\u0432\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u0445 task.<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0438\u0437 12 699 648 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0431\u044b\u043b\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u043e \u043d\u043e\u0432\u044b\u0445 2089<\/li>\n<li>\u0438\u0437 12 699 648 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432\u0441\u0435 \u0431\u044b\u043b\u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0435\u043d\u044b \u0432 sync.Pool, \u0441\u0431\u043e\u0439\u043d\u044b\u0445 task \u043d\u0435 \u0431\u044b\u043b\u043e<\/li>\n<\/ul>\n<p>  <\/p>\n<pre><code class=\"plaintext\">Usage task pool: countGet, countPut, countNew['12699648', '12699648', '2089']<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"kontrolnyy-vystrel\">\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u044b\u0439 \u0432\u044b\u0441\u0442\u0440\u0435\u043b<\/h3>\n<p>  <\/p>\n<p>\u0421\u0440\u0430\u0432\u043d\u0438\u043c, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u0440\u0430\u0441\u0447\u0435\u0442 \u0441\u0443\u043c\u043c\u044b \u0444\u0430\u043a\u0442\u043e\u0440\u0438\u0430\u043b\u043e\u0432 50! \u0431\u0435\u0437 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f worker pool \u0432 \u043e\u0434\u0438\u043d \u043f\u043e\u0442\u043e\u043a \u0434\u043b\u044f 1024 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">2023-03-05 21:05:40.898732    info    workerpool\/taskpool.go:68    (*Pool).PrintTaskPoolStats() - Usage task pool: countGet, countPut, countNew['0', '0', '0'] 2023-03-05 21:05:40.914259    info    workerpool\/taskpool.go:68    (*Pool).PrintTaskPoolStats() - Usage task pool: countGet, countPut, countNew['0', '0', '0'] 2023-03-05 21:05:41.298531    info    workerpool\/taskpool.go:68    (*Pool).PrintTaskPoolStats() - Usage task pool: countGet, countPut, countNew['0', '0', '0'] 2023-03-05 21:05:42.498569    info    workerpool\/taskpool.go:68    (*Pool).PrintTaskPoolStats() - Usage task pool: countGet, countPut, countNew['0', '0', '0'] BenchmarkCalculateFactorial-4              26288             45514 ns\/op               0 B\/op          0 allocs\/op PASS ok      github.com\/romapres2010\/goapp\/pkg\/app\/httphandler       8.675s<\/code><\/pre>\n<p>  <\/p>\n<p>\u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 worker pool (\u043d\u0430 2 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u044f\u0440\u0430\u0445) \u043e\u0442\u0441\u0442\u0430\u0435\u0442 \u0432 20 \u0440\u0430\u0437 \u043e\u0442 \u043f\u0440\u044f\u043c\u043e\u0433\u043e \u0440\u0430\u0441\u0447\u0435\u0442\u0430 \u0441\u0443\u043c\u043c\u044b \u0444\u0430\u043a\u0442\u043e\u0440\u0438\u0430\u043b\u043e\u0432 \u0432 \u043e\u0434\u0438\u043d \u043f\u043e\u0442\u043e\u043a.<br \/>  \u041d\u0430 6-8 \u044f\u0434\u0440\u0430\u0445 \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u0442\u044c \u0440\u0430\u0437\u0440\u044b\u0432 \u0434\u043e 8-10 \u0440\u0430\u0437, \u0434\u0430\u043b\u044c\u0448\u0435 \u0440\u043e\u0441\u0442 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u044f\u0434\u0435\u0440 \u043d\u0435 \u0441\u0438\u043b\u044c\u043d\u043e \u043f\u043e\u043c\u043e\u0436\u0435\u0442.<\/p>\n<p>  <\/p>\n<p><strong>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 worker pool \u0440\u0430\u0437\u0443\u043c\u043d\u043e \u2014 \u043d\u0435 \u0432\u0435\u0437\u0434\u0435 \u043e\u043d \u043d\u0443\u0436\u0435\u043d<\/strong><\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f task, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0431\u044b\u0441\u0442\u0440\u0435\u0435 200 ns\/op \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 Worker pool \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e. <\/p>\n<p>  <\/p>\n<h2 id=\"8-profilirovanie-worker-pool\">8. \u041f\u0440\u043e\u0444\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 Worker pool<\/h2>\n<p>  <\/p>\n<h3 id=\"obrabotchik-dlya-profilirovaniya\">\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0434\u043b\u044f \u043f\u0440\u043e\u0444\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f<\/h3>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u043f\u0440\u043e\u0444\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u043c \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u044b\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0438 \u0447\u0435\u0433\u043e \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u0442 \u0432 task <\/p>\n<p>  <\/p>\n<pre><code class=\"go\">\/\/ calculateEmpty \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043e\u0446\u0435\u043d\u043a\u0438 \u043d\u0430\u043a\u043b\u0430\u0434\u043d\u044b\u0445 \u0440\u0430\u0441\u0445\u043e\u0434\u043e\u0432 worker pool func calculateEmpty(ctx context.Context, wpService *_wpservice.Service, requestID uint64, wpFactorialReqResp *WpFactorialReqResp, wpTipe string, tasks []*_wp.Task) (err error) {      \/\/ \u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0434\u0430\u0447 \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430     for i, value := range *wpFactorialReqResp.NumArray {         task := _wp.NewTask(ctx, \"\", nil, uint64(i), requestID, -1*time.Second, calculateEmptyFn, value)         tasks = append(tasks, task)     }      \/\/ \u0432 \u043a\u043e\u043d\u0446\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c task \u0432 \u043a\u044d\u0448 \u0434\u043b\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f     defer func() {         for _, task := range tasks {             task.Delete()         }     }()      \/\/ \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0432 \u043e\u0431\u0449\u0438\u0439 background pool     err = wpService.RunTasksGroupWG(requestID, tasks, \"\")      return err }  \/\/ calculateEmpty \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043e\u0446\u0435\u043d\u043a\u0438 \u043d\u0430\u043a\u043b\u0430\u0434\u043d\u044b\u0445 \u0440\u0430\u0441\u0445\u043e\u0434\u043e\u0432 worker pool func calculateEmptyFn(parentCtx context.Context, ctx context.Context, data ...interface{}) (error, []interface{}) {     return nil, nil \/\/ \u0434\u043b\u044f \u043e\u0446\u0435\u043d\u043a\u0438 \u043d\u0430\u043a\u043b\u0430\u0434\u043d\u044b\u0445 \u0440\u0430\u0441\u0445\u043e\u0434\u043e\u0432 \u043d\u0430 Worker pool }<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"rezultat-profilirovaniya\">\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043f\u0440\u043e\u0444\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f<\/h3>\n<p>  <\/p>\n<h4 id=\"rezultat-profilirovaniya-dlya-dlinnyh-task\">\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043f\u0440\u043e\u0444\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043b\u044f &#171;\u0434\u043b\u0438\u043d\u043d\u044b\u0445&#187; task<\/h4>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/03a\/8b6\/039\/03a8b6039a87c0e802c820682296234c.png\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/03a\/8b6\/039\/03a8b6039a87c0e802c820682296234c.png\"\/><\/p>\n<p>  <\/p>\n<p>Memory<\/p>\n<p>  <\/p>\n<ul>\n<li>workerpool.(*Worker).run \u2014 \u043f\u0430\u043c\u044f\u0442\u044c \u043d\u0435 \u0432\u044b\u0434\u0435\u043b\u044f\u043b\u0430\u0441\u044c<\/li>\n<li>workerpool.(*Task).process \u2014 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043e \u043f\u0430\u043c\u044f\u0442\u044c \u0434\u043b\u044f 2042881 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432, \u0432\u0441\u0435\u0433\u043e 33030648 \u0431\u0430\u0439\u0442 \u2014 16 \u0431\u0430\u0439\u0442 \u043d\u0430 \u043e\u0434\u0438\u043d task<br \/>  CPU<\/li>\n<li>workerpool.(*Worker).run \u2014 1480 ns \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445,<br \/> \n<ul>\n<li>\u0447\u0442\u0435\u043d\u0438\u0435 \u043a\u0430\u043d\u0430\u043b\u043e\u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0437\u0430\u0434\u0430\u0447 \u0438 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u2014 350 ns <\/li>\n<\/ul>\n<\/li>\n<li>workerpool.(*Task).process \u2014 1100 ns \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445, <br \/> \n<ul>\n<li>390 ns \u2014 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u0432 \u043a\u0430\u043d\u0430\u043b \u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438-\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0438 \u0442\u0430\u0439\u043c\u0435\u0440\u0430, <\/li>\n<li>140 ns \u2014 \u0437\u0430\u043f\u0443\u0441\u043a \u0444\u0443\u043d\u043a\u0446\u0438\u0438-\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 goroutine<\/li>\n<li>270 ns \u2014 \u0438\u043d\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 &#171;\u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u043c\u0438\u0440\u0430&#187; \u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0438 task \u0432 \u043a\u0430\u043d\u0430\u043b \u043e\u0442\u0432\u0435\u0442\u0430 <\/li>\n<li>130 ns \u2014 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a \u0438 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0442\u0430\u0439\u043c\u0435\u0440\u0430, <\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>  <\/p>\n<h4 id=\"rezultat-profilirovaniya-dlya-korotkih-task\">\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043f\u0440\u043e\u0444\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043b\u044f &#171;\u043a\u043e\u0440\u043e\u0442\u043a\u0438\u0445&#187; task<\/h4>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/post_images\/c10\/0a7\/5ea\/c100a75eaec57700415037adc2c4c3c7.png\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/post_images\/c10\/0a7\/5ea\/c100a75eaec57700415037adc2c4c3c7.png\"\/><\/p>\n<p>  <\/p>\n<p>Memory<\/p>\n<p>  <\/p>\n<ul>\n<li>workerpool.(*Worker).run \u2014 \u043f\u0430\u043c\u044f\u0442\u044c \u043d\u0435 \u0432\u044b\u0434\u0435\u043b\u044f\u043b\u0430\u0441\u044c<\/li>\n<li>workerpool.(*Task).process \u2014 \u043f\u0430\u043c\u044f\u0442\u044c \u043d\u0435 \u0432\u044b\u0434\u0435\u043b\u044f\u043b\u0430\u0441\u044c<br \/>  CPU<\/li>\n<li>workerpool.(*Worker).run \u2014 380 ns \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445,<br \/> \n<ul>\n<li>\u0447\u0442\u0435\u043d\u0438\u0435 \u043a\u0430\u043d\u0430\u043b\u043e\u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0437\u0430\u0434\u0430\u0447 \u0438 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u2014 170 ns <\/li>\n<\/ul>\n<\/li>\n<li>workerpool.(*Task).process \u2014 170 ns \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445,<br \/> \n<ul>\n<li>110 ns \u2014 \u0438\u043d\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 &#171;\u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u043c\u0438\u0440\u0430&#187; \u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0438 task \u0432 \u043a\u0430\u043d\u0430\u043b \u043e\u0442\u0432\u0435\u0442\u0430<\/li>\n<\/ul>\n<\/li>\n<\/ul>\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\/post\/720286\/\"> https:\/\/habr.com\/ru\/post\/720286\/<\/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-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><a href=\"https:\/\/habr.com\/ru\/post\/720286\/\"># \u0428\u0430\u0431\u043b\u043e\u043d backend \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043d\u0430 Golang \u2014 \u0447\u0430\u0441\u0442\u044c 5 \u2014 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f Worker pool<\/a><\/p>\n<p>  <\/p>\n<p><a href=\"https:\/\/habr.com\/ru\/post\/720286\/\">\u041f\u044f\u0442\u0430\u044f \u0447\u0430\u0441\u0442\u044c<\/a> \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u0430 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 Worker pool \u0438 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044f\u043c \u0435\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u044b \u0432 \u0441\u043e\u0441\u0442\u0430\u0432\u0435 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0430, \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u043e\u0433\u043e \u0432 Kubernetes.<\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 Worker pool \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u0434\u0432\u0443\u043c\u044f \u0442\u0438\u043f\u0430\u043c\u0438 \u0437\u0430\u0434\u0430\u0447<\/p>\n<p>  <\/p>\n<ul>\n<li>&#171;\u041a\u043e\u0440\u043e\u0442\u043a\u0438\u0435&#187; \u2014 \u043d\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0435\u0434\u0435\u043b\u044c\u043d\u044b\u0439 timeout \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0438 \u0438\u0445 \u043d\u0435\u043b\u044c\u0437\u044f \u043f\u0440\u0435\u0440\u0432\u0430\u0442\u044c<\/li>\n<li>&#171;\u0414\u043b\u0438\u043d\u043d\u044b\u0435&#187; \u2014 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0435\u0434\u0435\u043b\u044c\u043d\u044b\u0439 timeout \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0438 \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u0440\u0432\u0430\u0442\u044c<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u041d\u0430\u043a\u043b\u0430\u0434\u043d\u044b\u0435 \u0440\u0430\u0441\u0445\u043e\u0434\u044b Worker pool \u043d\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c \u043e\u0447\u0435\u0440\u0435\u0434\u0438, \u0437\u0430\u043f\u0443\u0441\u043a \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 task, \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f task:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0414\u043b\u044f &#171;\u043a\u043e\u0440\u043e\u0442\u043a\u0438\u0445&#187; task \u2014 \u043e\u0442 300 ns\/op, 0 B\/op, 0 allocs\/op<\/li>\n<li>\u0414\u043b\u044f &#171;\u0434\u043b\u0438\u043d\u043d\u044b\u0445&#187; task \u2014 \u043e\u0442 1400 ns\/op, 16 B\/op, 1 allocs\/op<\/li>\n<\/ul>\n<p>  <\/p>\n<p><em>\u0414\u043b\u044f task, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0431\u044b\u0441\u0442\u0440\u0435\u0435 200 ns\/op \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 Worker pool \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e<\/em><\/p>\n<p>  <\/p>\n<p>\u0421\u043e\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043c\u0435\u0442\u0440\u0438\u043a\u0438 <a href=\"https:\/\/prometheus.io\/\" rel=\"nofollow noopener noreferrer\">prometheus<\/a>:<\/p>\n<p>  <\/p>\n<ul>\n<li>wp_worker_process_count_vec \u2014 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e worker \u0432 \u0440\u0430\u0431\u043e\u0442\u0435<\/li>\n<li>wp_task_process_duration_ms_by_name \u2014 \u0433\u0438\u0441\u0442\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f task \u0432 ms \u0441 \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u043e\u0439 \u043f\u043e task.name<\/li>\n<li>wp_task_queue_buffer_len_vec \u2014 \u0442\u0435\u043a\u0443\u0449\u0430\u044f \u0434\u043b\u0438\u043d\u0430 \u043a\u0430\u043d\u0430\u043b\u0430-\u043e\u0447\u0435\u0440\u0435\u0434\u0438 task \u2014 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u043a\u0430\u043d\u0430\u043b\u0430<\/li>\n<li>wp_add_task_wait_count_vec \u2014 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u0434\u0430\u0447, \u043e\u0436\u0438\u0434\u0430\u044e\u0449\u0438\u0445 \u043f\u043e\u043f\u0430\u0434\u0430\u043d\u0438\u044f \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 <a href=\"https:\/\/github.com\/romapres2010\/goapp\" rel=\"nofollow noopener noreferrer\">\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/a>.<\/p>\n<p>  <\/p>\n<p>\u0428\u0430\u0431\u043b\u043e\u043d goapp \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0433\u043e\u0442\u043e\u0432 \u043a \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044e \u0432 Docker, Docker Compose, Kubernetes (kustomize), Kubernetes (helm).<\/p>\n<p>  <\/p>\n<p>\u0421\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u0447\u0430\u0441\u0442\u0438:<\/p>\n<p>  <\/p>\n<ul>\n<li><a href=\"https:\/\/habr.com\/ru\/post\/492062\/\">\u041f\u0435\u0440\u0432\u0430\u044f \u0447\u0430\u0441\u0442\u044c<\/a> \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u0431\u044b\u043b\u0430 \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u0430 HTTP \u0441\u0435\u0440\u0432\u0435\u0440\u0443.<\/li>\n<li><a href=\"https:\/\/habr.com\/ru\/post\/500554\/\">\u0412\u0442\u043e\u0440\u0430\u044f \u0447\u0430\u0441\u0442\u044c<\/a> \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u0431\u044b\u043b\u0430 \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u0430 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e REST API.<\/li>\n<li><a href=\"https:\/\/habr.com\/ru\/post\/716634\/\">\u0422\u0440\u0435\u0442\u044c\u044f \u0447\u0430\u0441\u0442\u044c<\/a> \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u0430 \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044e \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u0432 Docker, Docker Compose, Kubernetes (kustomize).<\/li>\n<li>\u0427\u0435\u0442\u0432\u0435\u0440\u0442\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u0430 \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044e \u0432 Kubernetes \u0441 Helm chart \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 Horizontal Autoscaler.<\/li>\n<\/ul>\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-346318","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/346318","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=346318"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/346318\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=346318"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=346318"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=346318"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}