له نګینکس څخه انوی پراکسي ته مهاجرت

سلام، حبر! زه ستاسو پام ته د پوسټ ژباړه راوړم: له نګینکس څخه انوی پراکسي ته مهاجرت.

Envoy د لوړ فعالیت توزیع شوی پراکسي سرور دی (په C++ کې لیکل شوی) د انفرادي خدماتو او غوښتنلیکونو لپاره ډیزاین شوی، دا د مخابراتو بس او "د یونیورسل ډیټا الوتکه" هم ده چې د لوی مایکرو سرویس "خدمت میش" معمارۍ لپاره ډیزاین شوی. کله چې د دې رامینځته کول ، د سرورونو د پراختیا په جریان کې رامینځته شوي ستونزو حلونه لکه NGINX ، HAProxy ، د هارډویر بار بیلنسران او د کلاوډ بار بیلنسران په پام کې نیول شوي. سفیر د هر غوښتنلیک تر څنګ کار کوي او شبکه خلاصوي ترڅو د پلیټ فارم په پام کې نیولو پرته عام فعالیت چمتو کړي. کله چې په زیربنا کې ټول خدماتي ترافیک د انوی میش له لارې تیریږي ، نو دا اسانه کیږي چې د دوامداره مشاهدې سره د ستونزې ساحې لیدل ، د عمومي فعالیت سره سمون ، او په ځانګړي ځای کې اصلي فعالیت اضافه کړئ.

ځانګړتیاوې

  • د پروسې څخه بهر جوړښت: سفیر یو ځان لرونکی، د لوړ فعالیت سرور دی چې لږ مقدار رام اخلي. دا د هرې غوښتنلیک ژبې یا چوکاټ سره په ګډه کار کوي.
  • د http/2 او grpc ملاتړ: سفیر د راتلونکو او وتلو اړیکو لپاره د لومړي درجې http/2 او grpc ملاتړ لري. دا له http/1.1 څخه تر http/2 پورې شفاف پراکسي ده.
  • پرمختللی بار بیلانس: سفیر د پرمختللي بار توازن کولو ځانګړتیاو ملاتړ کوي پشمول د اتوماتیک بیاکتنې ، زنځیر ماتول ، د نړیوال نرخ محدودیت ، د سیوري غوښتنه کول ، د محلي زون بار بار توازن او نور.
  • د تنظیم مدیریت API: سفیر ستاسو د تنظیم کولو په متحرک ډول اداره کولو لپاره قوي API چمتو کوي.
  • د لید وړتیا: د L7 ترافیک ژور مشاهده ، د توزیع شوي تعقیب لپاره اصلي ملاتړ او د مونګوډب ، ډینامډب او ډیری نورو غوښتنلیکونو مشاهده.

1 ګام - د NGINX ترتیب بیلګه

دا سکریپټ په ځانګړي ډول جوړ شوی فایل کاروي nginx.confد بشپړ مثال په اساس NGINX ويکي. تاسو کولی شئ په پرانیستلو سره په مدیر کې ترتیب وګورئ nginx.conf

د nginx سرچینې ترتیب

user  www www;
pid /var/run/nginx.pid;
worker_processes  2;

events {
  worker_connections   2000;
}

http {
  gzip on;
  gzip_min_length  1100;
  gzip_buffers     4 8k;
  gzip_types       text/plain;

  log_format main      '$remote_addr - $remote_user [$time_local]  '
    '"$request" $status $bytes_sent '
    '"$http_referer" "$http_user_agent" '
    '"$gzip_ratio"';

  log_format download  '$remote_addr - $remote_user [$time_local]  '
    '"$request" $status $bytes_sent '
    '"$http_referer" "$http_user_agent" '
    '"$http_range" "$sent_http_content_range"';

  upstream targetCluster {
    172.18.0.3:80;
    172.18.0.4:80;
  }

  server {
    listen        8080;
    server_name   one.example.com  www.one.example.com;

    access_log   /var/log/nginx.access_log  main;
    error_log  /var/log/nginx.error_log  info;

    location / {
      proxy_pass         http://targetCluster/;
      proxy_redirect     off;

      proxy_set_header   Host             $host;
      proxy_set_header   X-Real-IP        $remote_addr;
    }
  }
}

