Utusan. 1. Perkenalan

Salam! Ini adalah artikel singkat yang menjawab pertanyaan: β€œapa itu utusan?”, β€œmengapa diperlukan?” dan "mulai dari mana?".

Apa ini

Envoy adalah penyeimbang L4-L7 yang ditulis dalam C++, berfokus pada performa dan ketersediaan tinggi. Di satu sisi, ini dalam beberapa hal merupakan analog dari nginx dan haproxy, kinerjanya sebanding dengan keduanya. Di sisi lain, ini lebih berorientasi pada arsitektur layanan mikro dan memiliki fungsionalitas yang tidak lebih buruk dari penyeimbang java dan go, seperti zuul atau traefik.

Tabel perbandingan haproxy/nginx/envoy, tidak mengklaim sebagai kebenaran mutlak, tetapi memberikan gambaran umum.

nginx
haproxy
mengirim
traefik.dll

bintang di github
11.2k/cermin
1.1k/cermin
12.4k
27.6k

tertulis di
C
C
C + +
go

API
tidak
soket saja/dorong
bidang data/tarikan
menarik

pemeriksaan kesehatan aktif
tidak
ya
ya
ya

penelusuran terbuka
plugin eksternal
tidak
ya
ya

JWT
plugin eksternal
tidak
ya
tidak

perpanjangan
Lua/C
Lua/C
Lua/C++
tidak

Kenapa

Ini adalah proyek muda, ada banyak hal yang hilang, beberapa di antaranya masih dalam tahap alfa awal. Tetapi mengirim, juga karena usianya yang masih muda, berkembang pesat dan sudah memiliki banyak fitur menarik: konfigurasi dinamis, banyak filter siap pakai, antarmuka sederhana untuk menulis filter Anda sendiri.
Area penerapannya mengikuti ini, tetapi pertama-tama ada 2 antipattern:

  • Mundur statis.

Faktanya adalah saat ini mengirim tidak ada dukungan cache. Orang-orang Google sedang mencoba ini untuk memperbaikinya. Idenya akan diimplementasikan sekali mengirim semua seluk-beluk (header kebun binatang) kepatuhan RFC, dan untuk implementasi spesifik buatlah antarmuka. Tapi untuk saat ini bahkan belum alpha, arsitekturnya sedang dibahas, PR terbuka (saat saya sedang menulis artikel PR, PR terhenti, tetapi poin ini masih relevan).

Untuk saat ini, gunakan nginx untuk statika.

  • Konfigurasi statis.

Anda bisa menggunakannya, tapi mengirim Bukan untuk itu ia diciptakan. Fitur dalam konfigurasi statis tidak akan diekspos. Ada banyak momen:

Saat mengedit konfigurasi di yaml, Anda akan salah, memarahi pengembang karena bertele-tele dan menganggap konfigurasi nginx/haproxy, meskipun kurang terstruktur, lebih ringkas. Itulah intinya. Konfigurasi Nginx dan Haproxy dibuat untuk diedit dengan tangan, dan mengirim untuk generasi dari kode. Seluruh konfigurasi dijelaskan dalam protobuf, menghasilkannya dari file proto jauh lebih sulit untuk membuat kesalahan.

Canary, skenario penerapan b/g, dan banyak lagi biasanya diimplementasikan hanya dalam konfigurasi dinamis. Saya tidak mengatakan bahwa hal ini tidak dapat dilakukan secara statis, kita semua melakukannya. Tetapi untuk ini Anda perlu memakai kruk, di salah satu penyeimbang, di mengirim termasuk.

Tugas yang sangat diperlukan oleh Utusan:

  • Penyeimbangan lalu lintas dalam sistem yang kompleks dan dinamis. Ini termasuk jaring layanan, namun belum tentu merupakan satu-satunya.
  • Kebutuhan akan fungsionalitas penelusuran terdistribusi, otorisasi kompleks, atau fungsi lain yang tersedia di mengirim di luar kotak atau diimplementasikan dengan mudah, tetapi di nginx/haproxy Anda harus dikelilingi oleh lua dan plugin yang meragukan.

Keduanya, bila perlu, memberikan performa tinggi.

Bagaimana itu bekerja

Utusan didistribusikan dalam biner hanya sebagai gambar buruh pelabuhan. Gambar sudah berisi contoh konfigurasi statis. Tapi kami tertarik padanya hanya untuk memahami strukturnya.

konfigurasi statis envoy.yaml

static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address:
        protocol: TCP
        address: 0.0.0.0
        port_value: 10000
    filter_chains:
    - filters:
      - name: envoy.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: local_service
              domains: ["*"]
              routes:
              - match:
                  prefix: "/"
                route:
                  host_rewrite: www.google.com
                  cluster: service_google
          http_filters:
          - name: envoy.router
  clusters:
  - name: service_google
    connect_timeout: 0.25s
    type: LOGICAL_DNS
    # Comment out the following line to test on v6 networks
    dns_lookup_family: V4_ONLY
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: service_google
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: www.google.com
                port_value: 443
    transport_socket:
      name: envoy.transport_sockets.tls
      typed_config:
        "@type": type.googleapis.com/envoy.api.v2.auth.UpstreamTlsContext
        sni: www.google.com

Konfigurasi dinamis

Masalah apa yang kita cari solusinya? Anda tidak bisa begitu saja memuat ulang konfigurasi penyeimbang beban yang sedang dimuat; masalah "kecil" akan muncul:

  • Validasi konfigurasi.

Konfigurasinya bisa besar, bisa sangat besar, jika kita membebani semuanya sekaligus, kemungkinan kesalahan di suatu tempat akan meningkat.

  • Koneksi berumur panjang.

