শূন্য প্যাকেটের ক্ষতির সাথে HAProxy ক্রেফুল রিলোড


42

আমি একাধিক অ্যাপাচি সার্ভারে ভার ভারসাম্য বজায় রাখতে একটি HAProxy লোড ব্যালেন্সিং সার্ভার চালাচ্ছি। লোড ব্যালেন্সিং অ্যালগরিদম পরিবর্তন করতে আমার যে কোনও সময় HAProxy পুনরায় লোড করা দরকার।

এটি সমস্ত ঠিকঠাক কাজ করে, কেবলমাত্র একটি প্যাকেট না হারিয়েই আমাকে সার্ভারটি পুনরায় লোড করতে হবে (এই মুহুর্তে একটি পুনরায় লোড আমাকে প্রতি সেকেন্ডে 5 সেকেন্ডের জন্য 1000 অনুরোধের সাথে গড়ে 99.76% সাফল্য দিচ্ছে)। আমি এটি সম্পর্কে অনেক ঘন্টা গবেষণা করেছি, এবং এইচএপিপ্রক্সি সার্ভারটি "করুণার সাথে পুনরায় লোড করার" জন্য নিম্নলিখিত কমান্ডটি পেয়েছি:

haproxy -D -f /etc/haproxy/haproxy.cfg -p /var/run/haproxy.pid -sf $(cat /var/run/haproxy.pid)

তবে, এটি প্লেইন পুরাতন এর তুলনায় খুব কম বা কোনও প্রভাব ফেলবে না service haproxy reload, এটি এখনও গড়ে 0.24% হ্রাস পাচ্ছে।

কোনও ব্যবহারকারীর একক ড্রপ প্যাকেট ছাড়াই কি HAProxy কনফিগারেশন ফাইলটি পুনরায় লোড করার কোনও উপায় আছে?


6
আপনার যদি এত নির্ভরযোগ্যতার প্রয়োজন হয় তবে এইচএপ্রসিটির একাধিক উদাহরণ চালানো আরও ভাল সমাধান হ'ল যেখানে আপনি কোনওটিকে পুনরায় লোড করার জন্য পরিষেবা থেকে সরিয়ে নিতে পারেন, এটিকে আবার রেখে দিন এবং অন্যের (গুলি) এর জন্য পুনরাবৃত্তি করতে পারেন।
ইউনিক্স

উত্তর:


32

মতে https://github.com/aws/opsworks-cookbooks/pull/40 এবং এর ফলে http://www.mail-archive.com/haproxy@formilux.org/msg06885.html আপনি করতে পারেন:

iptables -I INPUT -p tcp --dport $PORT --syn -j DROP
sleep 1
service haproxy restart
iptables -D INPUT -p tcp --dport $PORT --syn -j DROP

এটি পুনরায় আরম্ভের আগে SYN বাদ দেওয়ার প্রভাব ফেলেছে, যাতে ক্লায়েন্টরা এই এসওয়াইএনটিকে নতুন প্রক্রিয়াতে না পৌঁছানো পর্যন্ত পুনরায় পাঠাবে।



এই উভয় iptables v1.4.14: invalid port/service আদেশই আমাকে এটি দিয়েছে:
দিমিত্রি ডিবি

5
@ দিমিত্রিডিবি আপনার প্রতিস্থাপন $PORTকরার কথা, আসল বন্দরটি haproxyশুনছে। HAProxy একাধিক পোর্ট শোনা হয়, তাহলে লেখার প্রতিস্থাপন --dport $PORTসঙ্গে --dports $PORTS_SEPARATED_BY_COMMAS, যেমন --dports 80,443
পেপলুয়ান

1
iptables 1.4.7 (Centos 6.7) - আপনি যদি -dport ব্যবহার করতে চান তবে আপনাকে -m mulitport নির্দিষ্ট করতে হবে। সুতরাং এর "iptables -I INPUT -p tcp -m মাল্টিপোর্ট - ডিপোর্টস 80,443 - সিন-জে DROP" এবং একইভাবে -D
carpii

25

ইয়েল্প নিখুঁত পরীক্ষার ভিত্তিতে আরও পরিশীলিত পদ্ধতির ভাগ করেছে। ব্লগ নিবন্ধটি একটি গভীর ডুব, এবং এটির পুরোপুরি প্রশংসা করার জন্য সময় বিনিয়োগের পক্ষে উপযুক্ত।

