Βελτιστοποίηση Linux για τη διαχείριση 1.2 εκατομμυρίων αιτημάτων JSON ανά δευτερόλεπτο

Ένας λεπτομερής οδηγός έχει δημοσιευτεί σχετικά με τον συντονισμό του περιβάλλοντος Linux για την επίτευξη μέγιστης απόδοσης για την επεξεργασία αιτημάτων HTTP. Οι προτεινόμενες μέθοδοι κατέστησαν δυνατή την αύξηση της απόδοσης του επεξεργαστή JSON με βάση τη βιβλιοθήκη libreactor στο περιβάλλον Amazon EC2 (4 vCPU) από 224 χιλιάδες αιτήματα API ανά δευτερόλεπτο με τυπικές ρυθμίσεις του Amazon Linux 2 με πυρήνα 4.14 σε 1.2 εκατομμύρια αιτήματα ανά δεύτερο μετά τη βελτιστοποίηση (αύξηση 436%), και οδήγησε επίσης σε μείωση των καθυστερήσεων στην επεξεργασία αιτημάτων κατά 79%. Οι προτεινόμενες μέθοδοι δεν είναι συγκεκριμένες για το libreactor και λειτουργούν κατά τη χρήση άλλων διακομιστών http, συμπεριλαμβανομένων των nginx, Actix, Netty και Node.js (το libreactor χρησιμοποιήθηκε σε δοκιμές επειδή η λύση που βασίστηκε σε αυτό έδειξε καλύτερη απόδοση).

Βελτιστοποίηση Linux για τη διαχείριση 1.2 εκατομμυρίων αιτημάτων JSON ανά δευτερόλεπτο