Saat menginisialisasi pendengar baru, Anda perlu menjaga koneksi yang berjalan pada pendengar lama; jika perubahan sering terjadi dan ada koneksi yang berumur panjang, Anda harus mencari kompromi. Halo, kubernet masuknya di nginx.

  • Pemeriksaan kesehatan aktif.

Jika kita memiliki health check yang aktif, kita perlu memeriksa ulang semuanya di konfigurasi baru sebelum mengirimkan lalu lintas. Kalau hulunya banyak, ini butuh waktu. Halo haproxy.

Bagaimana hal ini diselesaikan di mengirimDengan memuat konfigurasi secara dinamis, sesuai dengan model kumpulan, Anda dapat membaginya menjadi beberapa bagian terpisah dan tidak menginisialisasi ulang bagian yang tidak berubah. Misalnya, pendengar, yang mahal untuk diinisialisasi ulang dan jarang diubah.

Konfigurasi mengirim (dari file di atas) memiliki entitas berikut:

  • pendengar β€” pendengar tergantung pada ip/port tertentu
  • tuan rumah virtual - host virtual berdasarkan nama domain
  • rute - aturan penyeimbangan
  • kelompok β€” sekelompok hulu dengan parameter penyeimbang
  • endpoint β€” alamat instans hulu

Masing-masing entitas ini ditambah beberapa entitas lainnya dapat diisi secara dinamis; untuk ini, konfigurasi menentukan alamat layanan dari mana konfigurasi akan diterima. Layanannya bisa berupa REST atau gRPC, lebih disukai gRPC.

Layanan tersebut diberi nama masing-masing: LDS, VHDS, RDS, CDS dan EDS. Anda dapat menggabungkan konfigurasi statis dan dinamis, dengan batasan bahwa sumber daya dinamis tidak dapat ditentukan dalam sumber daya statis.

Untuk sebagian besar tugas, cukup mengimplementasikan tiga layanan terakhir, yang disebut ADS (Aggregated Discovery Service), misalnya Jawa dan lihatlah implementasi bidang data gRPC yang sudah jadi di mana Anda hanya perlu mengisi objek dari sumber Anda.

Konfigurasinya mengambil bentuk berikut:

konfigurasi dinamis envoy.yaml

dynamic_resources:
  ads_config:
    api_type: GRPC
    grpc_services:
      envoy_grpc:
        cluster_name: xds_clr
  cds_config:
    ads: {}
static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address:
        protocol: TCP
        address: 0.0.0.0
        port_value: 10000
    filter_chains:
    - filters:
      - name: envoy.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager
          stat_prefix: ingress_http
          rds:
            route_config_name: local_route
            config_source:
              ads: {}
          http_filters:
          - name: envoy.router
  clusters:
  - name: xds_clr
    connect_timeout: 0.25s
    type: LOGICAL_DNS
    dns_lookup_family: V4_ONLY
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: xds_clr
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: xds
                port_value: 6565

Saat memulai mengirim dengan konfigurasi ini, ia akan terhubung ke bidang kontrol dan mencoba meminta konfigurasi RDS, CDS, dan EDS. Bagaimana proses interaksi terjadi dijelaskan di sini.

Pendeknya, mengirim mengirimkan permintaan yang menunjukkan jenis sumber daya yang diminta, versi dan parameter node. Sebagai tanggapan, ia menerima sumber daya dan versi; jika versi pada bidang kendali tidak berubah, ia tidak merespons.
Ada 4 opsi interaksi:

  • Satu aliran gRPC untuk semua jenis sumber daya, status lengkap sumber daya dikirimkan.
  • Aliran terpisah, kondisi penuh.
  • Satu aliran, status tambahan.
  • Aliran terpisah, status tambahan.

XDS tambahan memungkinkan Anda mengurangi lalu lintas antara bidang kontrol dan mengirim, ini relevan untuk konfigurasi besar. Tapi itu mempersulit interaksi; permintaan tersebut berisi daftar sumber daya untuk berhenti berlangganan dan berlangganan.

Contoh kami menggunakan ADS - satu aliran untuk RDS, CDS, EDS dan mode non-inkremental. Untuk mengaktifkan mode tambahan, Anda perlu menentukan api_type: DELTA_GRPC

Karena permintaan berisi parameter node, kita dapat mengirimkan sumber daya yang berbeda ke bidang kontrol untuk instance yang berbeda mengirim, ini nyaman untuk membangun jaring layanan.

Pemanasan

Pada mengirim saat startup atau saat menerima konfigurasi baru dari bidang kontrol, proses pemanasan sumber daya diluncurkan. Ini dibagi menjadi pemanasan pendengar dan pemanasan cluster. Yang pertama diluncurkan ketika ada perubahan pada RDS/LDS, yang kedua ketika CDS/EDS. Artinya, jika hanya upstream saja yang berubah, maka pendengar tidak akan dibuat ulang.

Selama proses pemanasan, sumber daya yang bergantung diharapkan berasal dari bidang kontrol selama waktu tunggu. Jika batas waktu habis, inisialisasi tidak akan berhasil dan pendengar baru tidak akan mulai mendengarkan pada port.
Urutan inisialisasi: EDS, CDS, pemeriksaan kesehatan aktif, RDS, LDS. Jika health check aktif diaktifkan, lalu lintas akan naik ke hulu hanya setelah satu health check berhasil.

Jika pendengar dibuat ulang, pendengar lama akan masuk ke status DRAIN dan akan dihapus setelah semua koneksi ditutup atau batas waktu berakhir --drain-time-s, default 10 menit.

Untuk dilanjutkan.

Sumber: www.habr.com

Tambah komentar