সত্য জিরো ডাউনটাইম HAProxy রিলোডগুলি

টিএল; ডাঃ লিনাক্স টিসি (ট্র্যাফিক নিয়ন্ত্রণ) এবং আইপটবেলগুলি অস্থায়ীভাবে এসওয়াইএন প্যাকেটগুলি সজ্জিত করার জন্য ব্যবহার করে যখন HAProxy পুনরায় লোড হচ্ছে এবং একই পোর্টের সাথে দুটি পিড সংযুক্ত রয়েছে ( SO_REUSEPORT)।

আমি সার্ভারফল্টে পুরো নিবন্ধটি পুনরায় প্রকাশ করতে স্বাচ্ছন্দ্য বোধ করি না; তবুও, আপনার আগ্রহটি চিহ্নিত করার জন্য এখানে কয়েকটি অংশ রয়েছে:

প্রতিটি মেশিনে চালিত আমাদের HAProxy লোড ব্যালান্সারের মধ্যে এসওয়াইএন প্যাকেটগুলি বিলম্ব করে, আমরা HAProxy পুনরায় লোডের সময় ট্র্যাফিককে ন্যূনতমভাবে প্রভাবিত করতে সক্ষম হয়ে থাকি যা আমাদের এসওএর মধ্যে উল্লেখযোগ্যভাবে ব্যবহারকারী ট্র্যাফিককে প্রভাবিত করার আশঙ্কা ছাড়াই আমাদের এসওএর মধ্যে পরিষেবা ব্যাকেন্ডগুলি যুক্ত করতে, অপসারণ করতে এবং পরিবর্তন করতে দেয়।

# plug_manipulation.sh
nl-qdisc-add --dev=lo --parent=1:4 --id=40: --update plug --buffer
service haproxy reload
nl-qdisc-add --dev=lo --parent=1:4 --id=40: --update plug --release-indefinite

# setup_iptables.sh
iptables -t mangle -I OUTPUT -p tcp -s 169.254.255.254 --syn -j MARK --set-mark 1

# setup_qdisc.sh
## Set up the queuing discipline
tc qdisc add dev lo root handle 1: prio bands 4
tc qdisc add dev lo parent 1:1 handle 10: pfifo limit 1000
tc qdisc add dev lo parent 1:2 handle 20: pfifo limit 1000
tc qdisc add dev lo parent 1:3 handle 30: pfifo limit 1000

## Create a plug qdisc with 1 meg of buffer
nl-qdisc-add --dev=lo --parent=1:4 --id=40: plug --limit 1048576
## Release the plug
nl-qdisc-add --dev=lo --parent=1:4 --id=40: --update plug --release-indefinite

## Set up the filter, any packet marked with “1” will be
## directed to the plug
tc filter add dev lo protocol ip parent 1:0 prio 1 handle 1 fw classid 1:4

সংক্ষিপ্তসার: https://gist.github.com/jolyunch/97e3505a1e92e35de2c0

এ জাতীয় আশ্চর্য অন্তর্দৃষ্টি ভাগ করে নেওয়ার জন্য চিপ্স অফ ইয়েল্প।


দুর্দান্ত লিঙ্ক! তবে লিঙ্কটির মেয়াদ শেষ হলে আপনি এখানে সংক্ষেপে বলতে চান। উর্ধ্বে না যাওয়ার একমাত্র কারণ এটি।
ম্যাট

@ ম্যাট কিছু অংশ এবং কোডের নমুনা যুক্ত করেছে
স্টিভ জেনসেন

8

সত্য শূন্য ডাউনটাইম সহ হ্যাপ্রোক্সি পুনরায় লোড করার আরও অনেক সহজ উপায় রয়েছে - এর নাম রাখা হয়েছে iptables flipping (নিবন্ধটি আসলে ইয়েলপ সমাধানে আনবউন্স প্রতিক্রিয়া)। এটি গৃহীত উত্তরের চেয়ে পরিষ্কার, কারণ এমন কোনও প্যাকেট ফেলে দেওয়ার দরকার নেই যা দীর্ঘ পুনরায় লোড নিয়ে সমস্যা তৈরি করতে পারে।