Βασικές βελτιστοποιήσεις:

  • Βελτιστοποίηση κώδικα απελευθερωτή. Ως βάση χρησιμοποιήθηκε η επιλογή R18 από το κιτ Techempower, η οποία βελτιώθηκε με την αφαίρεση του κώδικα για τον περιορισμό του αριθμού των χρησιμοποιούμενων πυρήνων της CPU (η βελτιστοποίηση επέτρεψε την επιτάχυνση της εργασίας κατά 25-27%), η συναρμολόγηση στο GCC με τις επιλογές "-O3" (αύξηση 5-10% ) και "-march-native" (5-10%), αντικαθιστώντας τις κλήσεις ανάγνωσης/εγγραφής με recv/send (5-10%) και μειώνοντας τα γενικά έξοδα κατά τη χρήση threads (2-3%) . Η συνολική αύξηση της απόδοσης μετά τη βελτιστοποίηση κώδικα ήταν 55%, και η απόδοση αυξήθηκε από 224k req/s σε 347k req/s.
  • Απενεργοποιήστε την προστασία από κερδοσκοπικές ευπάθειες εκτέλεσης. Η χρήση των παραμέτρων "nospectre_v1 nospectre_v2 pti=off mds=off tsx_async_abort=off" κατά τη φόρτωση του πυρήνα επέτρεψε την αύξηση της απόδοσης κατά 28%, και η απόδοση αυξήθηκε από 347k req/s σε 446k req/s. Ξεχωριστά, η αύξηση από την παράμετρο "nospectre_v1" (προστασία από Spectre v1 + SWAPGS) ήταν 1-2%, "nospectre_v2" (προστασία από Spectre v2) - 15-20%, "pti=off" (Spectre v3/Meltdown) - 6 %, "mds=off tsx_async_abort=off" (MDS/Zombieload και TSX Asynchronous Abort) - 6%. Οι ρυθμίσεις για προστασία από επιθέσεις L1TF/Foreshadow (l1tf=flush), iTLB multihit, Speculative Store Bypass και SRBDS παρέμειναν αμετάβλητες, οι οποίες δεν επηρέασαν την απόδοση καθώς δεν διασταυρώθηκαν με τη δοκιμασμένη διαμόρφωση (για παράδειγμα, ειδικά για KVM, ένθετα εικονικοποίηση και άλλα μοντέλα CPU).
  • Απενεργοποίηση ελέγχου και μηχανισμών αποκλεισμού κλήσεων συστήματος χρησιμοποιώντας την εντολή "auditctl -a never,task" και καθορίζοντας την επιλογή "--security-opt seccomp=unconfined" κατά την εκκίνηση του κοντέινερ docker. Η συνολική αύξηση της απόδοσης ήταν 11%, και η απόδοση αυξήθηκε από 446k req/s σε 495k req/s.
  • Απενεργοποίηση iptables/netfilter με ξεφόρτωση των συσχετισμένων λειτουργικών μονάδων πυρήνα. Η ιδέα να απενεργοποιηθεί το τείχος προστασίας, το οποίο δεν χρησιμοποιήθηκε σε μια συγκεκριμένη λύση διακομιστή, προκλήθηκε από τα αποτελέσματα δημιουργίας προφίλ, κρίνοντας από τα οποία η συνάρτηση nf_hook_slow χρειάστηκε το 18% του χρόνου για να εκτελεστεί. Σημειώνεται ότι το nftables λειτουργεί πιο αποτελεσματικά από το iptables, αλλά το Amazon Linux συνεχίζει να χρησιμοποιεί iptables. Μετά την απενεργοποίηση των iptables, η αύξηση της απόδοσης ήταν 22%, και η απόδοση αυξήθηκε από 495k req/s σε 603k req/s.
  • Μειωμένη μετανάστευση των εργαλείων χειρισμού μεταξύ διαφορετικών πυρήνων CPU για τη βελτίωση της αποτελεσματικότητας της χρήσης της κρυφής μνήμης επεξεργαστή. Η βελτιστοποίηση πραγματοποιήθηκε τόσο σε επίπεδο δέσμευσης διεργασιών απελευθερωτή σε πυρήνες CPU (CPU Pinning) όσο και μέσω καρφίτσωσης χειριστών δικτύου πυρήνα (Receive Side Scaling). Για παράδειγμα, το irqbalance απενεργοποιήθηκε και η συνάφεια ουράς με την CPU ορίστηκε ρητά στο /proc/irq/$IRQ/smp_affinity_list. Για τη χρήση του ίδιου πυρήνα CPU για την επεξεργασία της διαδικασίας libreactor και της ουράς δικτύου των εισερχόμενων πακέτων, χρησιμοποιείται ένας προσαρμοσμένος χειριστής BPF, ο οποίος συνδέεται ορίζοντας τη σημαία SO_ATTACH_REUSEPORT_CBPF κατά τη δημιουργία της υποδοχής. Για τη σύνδεση ουρών εξερχόμενων πακέτων στην CPU, οι ρυθμίσεις /sys/class/net/eth0/queues/tx- έχουν αλλάξει /xps_cpus. Η συνολική αύξηση της απόδοσης ήταν 38%, και η απόδοση αυξήθηκε από 603k req/s σε 834k req/s.
  • Βελτιστοποίηση χειρισμού διακοπών και χρήσης ψηφοφορίας. Η ενεργοποίηση της λειτουργίας adaptive-rx στο πρόγραμμα οδήγησης ENA και ο χειρισμός του sysctl net.core.busy_read αύξησε την απόδοση κατά 28% (η απόδοση αυξήθηκε από 834k req/s σε 1.06M req/s και ο λανθάνοντας χρόνος μειώθηκε από 361μs σε 292μs).
  • Απενεργοποίηση υπηρεσιών συστήματος που οδηγούν σε περιττό αποκλεισμό στη στοίβα δικτύου. Η απενεργοποίηση του dhclient και η μη αυτόματη ρύθμιση της διεύθυνσης IP οδήγησε σε αύξηση της απόδοσης κατά 6% και αύξηση της απόδοσης από 1.06M req/s σε 1.12M req/s. Ο λόγος που το dhclient επηρεάζει την απόδοση είναι στην ανάλυση κυκλοφορίας χρησιμοποιώντας μια ακατέργαστη πρίζα.
  • Fighting Spin Lock. Η εναλλαγή της στοίβας δικτύου σε λειτουργία "noqueue" μέσω sysctl "net.core.default_qdisc=noqueue" και "tc qdisc αντικαταστήσει dev eth0 root mq" οδήγησε σε αύξηση απόδοσης 2% και η απόδοση αυξήθηκε από 1.12M req/s σε 1.15M απαιτ.
  • Τελικές μικρές βελτιστοποιήσεις, όπως η απενεργοποίηση του GRO (Generic Receive Offload) με την εντολή "ethtool -K eth0 gro off" και η αντικατάσταση του κυβικού αλγόριθμου ελέγχου συμφόρησης με reno χρησιμοποιώντας sysctl "net.ipv4.tcp_congestion_control=reno". Η συνολική αύξηση της παραγωγικότητας ήταν 4%. Η απόδοση αυξήθηκε από 1.15M req/s σε 1.2M req/s.