د NGINX تشکیلات عموما درې کلیدي عناصر لري:

  1. د NGINX سرور ترتیب کول، د لاګ جوړښت او د Gzip فعالیت. دا په ټولو قضیو کې په نړیواله کچه تعریف شوی.
  2. کوربه ته د غوښتنې منلو لپاره د NGINX تنظیم کول one.example.com په 8080 بندر کې.
  3. د هدف ځای ترتیب کول، د URL مختلفو برخو لپاره د ټرافیک اداره کولو څرنګوالی.

ټول تشکیلات به په Envoy پراکسي کې نه پلي کیږي، او تاسو اړتیا نلرئ ځینې ترتیبات تنظیم کړئ. سفیر پراکسي لري څلور کلیدي ډولونه، کوم چې د NGINX لخوا وړاندیز شوي اصلي زیربنا ملاتړ کوي. اصلي خبره دا ده:

  • اوریدونکي: دوی ټاکي چې څنګه د سفیر پراکسي راتلونکي غوښتنې مني. Envoy Proxy اوس مهال یوازې د TCP پر بنسټ د اوریدونکو ملاتړ کوي. یوځل چې اړیکه جوړه شي ، دا د پروسس لپاره د فلټرونو سیټ ته لیږدول کیږي.
  • فلټرونه: دوی د پایپ لاین جوړښت برخه ده چې کولی شي د راتلوونکي او وتلو ډیټا پروسس کړي. پدې فعالیت کې فلټرونه شامل دي لکه Gzip، کوم چې پیرودونکي ته د لیږلو دمخه ډاټا کمپریس کوي.
  • راوټر: دوی اړین منزل ته ټرافيک وړاندې کوي، د کلستر په توګه تعریف شوي.
  • کلسترونه: دوی د ترافیک او ترتیب کولو پیرامیټونو لپاره پای ټکی تعریفوي.

موږ به دا څلور برخې وکاروو ترڅو د ځانګړي NGINX تشکیلاتو سره سمون لپاره د استازي پراکسي ترتیب رامینځته کړي. د استازي هدف د APIs او متحرک ترتیب سره کار کول دي. په دې حالت کې، د بنسټ ترتیب به د NGINX څخه جامد، سخت کوډ شوي ترتیبات وکاروي.

مرحله 2 - د NGINX ترتیب

لومړۍ برخه nginx.conf ځینې ​​​​NGINX داخلي تعریفوي چې تنظیم کولو ته اړتیا لري.

د کارګر اړیکې

لاندې ترتیب د کارګر پروسو او ارتباطاتو شمیر ټاکي. دا په ګوته کوي چې NGINX به د غوښتنې پوره کولو لپاره اندازه کړي.

worker_processes  2;

events {
  worker_connections   2000;
}

Envoy Proxy د کار جریان او اړیکې په بیلابیلو لارو اداره کوي.

سفیر په سیسټم کې د هر هارډویر تار لپاره کارګر تار جوړوي. د هر کارګر تار د غیر بلاک کولو پیښې لوپ اجرا کوي چې مسؤلیت لري

  1. د هر اوریدونکي غوږ نیسي
  2. د نویو اړیکو منل
  3. د اړیکې لپاره د فلټرونو سیټ رامینځته کول
  4. د پیوستون د ژوند په جریان کې ټول I/O عملیات پروسس کړئ.

د ارتباط ټول نور پروسس کول په بشپړ ډول د کارګر تار کې اداره کیږي ، پشمول د هر ډول لیږلو چلند.

په سفیر کې د هر کارګر تار لپاره، د ارتباط حوض شتون لري. نو د HTTP/2 اتصال حوضونه په یو وخت کې په هر بهرني کوربه کې یوازې یو پیوستون رامینځته کوي ، که چیرې څلور کارګر تارونه شتون ولري نو په مستحکم حالت کې به په هر بهرني کوربه کې څلور HTTP/2 اړیکې وي. په یوه کارګر تار کې د هرڅه په ساتلو سره، نږدې ټول کوډونه پرته له بندولو لیکل کیدی شي، لکه څنګه چې دا یو واحد تار دی. که چیرې د اړتیا په پرتله ډیر کارګر تارونه تخصیص شي ، نو دا کولی شي د حافظې ضایع کیدو لامل شي ، د ډیری بې کاره اړیکو رامینځته کول ، او د هغه وخت کمول چې اړیکې بیرته پول ته راستانه کیږي.