সংক্ষেপে, সমাধান নিম্নলিখিত পদক্ষেপ নিয়ে গঠিত:

  1. আসুন একজোড়া হ্যাপ্রোক্সি উদাহরণ দেওয়া যাক - প্রথম সক্রিয় যা ট্রাফিক গ্রহণ করে এবং দ্বিতীয়টি স্ট্যান্ডবাইতে যা কোনও ট্র্যাফিক গ্রহণ করে না।
  2. আপনি যে কোনও সময় স্ট্যান্ডবাই উদাহরণ পুনরায় কনফিগার (পুনরায় লোড) করুন।
  3. স্ট্যান্ডবাই নতুন কনফিগারেশনের সাথে প্রস্তুত হয়ে গেলে আপনি সমস্ত নতুন সংযোগগুলি স্ট্যান্ডবাই নোডে ডাইভার্ট করে যা নতুন সক্রিয় হয়ে যায় । আনবউশ বাশ স্ক্রিপ্ট সরবরাহ করে যা কয়েকটি সাধারণ iptableকমান্ডের সাথে ফ্লিপ করে
  4. এক মুহুর্তের জন্য আপনার দুটি সক্রিয় উদাহরণ রয়েছে। পুরানো সক্রিয় চালু থাকা সংযোগ বন্ধ না হওয়া পর্যন্ত আপনাকে অপেক্ষা করতে হবে। সময়টি আপনার পরিষেবার আচরণ এবং রাখার জন্য জীবিত সেটিংসের উপর নির্ভর করে।
  5. পুরানো সক্রিয় স্টপগুলিতে ট্র্যাফিক যা নতুন স্ট্যান্ডবাইতে পরিণত হয় - আপনি 1 ধাপে ফিরে এসেছেন।

তবুও সমাধানটি যে কোনও ধরণের পরিষেবায় (এনগিনেক্স, অ্যাপাচি ইত্যাদি) গ্রহণ করা যেতে পারে এবং এটি অনলাইনে যাওয়ার আগে স্ট্যান্ডবাই কনফিগারেশন পরীক্ষা করতে পারায় আরও বেশি ফল্ট সহনীয়।


4

সম্পাদনা করুন: আমার উত্তর এই ধারণাটি তৈরি করে যে কার্নেলটি কেবলমাত্র SO_REUSEPORT দিয়ে খোলার জন্য অতি সাম্প্রতিক বন্দরে ট্র্যাফিক প্রেরণ করে, যেখানে এটি কোনও মন্তব্যে বর্ণিত হিসাবে প্রকৃতপক্ষে সমস্ত প্রক্রিয়াতে ট্র্যাফিক প্রেরণ করে। অন্য কথায়, iptables নৃত্য এখনও প্রয়োজন। :(

আপনি যদি SO_REUSEPORT সমর্থন করে এমন কার্নেলটিতে থাকেন তবে এই সমস্যাটি হওয়া উচিত নয়।

হ্যাপ্রোক্সিটি পুনরায় চালু হওয়ার পরে যে প্রক্রিয়াটি গ্রহণ করে তা হ'ল:

1) বন্দরটি খোলার সময় SO_REUSEPORT সেট করার চেষ্টা করুন ( https://github.com/haproxy/haproxy/blob/3cd0ae963e958d5d5fb838e120f1b0e9361a92f8/src/proto_tcp.c#L792-L798 )

2) বন্দরটি খোলার চেষ্টা করুন (SO_REUSEPORT দিয়ে সফল হবে)