Εκτός από τις βελτιστοποιήσεις που λειτούργησαν, το άρθρο εξετάζει επίσης μεθόδους που δεν οδήγησαν στην αναμενόμενη αύξηση της απόδοσης. Για παράδειγμα, τα ακόλουθα αποδείχθηκαν αναποτελεσματικά:

  • Η λειτουργία του libreactor ξεχωριστά δεν διέφερε ως προς την απόδοση από τη λειτουργία του σε ένα κοντέινερ. Η αντικατάσταση του writev με αποστολή, η αύξηση των maxevents στο epoll_wait και ο πειραματισμός με εκδόσεις και σημαίες GCC δεν είχαν κανένα αποτέλεσμα (το αποτέλεσμα ήταν αισθητό μόνο για τις σημαίες "-O3" και "-march-native").
  • Αναβάθμιση του πυρήνα Linux στις εκδόσεις 4.19 και 5.4, χρησιμοποιώντας τους προγραμματιστές SCHED_FIFO και SCHED_RR, χειρισμός sysctl kernel.sched_min_granularity_ns, kernel.sched_wakeup_granularity_ns, transparent_hugepages=never, skew_tick=1 και c δεν επηρέασε την απόδοση.
  • Στο πρόγραμμα οδήγησης ENA, η ενεργοποίηση των λειτουργιών Offload (τμηματοποίηση, scatter-gather, rx/tx checksum), η δημιουργία με τη σημαία "-O3" και η χρήση των παραμέτρων ena.rx_queue_size και ena.force_large_llq_header δεν είχαν κανένα αποτέλεσμα.
  • Οι αλλαγές στη στοίβα δικτύου δεν βελτίωσαν την απόδοση:
    • Απενεργοποίηση IPv6: ipv6.disable=1
    • Απενεργοποίηση VLAN: modprobe -rv 8021q
    • Απενεργοποιήστε τον έλεγχο προέλευσης πακέτου
      • net.ipv4.conf.all.rp_filter=0
      • net.ipv4.conf.eth0.rp_filter=0
      • net.ipv4.conf.all.accept_local=1 (αρνητικό αποτέλεσμα)
    • net.ipv4.tcp_sack = 0
    • net.ipv4.tcp_dsack=0
    • net.ipv4.tcp_mem/tcp_wmem/tcp_rmem
    • net.core.netdev_budget
    • net.core.dev_weight
    • net.core.netdev_max_backlog
    • net.ipv4.tcp_slow_start_after_idle=0
    • net.ipv4.tcp_moderate_rcvbuf=0
    • net.ipv4.tcp_timestamps=0
    • net.ipv4.tcp_low_latency = 1
    • SO_PRIORITY
    • TCP_NODELAY

    Πηγή: opennet.ru

Προσθέστε ένα σχόλιο