د نورو معلوماتو لپاره لیدنه وکړئ د سفیر پراکسي بلاګ.

د HTTP ترتیب

لاندې د NGINX ترتیب کولو بلاک د HTTP تنظیمات تعریفوي لکه:

  • کوم مایم ډولونه ملاتړ کیږي
  • ډیفالټ مهال ویش
  • د Gzip ترتیب

تاسو کولی شئ دا اړخونه په Envoy Proxy کې د فلټرونو په کارولو سره تنظیم کړئ، کوم چې موږ به وروسته بحث وکړو.

3 ګام - د سرور ترتیب

د HTTP ترتیب کولو بلاک کې، د NGINX ترتیب په 8080 پورټ کې اوریدلو لپاره مشخص کوي او د ډومینونو لپاره راتلونکو غوښتنو ته ځواب ووایی one.example.com и www.one.example.com.

 server {
    listen        8080;
    server_name   one.example.com  www.one.example.com;

د استازي دننه، دا د اوریدونکو لخوا کنټرول کیږي.

درنو اوریدونکو

د Envoy Proxy سره د پیل کولو ترټولو مهم اړخ ستاسو د اوریدونکو تعریف کول دي. تاسو اړتیا لرئ د ترتیب کولو فایل رامینځته کړئ چې دا تشریح کوي چې تاسو څنګه د انوی مثال چلول غواړئ.

لاندې برخه به یو نوی اوریدونکی رامینځته کړي او دا به 8080 پورټ سره وتړي. تشکیلات Envoy پراکسي ته وايي چې کوم بندرونه باید د راتلونکو غوښتنو لپاره تړلي وي.

Envoy Proxy د خپل ترتیب لپاره د YAML نوټیشن کاروي. د دې یادښت د پیژندنې لپاره، دلته وګورئ لینک.

Copy to Editorstatic_resources:
  listeners:
  - name: listener_0
    address:
      socket_address: { address: 0.0.0.0, port_value: 8080 }

تعریف ته اړتیا نشته server_name، ځکه چې د انوی پراکسي فلټرونه به دا اداره کړي.

4 ګام - د ځای ترتیب

کله چې غوښتنه په NGINX کې راځي، د موقعیت بلاک ټاکي چې څنګه پروسس شي او چیرته ټرافيک ته لاره ومومي. په لاندې برخه کې، سایټ ته ټول ټرافیک اپ سټریم ته لیږدول کیږي (د ژباړونکي یادونه: اپ سټریم معمولا د اپلیکیشن سرور دی) نومول شوی کلستر هدف کلستر. پورته کلستر نوډونه تعریفوي چې غوښتنه باید پروسس کړي. موږ به په راتلونکي مرحله کې پدې اړه بحث وکړو.

location / {
    proxy_pass         http://targetCluster/;
    proxy_redirect     off;

    proxy_set_header   Host             $host;
    proxy_set_header   X-Real-IP        $remote_addr;
}

په سفیر کې، فلټرونه دا کار کوي.

د انفجار فلټرونه

د جامد ترتیب لپاره، فلټرونه د راتلونکو غوښتنو پروسس کولو څرنګوالی ټاکي. پدې حالت کې موږ فلټرونه تنظیم کوو چې میچ کوي سرور_نومونه په مخکینۍ مرحله کې. کله چې راتلونکی غوښتنې راشي چې د ځانګړو ډومینونو او لارو سره سمون لري، ټرافيک کلستر ته لیږدول کیږي. دا د NGINX د ښکته پورته ترتیب سره برابر دی.

Copy to Editor    filter_chains:
    - filters:
      - name: envoy.http_connection_manager
        config:
          codec_type: auto
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: backend
              domains:
                - "one.example.com"
                - "www.one.example.com"
              routes:
              - match:
                  prefix: "/"
                route:
                  cluster: targetCluster
          http_filters:
          - name: envoy.router

نوم envoy.http_connection_manager په Envoy Proxy کې یو جوړ شوی فلټر دی. نور فلټرونه شامل دي Redis, منګ, TCP. تاسو کولی شئ بشپړ لیست په کې ومومئ اسناد.

د نورو بار بیلانس پالیسي په اړه د نورو معلوماتو لپاره، لیدنه وکړئ د سفیر اسناد.

5 ګام - پراکسي او د پورته کولو ترتیب

په NGINX کې، د پورته کولو ترتیب د هدف سرورونو سیټ تعریفوي چې ټرافيک به پروسس کړي. په دې حالت کې، دوه کلسترونه ټاکل شوي.

  upstream targetCluster {
    172.18.0.3:80;
    172.18.0.4:80;
  }

په سفیر کې، دا د کلسترونو لخوا اداره کیږي.

د استازي کلسترونه

د پورته جریان مساوي د کلسترونو په توګه تعریف شوی. په دې حالت کې، هغه کوربه چې د ټرافیک خدمت کوي پیژندل شوي. هغه لاره چې کوربه ته لاسرسی لري، لکه د وخت پای، د کلستر ترتیب په توګه تعریف شوی. دا د اړخونو لکه د ځنډ او بار توازن په اړه د لا زیاتو کنټرول لپاره اجازه ورکوي.

Copy to Editor  clusters:
  - name: targetCluster
    connect_timeout: 0.25s
    type: STRICT_DNS
    dns_lookup_family: V4_ONLY
    lb_policy: ROUND_ROBIN
    hosts: [
      { socket_address: { address: 172.18.0.3, port_value: 80 }},
      { socket_address: { address: 172.18.0.4, port_value: 80 }}
    ]

کله چې د خدماتو کشف وکاروئ STRICT_DNS سفیر به په دوامداره او غیر متقابل ډول د DNS ټاکل شوي اهداف حل کړي. د DNS پایلې څخه هر راستون شوی IP پته به په اپسټریم کلستر کې یو څرګند کوربه وګڼل شي. دا پدې مانا ده چې که چیرې غوښتنه دوه IP پتې بیرته راولي، نو سفیر به فرض کړي چې په کلستر کې دوه کوربه شتون لري، او دواړه باید د بار متوازن وي. که چیرې کوربه له پایلې څخه لیرې شي، نو سفیر به ګومان وکړي چې دا نور شتون نلري او د موجوده ارتباطي حوضونو څخه به ټرافيک راوباسي.

د نورو معلوماتو لپاره وګورئ د سفیر پراکسي اسناد.

شپږم ګام - د ننوتلو لاسرسی او تېروتنې

وروستی ترتیب ثبت کول دي. د دې پرځای چې ډیسک ته د خطا لاګونو فشار ورکړئ ، د انوی پراکسي د کلاوډ پراساس چلند غوره کوي. ټول غوښتنلیک لاګونه تولید شوي دي stdout и سټډر.

کله چې کاروونکي غوښتنه کوي، د لاسرسي لاګونه اختیاري دي او د ډیفالټ لخوا غیر فعال شوي. د HTTP غوښتنو لپاره د لاسرسي لاګونو فعالولو لپاره ، تشکیلات فعال کړئ لاسرسی_لاګ د HTTP ارتباط مدیر لپاره. لاره کیدای شي یو وسیله وي لکه stdout، یا په ډیسک کې فایل ، ستاسو اړتیاو پورې اړه لري.

لاندې تشکیلات به د لاسرسي ټول لاګونه بیرته راستانه کړي stdout (د ژباړونکي یادښت - stdout د ډاکر دننه د سفیر کارولو لپاره اړین دی. که چیرې د ډاکر پرته کارول کیږي، نو د منظم لاګ فایل ته د لارې سره /dev/stdout بدل کړئ). د پیوستون مدیر لپاره د ترتیب برخې ته ټوټه کاپي کړئ:

Copy to Clipboardaccess_log:
- name: envoy.file_access_log
  config:
    path: "/dev/stdout"

پایلې باید داسې ښکاري:

      - name: envoy.http_connection_manager
        config:
          codec_type: auto
          stat_prefix: ingress_http
          access_log:
          - name: envoy.file_access_log
            config:
              path: "/dev/stdout"
          route_config:

په ډیفالټ ډول، سفیر یو فارمیټ تار لري چې د HTTP غوښتنې توضیحات پکې شامل دي:

[%START_TIME%] "%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%" %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% "%REQ(X-FORWARDED-FOR)%" "%REQ(USER-AGENT)%" "%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%"n

د دې فارمیټ تار پایله دا ده:

[2018-11-23T04:51:00.281Z] "GET / HTTP/1.1" 200 - 0 58 4 1 "-" "curl/7.47.0" "f21ebd42-6770-4aa5-88d4-e56118165a7d" "one.example.com" "172.18.0.4:80"

د محصول مینځپانګه د فارمیټ ساحې تنظیم کولو سره تنظیم کیدی شي. د مثال په ډول:

access_log:
- name: envoy.file_access_log
  config:
    path: "/dev/stdout"
    format: "[%START_TIME%] "%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%" %RESPONSE_CODE% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% "%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%"n"

د لاګ لاین د ساحې په ترتیب کولو سره د JSON فارمیټ کې هم تولید کیدی شي json_format. د مثال په توګه:

access_log:
- name: envoy.file_access_log
  config:
    path: "/dev/stdout"
    json_format: {"protocol": "%PROTOCOL%", "duration": "%DURATION%", "request_method": "%REQ(:METHOD)%"}

د سفیر راجستریشن میتودولوژی په اړه د نورو معلوماتو لپاره، لیدنه وکړئ

https://www.envoyproxy.io/docs/envoy/latest/configuration/access_log#config-access-log-format-dictionaries

ننوتل یوازینۍ لار نه ده چې د استازي پراکسي سره کار کولو کې بصیرت ترلاسه کړي. دا پرمختللي تعقیب او میټریک وړتیاوې لري چې پدې کې رامینځته شوي. تاسو کولی شئ په دې اړه نور معلومات ومومئ د تعقیب اسناد یا له لارې د متقابل تعقیب سکریپټ.

7 ګام - پیل کړئ

تاسو اوس خپل تشکیلات له NGINX څخه Envoy Proxy ته لیږدولي دي. وروستی ګام دا دی چې د دې آزموینې لپاره د انوان پراکسي مثال پیل کړئ.

د کارونکي په توګه چلول

د NGINX ترتیب کولو کرښې په سر کې کارن www؛ د امنیت ښه کولو لپاره د ټیټ امتیاز لرونکي کارونکي په توګه د NGINX چلولو لپاره مشخص کوي.

Envoy Proxy د دې اداره کولو لپاره د کلاوډ پراساس چلند غوره کوي چې څوک د پروسې مالکیت لري. کله چې موږ د کانټینر له لارې Envoy Proxy چلوو، موږ کولی شو یو ټیټ امتیاز لرونکي کاروونکي مشخص کړو.

د استازي پراکسي پیل کول

لاندې کمانډ به په کوربه کې د ډاکر کانټینر له لارې د استازي پراکسي چلوي. دا کمانډ Envoy ته دا وړتیا ورکوي چې د 80 په پورټ کې د راتلونکو غوښتنو لپاره غوږ ونیسي. په هرصورت، لکه څنګه چې د اوریدونکي ترتیب کې مشخص شوي، Envoy پراکسي د 8080 په بندر کې د راتلونکو ټرافیکونو لپاره غوږ نیسي. دا پروسې ته اجازه ورکوي چې د ټیټ امتیاز لرونکي کاروونکي په توګه پرمخ بوځي.

docker run --name proxy1 -p 80:8080 --user 1000:1000 -v /root/envoy.yaml:/etc/envoy/envoy.yaml envoyproxy/envoy

ازمايښت

د پراکسي چلولو سره، ازموینې اوس کیدی شي او پروسس شي. لاندې cURL کمانډ د کوربه سرلیک سره غوښتنه کوي چې په پراکسي ترتیب کې تعریف شوي.

curl -H "Host: one.example.com" localhost -i

د HTTP غوښتنه به د تېروتنې پایله ولري 503. دا ځکه چې د اپ سټریم اړیکې کار نه کوي او شتون نلري. نو ځکه، د استازي پراکسي د غوښتنې لپاره هیڅ ځای شتون نلري. لاندې کمانډ به د HTTP خدماتو لړۍ پیل کړي چې د سفیر لپاره تعریف شوي ترتیب سره سمون لري.

docker run -d katacoda/docker-http-server; docker run -d katacoda/docker-http-server;

د موجودو خدماتو سره، سفیر کولی شي په بریالیتوب سره خپل منزل ته ټرافيک پراکسي کړي.

curl -H "Host: one.example.com" localhost -i

تاسو باید یو ځواب وګورئ چې دا په ګوته کوي چې کوم ډاکر کانټینر غوښتنه پروسس کړې. د استازي پراکسي لاګونو کې تاسو باید د لاسرسي تار محصول هم وګورئ.

اضافي HTTP ځواب سرلیکونه

تاسو به د اصلي غوښتنې ځواب سرلیکونو کې اضافي HTTP سرلیکونه وګورئ. سرلیک هغه وخت ښیې چې اپسټریم کوربه د غوښتنې پروسس کولو کې مصرف کړی. په ملی ثانیو کې څرګند شوی. دا ګټور دی که چیرې پیرودونکي د شبکې ځنډ په پرتله د خدماتو وخت وټاکي.

x-envoy-upstream-service-time: 0
server: envoy

وروستی ترتیب

static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address: { address: 0.0.0.0, port_value: 8080 }
    filter_chains:
    - filters:
      - name: envoy.http_connection_manager
        config:
          codec_type: auto
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: backend
              domains:
                - "one.example.com"
                - "www.one.example.com"
              routes:
              - match:
                  prefix: "/"
                route:
                  cluster: targetCluster
          http_filters:
          - name: envoy.router
          clusters:
  - name: targetCluster
    connect_timeout: 0.25s
    type: STRICT_DNS
    dns_lookup_family: V4_ONLY
    lb_policy: ROUND_ROBIN
    hosts: [
      { socket_address: { address: 172.18.0.3, port_value: 80 }},
      { socket_address: { address: 172.18.0.4, port_value: 80 }}
    ]

admin:
  access_log_path: /tmp/admin_access.log
  address:
    socket_address: { address: 0.0.0.0, port_value: 9090 }

د ژباړونکي څخه اضافي معلومات

د Envoy Proxy د نصبولو لارښوونې په ویب پاڼه کې موندل کیدی شي https://www.getenvoy.io/

په ډیفالټ ډول، rpm د سیسټمډ خدمت ترتیب نلري.

د سیسټمډ خدمت ترتیب اضافه کړئ /etc/systemd/system/envoy.service:

[Unit]
Description=Envoy Proxy
Documentation=https://www.envoyproxy.io/
After=network-online.target
Requires=envoy-auth-server.service
Wants=nginx.service

[Service]
User=root
Restart=on-failure
ExecStart=/usr/bin/envoy --config-path /etc/envoy/config.yaml
[Install]
WantedBy=multi-user.target

تاسو اړتیا لرئ یو ډایرکټر /etc/envoy/ جوړ کړئ او هلته config.yaml config کېږدئ.

د سفیر پراکسي په کارولو سره د ټیلیګرام چیٹ شتون لري: https://t.me/envoyproxy_ru

Envoy Proxy د جامد منځپانګې خدمت کولو ملاتړ نه کوي. له همدې امله، څوک کولی شي ځانګړتیا ته رایه ورکړي: https://github.com/envoyproxy/envoy/issues/378

یوازې راجستر شوي کاروونکي کولی شي په سروې کې برخه واخلي. ننوزئمهرباني وکړئ

ایا دې پوسټ تاسو هڅولي چې د سفیر پراکسي نصب او ازموینه وکړئ؟

  • هو

  • نه

75 کاروونکو رایه ورکړه. 18 کاروونکي منع شوي.

سرچینه: www.habr.com

Add a comment