3) যদি এটি সফল না হয়, পুরাতন প্রক্রিয়াটি তার বন্দরটি বন্ধ করতে সিগন্যাল করুন, 10 মিমি অপেক্ষা করুন এবং এটি আবার চেষ্টা করুন। ( https://github.com/haproxy/haproxy/blob/3cd0ae963e958d5d5fb838e120f1b0e9361a92f8/src/haproxy.c#L1554-L1577 )

এটি প্রথমে লিনাক্স 3.9 কার্নেলের সমর্থিত ছিল তবে কিছু ডিস্ট্রো এটির ব্যাকপোর্ট করেছে। উদাহরণস্বরূপ, 2.6.32-417.el6 থেকে EL6 কার্নেলগুলি এটি সমর্থন করে।


এটি SO_REUSEPORTকিছু নির্দিষ্ট পরিস্থিতিতে - বিশেষত ভারী ট্র্যাফিকের আওতায় ঘটবে । যখন এসওয়াইএন পুরানো হ্যাপ্রোক্সি প্রক্রিয়াতে প্রেরণ করা হয় এবং একই মুহুর্তে এটি শোনার সকেট বন্ধ করে দেয় যার ফলস্বরূপ আরএসটি হয়। উপরের অন্যান্য উত্তরে উল্লিখিত ইয়েল্প নিবন্ধটি দেখুন।
জার্মটাস

4
এটি সফল হয় ... কেবলমাত্র সংক্ষিপ্তসারটি জানাতে, লিনাক্স একটি বিশেষ পোর্টে শোনা সমস্ত প্রসেসের মধ্যে নতুন সংযোগ বিতরণ করে যখন SO_REUSEPORT ব্যবহৃত হয় তাই খুব অল্প সময় আছে যেখানে পুরানো প্রক্রিয়াটি এখনও তার সারিটিতে সংযোগ স্থাপন করবে।
জেসন স্টাবস

2

আমি আমার সেটআপটি ব্যাখ্যা করব এবং কীভাবে আমি মনোমুগ্ধকর লোডগুলি সমাধান করেছি:

আমার 2 টি নোড এইচএপ্রক্সি চালিত এবং কিপালাইভড সহ একটি সাধারণ সেটআপ রয়েছে। ইন্টারফেসের ডামি0 ধরে রাখুন, তাই আমি সুইচ ওভারটিকে জোর করে "ifconfig dummy0 ডাউন" করতে পারি।

আসল সমস্যাটি হ'ল, কেন জানি না, একটি "হ্রপোক্সি রিলোড" এখনও সমস্ত ইস্টাব্লিশড সংযোগগুলি ফেলে দেয় :( আমি জের্তা দ্বারা প্রস্তাবিত "iptables ফ্লিপিং" চেষ্টা করেছি, তবে আমি কিছু সমস্যা খুঁজে পেয়েছি কারণ এটি গন্তব্যটিতে একটি NAT সম্পাদন করে আইপি ঠিকানা, যা কিছু পরিস্থিতিতে উপযুক্ত সমাধান নয়।

পরিবর্তে, আমি নতুন সংযোগের প্যাকেটগুলি চিহ্নিত করতে একটি কনমার্কের নোংরা হ্যাক ব্যবহার করার সিদ্ধান্ত নিয়েছি এবং তারপরে চিহ্নিত চিহ্নিত প্যাকেটগুলি অন্য নোডে পুনর্নির্দেশ করব।

এখানে iptables রুলসেট:

iptables -t mangle -A PREROUTING -i eth1 -d 123.123.123.123/32 -m conntrack --ctstate NEW -j CONNMARK --set-mark 1
iptables -t mangle -A PREROUTING -j CONNMARK --restore-mark
iptables -t mangle -A PREROUTING -i eth1 -p tcp --tcp-flags FIN FIN -j MARK --set-mark 2
iptables -t mangle -A PREROUTING -i eth1 -p tcp --tcp-flags RST RST -j MARK --set-mark 2
iptables -t mangle -A PREROUTING -i eth1 -m mark ! --mark 0 -j TEE --gateway 192.168.0.2
iptables -t mangle -A PREROUTING -i eth1 -m mark --mark 1 -j DROP

প্রথম দুটি নিয়ম নতুন প্রবাহের প্যাকেটগুলিকে চিহ্নিত করে (123.123.123.123 হ্রপোক্সিতে সীমান্তগুলি আবদ্ধ করার জন্য ব্যবহৃত রক্ষণশীল ভিআইপি)।

তৃতীয় এবং চতুর্থ নিয়মগুলি প্যাকেটগুলি এফআইএন / আরএসটি প্যাকেটগুলি চিহ্নিত করে। (কেন জানি না, টিইআই লক্ষ্যমাত্রা এফআইএন / আরএসটি প্যাকেটগুলি "উপেক্ষা করে")।

পঞ্চম নিয়ম সমস্ত চিহ্নিত প্যাকেটের নকল অন্য HAproxy (192.168.0.2) এ প্রেরণ করে।

Original ষ্ঠ নিয়মে নতুন প্রবাহের প্যাকেটগুলি তাদের মূল গন্তব্যে পৌঁছনোর জন্য আটকে দেয়।

ইন্টারফেসে বা কার্নেলগুলিতে rp_filter অক্ষম করার কথা মনে রাখবেন সেই মার্টিয়ান প্যাকেটগুলি নামবে।

এবং শেষ কিন্তু শেষ নয়, রিটার্নিং প্যাকেটগুলি মনে রাখবেন! আমার ক্ষেত্রে অসমমিত রাউটিং রয়েছে (অনুরোধ ক্লায়েন্টের কাছে আসে -> haproxy1 -> haproxy2 -> ওয়েবসার্ভার, এবং উত্তরগুলি ওয়েবসভার -> haproxy1 -> ক্লায়েন্ট থেকে আসে) তবে এটি প্রভাবিত করে না। এটা ভাল কাজ করে।

আমি জানি যে সর্বাধিক মার্জিত সমাধানটি হ'ল ডাইভার্টটি করতে আইপ্রউট 2 ব্যবহার করা হবে তবে এটি কেবল প্রথম এসওয়াইএন প্যাকেটের জন্য কাজ করেছিল। এটি যখন এসি (3-ওয়ে হ্যান্ডশেকের তৃতীয় প্যাকেট) পেয়েছে তখন এটি চিহ্নিত করে না :( আমি তদন্ত করতে বেশি সময় ব্যয় করতে পারিনি, আমি যখনই এটি টিই লক্ষ্য নিয়ে কাজ করতে দেখলাম তখনই এটি এটি সেখানে রেখে গেল। অবশ্যই, iproute2 দিয়ে এটি ব্যবহার করে নির্দ্বিধায়

মূলত, "গ্রেফুল লোড" এর মতো কাজ করে:

  1. আমি iptables নিয়মটি সক্ষম করে তাৎক্ষণিকভাবে অন্যান্য এইচএপ্রক্সিতে নতুন সংযোগগুলি দেখতে পাচ্ছি।
  2. "ড্রেনিং" প্রক্রিয়াটি তদারকি করার জন্য আমি "নেটস্ট্যাট-গ্রেট ESTABLISHED | wc -l" তে নজর রাখছি।
  3. একবার মাত্র কয়েকটি (বা শূন্য) সংযোগ হয়ে গেলে, "আইফোনফিগ ডামি0 ডাউন" ব্যর্থ রাখার জন্য রক্ষণশীলকে বাধ্য করতে, যাতে সমস্ত ট্র্যাফিক অন্য এইচএপ্রক্সিতে চলে যায়।
  4. আমি iptables রুলসেটটি সরিয়েছি
  5. (কেবলমাত্র "নন-প্রিম্পটিং" কিপালাইভ কনফিগারেশনের জন্য) "ifconfig ডামি0 আপ"।

আইপেটেবলস রুলসেটটি সহজেই স্টার্ট / স্টপ স্ক্রিপ্টের সাথে সংহত করা যায়:

#!/bin/sh

case $1 in
start)
        echo Redirection for new sessions is enabled

