توزیع، هدایت و FailOver ترافیک با پروکسی Apache

منظورم از توزیع همان load balance و از هدایت، ارسال به سرور دلخواه براساس URI و fail over هم به معنی انتقال ترافیک روی سرورهای فعال براساس شرایط و سناریو تعریف شده است.منظور از apache هم در این مقاله وب سرور آپاچه هست.مثلاً اگر طرف زد http://example اولاً بین چند سرور load balance براساس الگوریتم های مختلف انجام شود. ثانیاً اگر زد http://example/foo به server1 یا آرایه load balance1 و اگر زد http://example/bar به server2 یا آرایه load balance2 برود.قبل از هر چیز خدمتتون عرض کنم این موضوع نکات کاربردی و امنیتی زیاد دارد و درصورتیکه خواستید در محیط عملیاتی اجرا کنید حتماً مستندات ماژول ها و موارد مرتبط را مطالعه بفرمایید. من خیلی ساده و سریع سرنخ اصلی موضوع را خدمتتون عرض می کنم اما راه حل ها و دستورات و سناریوهای بسیار متعددی وجود دارند.وب سرور apache اینقدر سوراخ سنبه و جزئیات دارد که فکر نکنم حتی برنامه نویسان خودش کامل بلد باشند.پروکسی درخواست براساس URI با Apache Reverse Proxyدقت کنید ما اینجا از apache بعنوان Reverse Proxy استفاده می کنیم. خود این apache درخواست ها را سرو نمی کند و به بقیه سرورها می فرستد و جواب آن را از سرور مشخص شده باز می گرداند.به شرایطی که پروکسی بین سرور و اینترنت(شبکه خارجه) است Reverse Proxy و به شرایطی که پروکسی بین کلاینت و اینترنت است Forward Proxy می گویند.برای بخش ها و قابلیت های مختلف این ماژول ها باید روی آپاچه شما فعال باشند :proxy_module proxy_http_module proxy_balancer_module lbmethod_bybusyness_module lbmethod_byrequests_module lbmethod_bytraffic_module lbmethod_heartbeat_module headers_moduleالبته اصل کار ما با همان 3تای اول است و چهارتای بعدی مربوط به روش های load balance و آخری مربوط به بازنویسی هدرها است.اینها معمولاً در نصب پیش فرض آپاچه (حداقل روی ردهتی ها) فعال هستند. با دستور httpd -M می توانید ببینید load شده اند یا نه. (اگر نبود سرچ کنید و نصب و فعال نمایید D:) در اینجا من 3 تا سرور دارم:سرور gateway یا bastion با آدرس 192.168.75.152 که خودش چیزی سرو نمی کند و فقط نقش reverse proxy دارد.سرور server1 با آدرس 192.168.122.64 که محتوی server1 را نمایش می دهد.سرور server2 با آدرس 192.168.122.155 که محتوی server2 را نمایش می دهد.این تنظیمات که در ادامه ذکر می شوند روی تنظیمات آپاچه همان سرور gateway پیاده سازی می شوند.اولین دستور proxypass است که بوسیله آن می توانید براحتی تعیین کنید هر URI درخواست از کجا خوانده شود. این دستور را هم در location هم در virtualhost می توانید قرار دهید.در مثال ذیل درخواست های http://192.168.75.152/foo به server1 و http://192.168.75.152/bar به server2 می رود.<location /foo> ProxyPass http://192.168.122.64 </location><location /bar> ProxyPass http://192.168.122.195 </location>نتیجه :با دستور ProxyPass معمولاً ProxyPassReverse را هم استفاده می کنند. reverse اینجا به معنی این نیست که برای ارتباط 2طرفه زنده لازم است حتماً pass و passReverse باشند، به این معنی است که اگر روی سرورهای backend اپلیکیشن یا تنظیماتی مقدار هدر Location: را عوض می کند و آدرس خود را درج می کند، این مقدار با آدرس gateway server عوض شود.بنابراین تقریباً همیشه این 2 دستور را با هم می بینید و تنظیمات بالا به اینصورت می شود:<location /foo> ProxyPass http://192.168.122.64 ProxyPassReverse http://192.168.122.64 </location><location /bar> ProxyPass http://192.168.122.195 ProxyPassReverse http://192.168.122.195 </location>حالا اگر خواستید یک URI داخل یکی از این مسیرهای foo یا bar را مستثنی کنید می توانید از ! در انتهای دستور proxeset و آدرس معرفی شده استفاده نمایید که در مثال های بعدی استفاده شده است.این ساده ترین روش انجام اینکار است.ممکنه مسیرها دینامیک باشند و بخواهید از regex در مسیر معرفی شده استفاده کنید. برای اینکار می توانید از proxypass ~ regex استفاده کنید(یک ~ بعد از proxypass) یا مستقیماً از دستور ProxyPassMatch استفاده نمایید.تنظیمات قبلی را از روی apache سرور gateway پاک می کنم و هر 2 را در یک virtualhost می نویسم که تمیز تر و مفهوم تر باشد. <VirtualHost *:80> ProxyPassMatch ^/foo/(.*)$ http://192.168.122.64/$1 ProxyPassReverse ^/foo/(.*)$ http://192.168.122.64/$1 ProxyPassMatch ^/bar/(.*)$ http://192.168.122.195/$1 ProxyPassReverse ^/bar/(.*)$ http://192.168.122.195/$1 </VirtualHost>این روش مثلاً جایی کاربرد دارد که شما فایل ها یا صفحات یا میکروسرویس هایی روی سرورهای مختلف و حتی داخلی دارید و می خواهید اگر آدرس images/image.jpg/ بود از یک سرور ، اگر files/file.pdf/ بود از یک سرور دیگر یا اگر مثلاً /app1/ بود از یک سرور دیگری جواب را serve کنید.دقت بفرمایید ترافیک کاربر روی آپاچه سرور gateway است و سرورهای backend مستقیماً با کاربر ارتباط ندارند.همین کار را با RewriteRule و فلگ [P] نیز می توانید انجام دهید.RewriteRule &quot^/?images(.*)&quot &quothttp://imageserver.local/images$1&quot [P]فلگ [P] یعنی بصورت پروکسی عمل کن.واقعیت هم اینه در بسیاری از مواقع نوشتن این دستورات با rewrite راحت تر و دقیق تر است. البته بصورت ترکیبی هم می توان استفاده کرد. در مستندات mod_proxy و مستندات مرتبط دستورات دیگر و مثال های خوبی ذکر شده اند که بد نیست ببینید.(منابع بیشتر آخر مقاله)مثلاً اگر همان virtualhost بالا را بخواهیم با RewriteRule بنویسیم بشکل ذیل می شود:<VirtualHost *:80> RewriteEngine On RewriteRule &quot^/?foo/(.*)&quot &quothttp://192.168.122.64/$1&quot [P] ProxyPassReverse ^/foo/(.*)$ http://192.168.122.64/$1 RewriteRule &quot^/?bar/(.*)&quot &quothttp://192.168.122.195/$1&quot [P] ProxyPassReverse ^/bar/(.*)$ http://192.168.122.195/$1 </VirtualHost>همچنین دقت بفرمایید آدرس http://192.168.75.152/foo/boo با /http://192.168.75.152/foo/boo فرق دارد (/ آخر) و اگر در سرور مقصد DirectorySlash آف باشد بجای باز شدن از طریق پروکسی مستقیماً روی آدرس سرور مقصد 301 ریدایرکت می شوید.توزیع ترافیک و Load Balancing و Fail Over با Apacheساده ترین تنظیم بالانسر بشکل ذیل است :<VirtualHost *:80> <Proxy balancer://myset> BalancerMember http://192.168.122.64 BalancerMember http://192.168.122.195 </Proxy> ProxyPass &quot/&quot &quotbalancer://myset/&quot ProxyPassReverse &quot/&quot &quotbalancer://myset/&quot </VirtualHost>در اینحالت اگر آدرس http://192.168.75.152 را بزنم و چندبار refresh کنم یکبار صفحه server1 و یکبار صفحه server2 را خواهم دید. پیش فرض گردشی و نوبتی است.در بخش <proxy> یک بالانسر با نام myset تعریف کرده ایم.سپس سرورهای مختلف عضو را با عبارت BalancerMember مشخص نموده ایم.و در ProxyPass گفته ایم آدرس / که معادل صفحه پیش فرض http://192.168.75.152 است روی myset پروکسی شود.در اینجا روش و الگوریتم balancing را ذکر نکرده ایم و همان پیش فرض است.شما 4 مدل روش و الگوریتم balancing دارید:mod_lbmethod_byrequests (counts requests)mod_lbmethod_bytraffic (totals sizes of requests and responses)mod_lbmethod_bybusyness (Load balancing based on active threads in an connection established with the backend. The backend with the lowest number of threads is given the next request)mod_lbmethod_heartbeat (the backend can even communicate via a heartbeat on th network and use it to inform the reverse proxy whether it has any free capacity)جزئیات و اگوریتم وزن دهی هرکدام مستندات که در پاراگراف بالا لینک شده اند را مطالعه بفرمایید.برای تعریف استفاده از هر کدام از دستور =ProxySet lbmethodباید استفاده بفرمایید که در مثال بعدی استفاده شده است.همچنین می توانید در تنظیمات تعریف کنید یک اینترفیس وب داخلی برای بالانسر به آدرس balancer-manager در اختیار شما قرار بگیرد.تنظیمات بالا به همراه بالانسرمنیجر بشکل ذیل می شود:<VirtualHost *:80> ProxyRequests off <Proxy balancer://myset> BalancerMember http://192.168.122.64 BalancerMember http://192.168.122.195 ProxySet lbmethod=bytraffic </Proxy> <Location /balancer-manager> SetHandler balancer-manager </Location> ProxyPass /balancer-manager ! ProxyPass &quot/&quot &quotbalancer://myset/&quot ProxyPassReverse &quot/&quot &quotbalancer://myset/&quot <VirtualHost>در این حالت هر بار که صفحه را refresh کنیم از یکی از سرورهای آرایه پاسخ خواهیم گرفت و آدرس http://192.168.75.152/balancer-manager هم صفحه وب بالانسر منیجر را باز می کند.یک دستور ProxyRequests off را هم بالا اضافه کردم تا فقط همین شرایط تعریف شده پروکسی شوند و هرکس نتواند از پروکسی ما استفاده خودش را بکند. مجدداً تاکید می کنم این موضوع نکات امنیتی زیاد دارد که باید تحقیق و رعایت بفرمایید.بالانسر آپاچه قابلیت stickyness دارد. یعنی یک کلاینتی که درخواستش به یک سرور وصل شده بقیه را هم با همان سرور ادامه دهد. این قابلیت در اپلیکیشن های تعاملی کاربرد دارد. برای تنظیم کوکی ها و سشن های کاربر با سرور backend هم گزینه ها و دستوراتی هست که در مستندات mod_proxy مطالعه بفرمایید.تنظیمات کامل شده apache load balancer بالا بشرح ذیل می شود :<VirtualHost *:80> ProxyRequests Off ProxyPreserveHost On Header add Set-Cookie &quotROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/&quot env=BALANCER_ROUTE_CHANGED <Proxy balancer://mycluster> BalancerMember http://192.168.122.64 route=1 BalancerMember http://192.168.122.195 route=2 ProxySet lbmethod=byrequests ProxySet stickysession=ROUTEID </Proxy> <Location /balancer-manager> SetHandler balancer-manager </Location> ProxyPass /balancer-manager ! ProxyPass / balancer://mycluster/ ProxyPassReverse / balancer://mycluster/ ErrorLog ${APACHE_LOG_DIR}/proxy-error.log CustomLog ${APACHE_LOG_DIR}/proxy-access.log combined </VirtualHost>اعضای بالانسر (و خود بالانسر) پارامترهای مختلفی را می گیرند که بوسیله آن ها می توانید سناریوهای پیچیده failover را پیاده سازی کنید. مثلاً در مثال ذیل اگر www2 و/یا www3 در دسترس نباشند ترافیک به spare1 و spare2 ارسال خواهد شد ، تنها درصورتی ترافیک به hstandby ارسال خواهد شد که همه بقیه از دسترس خارج شده باشند. اینها balancer set 0 (تعریف نشده بصورت پیش فرض 0 است.) هستند. می توانیم balancer setهای دیگری هم تعریف کنیم. مثلاً اینجا اگر همه اعضای balancer set 0 از دسترس خارج شده باشند، ترافیک به bkup1 و bkup2 که در set 1 هستند ارسال می شود.<Proxy balancer://myset> BalancerMember http://www2.example.com:8080 BalancerMember http://www3.example.com:8080 loadfactor=3 timeout=1 BalancerMember http://spare1.example.com:8080 status=+R BalancerMember http://spare2.example.com:8080 status=+R BalancerMember http://hstandby.example.com:8080 status=+H BalancerMember http://bkup1.example.com:8080 lbset=1 BalancerMember http://bkup2.example.com:8080 lbset=1 ProxySet lbmethod=byrequests </Proxy> ProxyPass &quot/&quot &quotbalancer://myset/&quot ProxyPassReverse &quot/&quot &quotbalancer://myset/&quotعبارت loadfactor بین 1 تا 100است که وزن عضو را در آرایه مشخص می کند.(مستندات mod_proxy را برای جزئیات محاسبه ببینید.)عبارت timeout و connectiontimeout براساس ثانیه تعیین می کند gateway server چقدر منتظر جواب گرفتن از آن عضو آرایه یا برقراری ارتباط با آن بماند.عبارت status یعنی وضعیت سرور back-end که مقادیر ذیل را می گیرد :عبارت lbset هم به دسته بندی و set ممبرها اشاره می کند.در نظر داشته باشید آپاچه بسیار محبوب و قدرتمند است اما HAProxy و ابزارها و دستگاه های تخصصی مشابه نیست! هر چند شاید بتوانید سناریوهای متعدد و حتی پیچیده ای را با پرفورمنس خوب روی apache پیاده سازی کنید.و مجدداً تاکید می کنم برای استفاده در محیط عملیاتی راهنماها را کامل مطالعه بفرمایید و ابتدا پیاده سازی و ترجیحاً با CURL تست کنید.منابع بیشتر برای مطالعه :Apache Reverse Proxy GuideApache Module mod_proxyApache Module mod_proxy_balancerApache Url Mapping