#       echo 0 > /proc/sys/net/ipv4/tcp_fwmark_accept
        for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 0 > $f; done
        iptables -t mangle -A PREROUTING -i eth1 ! -d 123.123.123.123 -m conntrack --ctstate NEW -j CONNMARK --set-mark 1
        iptables -t mangle -A PREROUTING -j CONNMARK --restore-mark
        iptables -t mangle -A PREROUTING -i eth1 -p tcp --tcp-flags FIN FIN -j MARK --set-mark 2
        iptables -t mangle -A PREROUTING -i eth1 -p tcp --tcp-flags RST RST -j MARK --set-mark 2
        iptables -t mangle -A PREROUTING -i eth1 -m mark ! --mark 0 -j TEE --gateway 192.168.0.2
        iptables -t mangle -A PREROUTING -i eth1 -m mark --mark 1 -j DROP
        ;;
stop)
        iptables -t mangle -D PREROUTING -i eth1 -m mark --mark 1 -j DROP
        iptables -t mangle -D PREROUTING -i eth1 -m mark ! --mark 0 -j TEE --gateway 192.168.0.2
        iptables -t mangle -D PREROUTING -i eth1 -p tcp --tcp-flags RST RST -j MARK --set-mark 2
        iptables -t mangle -D PREROUTING -i eth1 -p tcp --tcp-flags FIN FIN -j MARK --set-mark 2
        iptables -t mangle -D PREROUTING -j CONNMARK --restore-mark
        iptables -t mangle -D PREROUTING -i eth1 ! -d 123.123.123.123 -m conntrack --ctstate NEW -j CONNMARK --set-mark 1

        echo Redirection for new sessions is disabled
        ;;
esac
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.