Socket.io: AWS EC2 Behind ELB Selalu Mencetak Kesalahan Kode respons tak terduga: 400

Dibuat pada 30 Okt 2014  ·  66Komentar  ·  Sumber: socketio/socket.io

Hai teman-teman -

Sepertinya tidak dapat menemukan solusi untuk ini, tetapi ketika saya menjalankan aplikasi saya di belakang penyeimbang beban, saya mendapatkan kesalahan ini pada klien:

WebSocket connection to 'wss://fakedomain.com/socket.io/?EIO=3&transport=websocket&sid=QH8VmXbiEcp3ZyiLAAAD' failed: Error during WebSocket handshake: Unexpected response code: 400 

Saya memahami kesalahannya, karena ia mencoba berbicara dengan penyeimbang beban dan sekarang instance EC2 (saya tidak hebat dengan AWS, jadi silakan menawarkan bantuan untuk yang ini!) tetapi yang tidak saya mengerti adalah bagaimana membuat kesalahan tidak muncul!

Saya ingin memperbaiki akar masalahnya tetapi saya kira itu melibatkan server socket.io khusus yang terpisah untuk menangani semua hal waktu nyata yang saya tidak punya waktu untuk saat ini, tetapi bisakah seseorang tolong jalankan saya melalui penekanan kesalahan ini?

Saya berasumsi itu jatuh kembali ke polling, yang tampaknya berfungsi dengan baik (saya memiliki koneksi soket yang terhubung dan menyala) tetapi saya tidak ingin meluncurkan dengan kesalahan merah di konsol saya.

Terima kasih sebelumnya atas saran yang mungkin Anda miliki!

Komentar yang paling membantu

Saya berasumsi Anda tidak menggunakan Elastic Beanstalk (petunjuk di sana akan jauh lebih mudah).

Buka EC2->Jaringan & Keamanan->Load Balancers

Pilih penyeimbang beban Anda dan buka Pendengar. Pastikan protokol Load Balancer dan Instance Protocol diatur ke TCP untuk port 80 dan SSL untuk port 443, bukan HTTP dan HTTPS.

Semua 66 komentar

Juga, saya telah menginstal melalui bower jika itu penting:

"socket.io-client": "~1.1.0",

Apakah Anda memiliki koneksi yang lengket di server Anda?

Saya berasumsi Anda tidak menggunakan Elastic Beanstalk (petunjuk di sana akan jauh lebih mudah).

Buka EC2->Jaringan & Keamanan->Load Balancers

Pilih penyeimbang beban Anda dan buka Pendengar. Pastikan protokol Load Balancer dan Instance Protocol diatur ke TCP untuk port 80 dan SSL untuk port 443, bukan HTTP dan HTTPS.

Oh man. Ini adalah saran yang solid yang belum pernah saya lihat di tempat lain. Saya akan mencoba di AM
dan melaporkan kembali. Terima kasih!

Pada Rabu, 29 Okt 2014, 19:48 Vadim Kazakov [email protected]
menulis:

Saya berasumsi Anda tidak menggunakan Elastic Beanstalk (instruksi di sana akan
menjadi jauh lebih mudah).

Buka EC2->Jaringan & Keamanan->Load Balancers

Pilih penyeimbang beban Anda dan buka Pendengar. Pastikan bahwa kedua Beban
Protokol penyeimbang dan Protokol Instance diatur ke TCP untuk port 80 dan
SSL untuk port 443 daripada HTTP dan HTTPS.


Balas email ini secara langsung atau lihat di GitHub
https://github.com/Automattic/socket.io/issues/1846#issuecomment -61038664
.

Jadi mungkin saya salah, tetapi situs kami berjalan di HTTPS (dengan sertifikat SSL kami). Mengubahnya menjadi merusak banyak hal. Saya sedang memeriksa X-Forwarded-Proto di aplikasi saya untuk memastikan permintaannya adalah HTTPS dan jika tidak, memaksanya untuk mengarahkan ulang. Rupanya tidak ada header X-Forwarded-Proto dengan SSL/TCP dan Express melaporkan req.secure sebagai false (meskipun saya mengetik https).

Saran?

Tidak yakin, soket menggunakan protokol TCP/SSL bukan HTTP sehingga Anda perlu mengubahnya ke TCP/SSL agar soket web berfungsi. Sejauh bagaimana cara memperbaiki sisa aplikasi Anda, saya tidak tahu.

Terima kasih untuk bantuannya. Saya harus membuat lingkungan baru dan sedikit dipusingkan. Ada banyak roda di mesin!

Apakah mungkin untuk menjalankan soket web di port mereka sendiri? Jika demikian, dapatkah Anda menautkan beberapa dokumentasi? (Saya cukup yakin tidak ada tapi saya bisa saja salah)

Mereka dapat bekerja pada port apa pun yang Anda inginkan, cukup tentukan kapan Anda menghubungkan port seperti:

io('https://myserver:123');

Saya menggunakan Elasticbeanstalk dan menghadapi masalah yang sama, saya tidak menginstal SSL tetapi terhubung melalui http biasa.

Hai,
Saya memiliki masalah yang sama, meskipun saya menggunakan SockJS.
aplikasi saya adalah aplikasi Java Spring 4, bekerja pada mesin pengembangan dan
mendapatkan kesalahan yang sama di AWS.
sepertinya header Upgrade dijatuhkan oleh seseorang, saya bisa melihatnya di klien.

belum bisa menemukan solusi...

Saya berada di kapal yang sama dan dalam obrolan langsung dengan insinyur AWS dan kami berdua bingung. Saya memang mengkonfirmasi bahwa ELB perlu diubah dari HTTP/HTTPS ke TCP (atau SSL (Secure TCP)) tetapi saya masih sering mendapatkan 400 kesalahan. Tidak pernah mengalami masalah ini sampai pindah ke Elastic Beanstalk load balance cluster.

silakan coba komentari hal-hal middleware app.use apa pun (terkait header/kors) jika ada, atau app.get("/", tidak yakin mana yang berhasil untuk saya, tetapi kirimkan hasil Anda.

Pembaruan: Saya telah mengkonfirmasi itu adalah ELB, apakah itu dikonfigurasi untuk lalu lintas HTTP atau HTTPS, socket.io gagal. Ketika saya langsung ke salah satu EC2 semuanya bekerja dengan baik.

Terlampir adalah apa yang saya lihat ketika melewati ELB.
snipimage

Sepertinya saya telah memecahkan masalah saya dengan menambahkan instance Route53 di depan loadbalancer.
saya sekarang memiliki soket web yang berfungsi dengan koneksi aman di bawah lingkungan AWS.

Coba tambahkan Route 53, jika ini tidak menyelesaikan masalah Anda, saya akan dengan senang hati membagikan konfigurasi saya.

@yoav200 pikir Anda dapat membagikan seluruh konfigurasi Anda untuk apa yang membuat semuanya bekerja untuk Anda? Yaitu, port pada protokol + keamanan EBS (http/tcp), .ebextensions apa pun yang Anda butuhkan, dll. Saya mencoba banyak hal berbeda untuk meretas konfigurasi nginx saya untuk menjaga header pemutakhiran dan mengirimkannya ke node, tetapi tidak ada yang berhasil untuk saya . FWIW - halaman wiki akan sangat, sangat membantu untuk ini. Satu-satunya hal yang berhasil adalah langsung ke instance EC2 saya.

Saya telah menyiapkan instance Route 53 yang mengelola domain saya.
saya telah mengonfigurasi Zona yang Di-host dengan catatan yang mengarahkan domain saya langsung ke penyeimbang beban.

penyeimbang beban dikonfigurasi untuk meneruskan permintaan ke instance Tomcat saya, seperti yang ditunjukkan di sini:
lb-listeners

grup keamanan untuk ELB cukup standar:
lb-security-group

Apakah Anda menggunakan nginx? Apakah Anda harus melakukan sesuatu yang khusus untuk konfigurasi?

Saya sangat dekat dengan ini, menghabiskan hampir 8 jam dengan teknisi dukungan AWS selama dua hari terakhir. Harus mengeluarkan nginx dari campuran tetapi saya sangat dekat, soket berfungsi dengan baik melalui ELB melalui http, besok saya pikir saya dapat menangani hal-hal https di sisi server alih-alih di tingkat ELB.

Saya akan melaporkan kembali dengan temuan saya.

Saya tidak menggunakan nginx, saya mengelola semuanya di Amazon, saya juga telah memindahkan domain saya ke Amazon,
namun saya telah memigrasikan aplikasi saya dari lingkungan cloud yang dihosting yang menggunakan AWS untuk instance mereka tetapi mengelola beban dengan nginx dan saya tidak punya masalah di sana.

ketika ditanya bagaimana cara kerjanya untuk mereka, tanggapan mereka adalah:

kami tidak menggunakan Amazon Elastic Load Balancer, kami menggunakan lapisan penyeimbang beban NGinx kami sendiri.
Solusinya adalah menggunakan server Nginx atau HAProxy alih-alih ELB dan menggunakan grup penskalaan otomatis dengan 1 node haproxy/nginx untuk memastikan ketersediaan komponen yang tinggi.

Ya, saya diberitahu bahwa HAProxy adalah opsi lain, tetapi saya cukup yakin saya akan membuatnya bekerja dengan layanan berikut pada akhir hari:

  • Pohon Kacang elastis
  • ELB
  • Grup penskalaan otomatis EC2 (dibuat oleh EB)
  • RDS
  • ElastiCache

Aplikasi node bekerja dengan semua layanan ini saat ini tetapi seperti yang saya katakan, hanya melalui HTTP sehingga tidak banyak yang harus dilakukan untuk menyiapkan produksi. Saya akan melaporkan kembali dengan temuan/konfigurasi saya nanti.

@niczak, bisakah Anda berbagi sedikit tentang bagaimana Anda melakukannya?

Saat ini saya mencoba untuk terhubung ke Socket.IO pada instance Node saya di EC2 bersama dengan menggunakan Redis ElastiCache.

Saya membuka instance EC2 ke publik bersama dengan menanggapi dengan alamat IP publik sehingga saya dapat dengan mudah terhubung ke soket (http://coding-ceo.ghost.io/how-to-run-socket-io-behind -elb-on-aws/). pada ELB saya, saya menggunakan sesi lengket (berharap ini akan tetap terhubung), namun soket saya masih tidak terhubung dan memberi saya yang indah gagal: Koneksi ditutup sebelum menerima respons jabat tangan.

Jajak pendapat berfungsi dengan baik, tetapi mencoba membuat soket dan seluruh jalur berfungsi dengan baik.

Akan senang melihat kasus penggunaan di sini sehingga saya dapat mengonfigurasi instance saya dengan benar (bahkan jika itu hanya pada HTTP alih-alih http dan https) karena saya telah menghancurkan diri saya sendiri cukup lama sekarang.

Terima kasih banyak atas bantuan Anda!

@petrogad

Hei Pete!

Pendengar ELB saya sesederhana mungkin (lihat gambar) dan secara default pada port EC2 80 diteruskan ke 8080 menggunakan iptables. Dengan itu, saya dapat menekan server saya di HTTPS, lalu aplikasi simpul saya mendengarkan pada 8080 dan menyajikan sertifikat SSL itu sendiri.

elb

Kode node untuk menangani certs adalah sebagai berikut:

        files = ["COMODOHigh-AssuranceSecureServerCA.crt", "AddTrustExternalCARoot.crt"];
        ca = (function() {
            var _i, _len, _results;
            _results = [];
            for (_i = 0, _len = files.length; _i < _len; _i++) {
                file = files[_i];
                _results.push(fs.readFileSync('/etc/ssl/tcerts/' + file));
            }
            return _results;
            })();

        httpsOptions = {
            ca: ca,
            key: fs.readFileSync('/etc/ssl/tcerts/multidomain.key', 'utf8'),
            cert: fs.readFileSync('/etc/ssl/tcerts/14432575.crt', 'utf8')
        };

        this.serverPort = 8080;
        var httpsServer = https.createServer(httpsOptions, apiInstance);
        httpsServer.listen(this.serverPort);
        startSockets(httpsServer);

Agar soket web berfungsi (tanpa kembali ke polling panjang) saya _harus_ menonaktifkan Cross-Zone Load Balancing. Sayangnya AWS tidak mengklaim untuk mendukung soket web melalui ELB mereka sehingga jenis "peretasan" konfigurasi ini diperlukan. Semoga ini cukup untuk membuat Anda bangun dan berlari!

Terima kasih @niczak !

Semuanya bekerja dengan sempurna, lalu lintas HTTP berjalan yang membuang banyak hal. Juga membuat redis di beberapa instance berfungsi; hal terakhir hanya mengerjakan reCluster dan mengizinkan rute tcp untuk tetap dengan pekerja tertentu.

Apakah Anda sudah banyak sukses dengan ini? Saya menggunakan express, jadi sticky-session belum berfungsi dengan baik. Apakah Anda beruntung dengan itu?

Terima kasih lagi dan semoga setelah ini semua selesai bisa mendapatkan posting blog yang bagus di luar sana untuk orang lain yang berjuang dengan item serupa.

Terima kasih @niczak !!

Saya akhirnya mendapatkan pekerjaan saya juga. Namun, sebagai tambahan untuk mengonfigurasi
1) Load balancer untuk menggunakan protokol TCP
2) Penyeimbang beban untuk menonaktifkan penyeimbangan beban Lintas-Zona

Saya juga perlu mengatur
3) Server proxy menjadi "tidak ada" di bagian Konfigurasi Perangkat Lunak.

screen shot 2015-01-09 at 10 28 56 am

Itu berita bagus @aidanbon dan @petrogad , huzzah untuk soket di AWS! :+1:

Terima kasih banyak! Ini memecahkan masalah saya dengan pohon kacang elastis. Masuk akal untuk menghapus proxy nginx

Pembaruan dari posting asli saya:

Saya mengubah HTTPS saya menjadi SSL (443 ---> port khusus saya) dan meninggalkan HTTP (80 ---> port khusus saya).

Saya memiliki kode yang diperiksa dengan express !req.secure && X-Forwarded-Proto !=== https yang mengarahkan Anda ke HTTPS jika Anda masuk pada port 80...

NAMUN

Mengubah ke SSL membuat X-Forwarded-Proto kembali tidak terdefinisi.... memutuskan koneksi ini. (juga req.secure sepertinya sudah usang)

Jadi sekarang:

if (req.get('X-Forwarded-Proto') === 'http') {
            res.redirect('https://' + req.get('Host') + req.url);
        }

tampaknya berfungsi dengan baik, dan saya tidak lagi mendapatkan kesalahan 400 di konsol.

Halo - Saya berhasil menggunakan Node, NGINX, SSL, dan ELB di Elastic Beanstalk melakukan hal berikut:

Buat perintah container di .ebextensions untuk memodifikasi skrip konfigurasi nginx agar menyertakan soket web proxy:

container_commands:
    00proxy:
        command: sed -i 's/proxy_http_version.*/proxy_http_version\ 1.1\;\n\ \ \ \ \ \ \ \ proxy_set_header\ \ \ \ \ \ \ \ Upgrade\ \ \ \ \ \ \ \ \ \$http_upgrade\;\n\ \ \ \ \ \ \ \ proxy_set_header\ \ \ \ \ \ \ \ Connection\ \ \ \ \ \ \"upgrade\"\;/g' /tmp/deployment/config/#etc#nginx#conf.d#00_elastic_beanstalk_proxy.conf

Instal sertifikat SSL Anda di load balancer menggunakan konsol web Elastic Beanstalk.

Kemudian buka konsol web EC2, dan ubah penyeimbang beban untuk mendengarkan di SSL 443 -> TCP 80. Ini tidak berfungsi ketika saya mengubahnya di konsol web EB, saya harus melakukannya langsung di EC2.

Itu harus membuat semuanya bekerja. Saya tidak perlu melakukan pengalihan apa pun dan saya juga berhasil membuat NGINX berfungsi.

@ChrisEdson apakah ada hal lain untuk disertakan dalam paket untuk menggunakan solusi ini?
Saya mencobanya tetapi penerapannya gagal karena kesalahan. Log menunjukkan baris berikut:

/etc/init.conf: Unable to load configuration: No such file or directory

Bisakah Anda memposting kode Anda?

Pada Jumat, 4 Sep 2015 jam 13:13, Treyone [email protected] menulis:

@ChrisEdson apakah ada hal lain untuk disertakan dalam paket untuk menggunakan solusi ini?
Saya mencobanya tetapi penerapannya gagal karena kesalahan. Log menunjukkan baris berikut:

/etc/init.conf: Unable to load configuration: No such file or directory

Balas email ini secara langsung atau lihat di GitHub:
https://github.com/socketio/socket.io/issues/1846#issuecomment -137718880

Kode aplikasi adalah implementasi socket.io yang sangat mendasar, hampir merupakan contoh penggunaan yang tidak biasa.
Satu-satunya hal yang saya tambahkan adalah file .config di .ebextensions, di mana saya menyalin potongan kode yang Anda kutip sebelumnya.
Jadi saya tidak punya banyak untuk posting :)

Jangan khawatir, hanya sulit untuk men-debug tanpa kode atau log. Bisakah Anda memposting log? Mungkin tidak pantas untuk tetap di sini, mungkin menaruhnya di tempat sampah.

Pada Jum, 4 Sep 2015 jam 15:26, Treyone [email protected] menulis:

Kode aplikasi adalah implementasi socket.io yang sangat mendasar, hampir merupakan contoh penggunaan yang tidak biasa.
Satu-satunya hal yang saya tambahkan adalah file .config di .ebextensions, di mana saya menyalin potongan kode yang Anda kutip sebelumnya.

Jadi saya tidak punya banyak untuk posting :)

Balas email ini secara langsung atau lihat di GitHub:
https://github.com/socketio/socket.io/issues/1846#issuecomment -137749890

Hum, saya menerbitkan kode saya melalui grunt alih-alih kemasan manual dan berfungsi seperti pesona. Otomatisasi harus wajib;)

Senang mendengarnya!

Pada Selasa, 8 Sep 2015 jam 15:14, Treyone [email protected] menulis:

Hum, saya menerbitkan kode saya melalui grunt alih-alih kemasan manual dan berfungsi seperti pesona. Otomatisasi harus wajib;)

Balas email ini secara langsung atau lihat di GitHub:
https://github.com/socketio/socket.io/issues/1846#issuecomment -138572724

Selamatkan hari saya!

Kami juga melihat masalah mendasar ini. Pada dasarnya, karena SocketIO mengirimkan dua permintaan untuk membuat koneksi websocket, jika panggilan tersebut digabungkan di seluruh instance, ID sesi tidak dikenali dan jabat tangan gagal, menyebabkan SocketIO jatuh kembali ke polling panjang. Ini benar apakah Anda menggunakan ws atau wss; itu mengasumsikan Anda telah menyiapkan penyeimbangan beban pada lapisan-4 (TCP), karena saya tidak bisa mendapatkan penyeimbangan beban lapisan-7 (HTTP) untuk bekerja dengan soket web.

Perbaikannya adalah dengan mengaktifkan sesi sticky, sehingga setelah panggilan melewati sebuah instance, penyeimbang beban terus mengirimkan permintaan tersebut ke instance yang sama; namun, jika Anda menggunakan ELB AWS, mereka tidak mengizinkan Anda menggunakan sesi lekat untuk penyeimbangan beban lapisan-4.

Apa yang akhirnya kami lakukan adalah menggunakan soket web mentah, daripada SocketIO, karena tidak ada data sesi yang perlu dipertahankan di seluruh panggilan (hanya satu panggilan, jabat tangan, berlangsung, dan itu berfungsi).

Perbaikan pada bagian AWS adalah mengizinkan sesi lengket untuk digunakan dalam beberapa cara untuk penyeimbangan beban lapisan-4.

Perbaikan pada bagian SocketIO adalah membuatnya sehingga jabat tangan websocket tidak memerlukan konteks sessionID sebelumnya (Saya tidak tahu tujuan atau siklus hidup di sekitar ini; Saya berasumsi itu ada untuk membantu polling yang panjang, dan lebih banyak lagi sambungkan kembali dengan cepat jika koneksi terputus; jika klien menentukan koneksi telah mati, itu dapat menghasilkan sesi baru dan menyambung kembali dengan sukses, daripada membuat backend menolak jabat tangan karena yakin koneksi sudah ada).

Perbaikan potensial adalah menggunakan Redis untuk mempertahankan status sesi di semua instance. Saya belum menguji ini.

Solusinya, jika beban Anda memungkinkan, adalah juga memastikan hanya satu instance node per zona ketersediaan, dan menonaktifkan penyeimbangan beban lintas zona. Dengan begitu, semua panggilan akan default ke satu node, menghindari masalah ini.

@aidanbon Saya tidak dapat menemukan Proxy server to be "none" in the Software Configuration section ?

Saya hanya menggunakan server ubuntu dan MeteorJS dengan penyebaran mup .. bisakah Anda memberi saya tautan ??

Bersulang

@sahanDissanayake Saya menemukan opsi konfigurasi Server Proksi saya melalui:

  1. Klik "Konfigurasi" di Lingkungan yang diinginkan
  2. Klik "Konfigurasi Perangkat Lunak" dari dalam halaman Konfigurasi
  3. Drop-down "Server proxy" seperti yang ditunjukkan pada tangkapan layar saya sebelumnya.

Catatan: Lingkungan saya disediakan hampir setahun yang lalu. Tidak yakin panel AWS telah diperbarui untuk lingkungan yang lebih baru. Namun, saya masih dapat melihat drop-down ini hari ini di lingkungan saya.

@aidanbon Saya tidak menggunakan layanan lain selain EC2.. jadi pengaturan Anda tidak relevan dengan saya? atau apakah saya harus mulai menggunakan server poxy ini?

Jadi masalah yang saya miliki adalah, soket web aplikasi web saya berfungsi di port 8080, tetapi BUKAN di port 80.

Ini adalah masalah

@lostcolony Terima kasih atas ringkasannya. Saya telah sampai pada kesimpulan yang sama. Sudahkah Anda membaca posting blog ini: https://medium.com/@Philmod/load -balancing-websockets-on-ec2-1da94584a5e9#.hd2ectz8t? Dia pada dasarnya mengatakan bahwa seseorang dapat meneruskan layer-4 (TCP) ke instance HAProxy, yang kemudian melepas header PROXY dan mengarahkan lalu lintas ke instance yang tepat menggunakan sesi sticky. Namun, tidak jelas bagi saya bagaimana kedua HAProxy membuat daftar server "backend" mereka dikonfigurasi dan di mana ia berjalan dan di mana server socket.io yang sebenarnya berjalan. Bisakah Anda memahaminya?

EDIT: Saya pikir saya mengklik sekarang. Dia tahu daftarnya karena dia memiliki seperangkat server yang dikenal dan tidak peduli dengan penskalaan otomatis...

Daftar server akan dikonfigurasi pada setiap kotak HAproxy. Saya tidak yakin bagaimana
untuk membuatnya berfungsi dengan instans EC2 penskalaan otomatis, kecuali jika Anda menulis beberapa
infrastruktur tambahan untuk memperbarui daftar itu ketika server baru datang
on line. Socket.io mereka berjalan di server yang sama dengan aplikasi Web mereka, jadi
koneksi masuk melalui Elb, digabungkan ke instance HAproxy,
instance HAproxy memastikan bahwa koneksi IP selalu sama
server web/aplikasi, tempat socket.io disiapkan.
Pada 13 Jan 2016 2:50, "Felix Schlitter" [email protected] menulis:

@lostcolony https://github.com/lostcolony Terima kasih atas ringkasannya. Saya
telah sampai pada kesimpulan yang sama. Sudahkah Anda membaca posting blog ini:
https://medium.com/@Philmod/load -balancing-websockets-on-ec2-1da94584a5e9#.hd2ectz8t?
Dia pada dasarnya mengatakan seseorang dapat melewati layer-4 (TCP) ke a
instans HAProxy, yang kemudian melepas header PROXY dan merutekan
lalu lintas ke instance yang tepat menggunakan sesi sticky. Namun, tidak
jelas bagi saya bagaimana kedua HAProxy mendapatkan daftar server "backend" mereka
dikonfigurasi dan di mana ia berjalan dan di mana server socket.io yang sebenarnya berjalan.
Bisakah Anda memahaminya?


Balas email ini secara langsung atau lihat di GitHub
https://github.com/socketio/socket.io/issues/1846#issuecomment -171208211
.

@lostcolony OK, saya melihat ada proyek menarik dalam hal penskalaan otomatis di amazon, menggunakan HAProxy - setidaknya berguna untuk referensi: https://github.com/markcaudill/haproxy-autoscale. Yang saya tidak mengerti adalah mengapa menggunakan ELB di depan HAProxy? Harus ada hanya satu instans HAProxy, jika tidak, bagaimana Anda menjamin bahwa ELB mengirimkan lalu lintas ke instans HAProxy yang tepat? Kecuali mereka (instance HAProxy) berbagi tabel lengket umum entah bagaimana menggunakan ElastiCache atau Redis atau sesuatu seperti itu? ... Saya menyadari kita akan _way_ keluar dari topik.

Jika Anda memiliki HAProxies yang dikonfigurasi untuk merutekan koneksi berdasarkan IP, Anda
bisa menjamin itu akan berakhir pada contoh yang sama. Artinya, jika HAProxies
semua memiliki aturan yang sama yang mengatakan bahwa ip ABCD diarahkan ke instance satu,
maka terlepas dari HAProxy mana yang dipukul ELB, itu akan berakhir pada saat yang sama
tempat. Itulah yang terjadi di tautan yang Anda kirim, mereka menyeimbangkan
melalui sumber, artinya instance HAProxy meng-hash IP dan menggunakannya untuk
menentukan ke mana ia pergi. Beberapa HAProxies, asalkan semuanya
tahu tentang contoh yang sama, dengan demikian akan mengirim lalu lintas dari satu lokasi ke
contoh backend yang sama.

Pada Wed, Jan 13, 2016 at 01:19, Felix Schlitter [email protected]
menulis:

@lostcolony https://github.com/lostcolony OK, saya melihat ada
proyek menarik sehubungan dengan penskalaan otomatis di amazon, menggunakan HAProxy -
setidaknya bermanfaat untuk referensi:
https://github.com/markcaudill/haproxy-autoscale. Yang tidak saya mengerti adalah mengapa
menggunakan ELB di depan HAProxy? Harus ada hanya satu contoh HAProxy,
jika tidak, bagaimana Anda menjamin bahwa ELB mengirimkan lalu lintas ke kanan?
Contoh HAProxy? Kecuali jika mereka (instance HAProxy) memiliki kesamaan
tabel lengket entah bagaimana menggunakan ElastiCache atau Redis atau sesuatu seperti itu
garis? ... Saya menyadari kita akan _way_ keluar dari topik.


Balas email ini secara langsung atau lihat di GitHub
https://github.com/socketio/socket.io/issues/1846#issuecomment -171386260
.

@lostcolony Saya mengerti bahwa hash diturunkan secara deterministik untuk ip yang diberikan, namun, harus ada pemetaan "hash -> instance". Dalam kasus Anda, Anda mengatakan ada aturan yang mengatakan "ABCD diarahkan ke instance satu", tetapi apakah Anda tidak ingin HAProxy menentukan sendiri ke mana harus mengarahkan, mengingat daftar server yang tersedia? Lagi pula, "ABCD" hanyalah ip klien dan tidak diketahui sebelumnya.

Aturan untuk memetakan hash ke sebuah instance adalah sama di semua HAProxy
contoh. Artinya, ABCD akan menghasilkan hash yang sama tidak peduli
Contoh HAProxy yang terkena, dan hash itu akan dipetakan ke server yang sama, tidak
masalah instance HAProxy yang digunakan, asalkan setiap HAProxy tahu tentang
contoh yang sama (dan mungkin dalam urutan yang sama/nama yang sama). Itu
IP sebenarnya tidak harus diketahui di muka, karena tidak penting.
IP apa pun akan di-hash ke server yang sama terlepas dari HAProxy yang dilewatinya
melalui.

Untuk contoh yang sepenuhnya dipalsukan (HAProxy menggunakan sesuatu yang tidak begitu
dapat diprediksi, saya yakin), bayangkan kami memiliki tiga server, yang dikonfigurasi
agar sebagai server0, server1, dan serve2 (detail sebenarnya tidak masalah,
hanya saja ada urutan yang jelas, implisit baik-baik saja). Setiap HAProxy
instance memiliki server yang sama, dalam urutan yang sama. Mereka juga memiliki hal yang sama
aturan tentang bagaimana menangani alamat IP yang masuk. Untuk contoh basi ini,
itu menambahkan keempat bagian alamat sebagai bilangan bulat (mudah diperluas ke
mendukung IPv6, tambahkan semua sebagai hex ke dalam basis 10), dan bagi dengan 3, ambil
sisa. Jadi IP 123.12.61.24 = (123+12+61+24) % 3, atau 1. Jadi dirutekan
ke server1. Jadi, apa pun instance HAProxy yang digunakan, itu
koneksi akan dikirim ke server1.

Sekarang, jika server1 offline, algoritme berubah di semua HAProxy
contoh, untuk menambahkan semua bagian, modulus 2.

Dan ini biasanya berfungsi -kecuali- Anda mendapatkan netsplit (atau mengkonfigurasi
instans HAProxy untuk memiliki daftar server yang berbeda). Di mana satu HAProxy melihat
3 contoh, dan yang lain melihat 2. Jika itu terjadi, Anda tidak dapat dijamin
untuk mencapai backend yang sama. Dan memang, itu bisa menjadi masalah. Tetapi
itulah solusi yang dijelaskan dalam tautan.

Pada Wed, Jan 13, 2016 at 15:51, Felix Schlitter [email protected]
menulis:

@lostcolony https://github.com/lostcolony Saya mengerti bahwa hash adalah
diturunkan secara deterministik untuk ip yang diberikan, namun, harus ada pemetaan
dari "hash -> contoh". Dalam kasus Anda, Anda mengatakan ada aturan itu
mengatakan "ABCD diarahkan ke instance satu", tetapi apakah Anda tidak mau?
HAProxy untuk menentukan sendiri ke mana harus mengarahkan, mengingat daftar yang tersedia
server? Lagi pula, "ABCD" hanyalah ip klien dan tidak diketahui
depan.


Balas email ini secara langsung atau lihat di GitHub
https://github.com/socketio/socket.io/issues/1846#issuecomment -171428465
.

Saya menemukan bahwa di Elastic Beanstalk meskipun saya telah mengatur penyeimbang beban untuk menggunakan TCP dan SSL dengan antarmuka web, ketika saya memeriksa konfigurasi penyeimbang beban secara langsung, itu masih menggunakan HTTPS untuk pendengar yang aman. Jadi, Anda mungkin harus memeriksa di bagian EC2 > Load Balancers bahwa port telah diatur sebagaimana mestinya:

screen shot 2016-03-08 at 16 08 34

Setelah diurutkan, tambahkan yang berikut ini ke .ebextensions dan semuanya berfungsi dengan baik untuk saya :)

container_commands:
  01_nginx_static:
    command: |
      sed -i '/\s*proxy_set_header\s*Connection/c \
              proxy_set_header Upgrade $http_upgrade;\
              proxy_set_header Connection "upgrade";\
          ' /tmp/deployment/config/#etc#nginx#conf.d#00_elastic_beanstalk_proxy.conf

Ini hanya akan berfungsi 100% ketika Anda hanya memiliki satu instance, karena dukungan sesi sticky tidak berfungsi melalui TCP.

@lostcolony , postingan @williamcoates barusan mengingatkan saya untuk berterima kasih atas penjelasannya. Tidak percaya aku lupa melakukan itu. Penjelasan Anda sangat membantu, jadi terima kasih telah meluangkan waktu.

Jadi saya memiliki masalah yang sama dan ternyata saya telah mengatur ECB untuk menggunakan HTTPS.
Saya mengubah HTTPS ke SSL dan saya tidak mendapatkan pesan itu lagi.
jadi, jangan gunakan HTTP/HTTPS tetapi TCP/SSL

Mulai Agustus 2016 Anda dapat menggunakan Application Load Balancer (ALB) Amazon alih-alih ELB "klasik". Bekerja "di luar kotak" untuk saya dengan pendengar di HTTP 80 dan HTTPS 443.

@trans1t Manis, terima kasih infonya! Saya harus memeriksanya.

@niczak - Saya juga telah beralih ke ALB untuk kekakuan lalu lintas soket. Namun, saya pertama kali berjuang dengan konfigurasi ALB Sticky Sessions (karena tidak terlalu banyak dokumen tentang hal ini; setidaknya beberapa bulan yang lalu). Akhirnya ketahuan. Kuncinya adalah bahwa "Kelengketan ditentukan pada tingkat grup target", jadi pastikan Anda membuat grup target untuk melayani lalu lintas Anda dan kemudian menambahkan kekakuan ke dalamnya.

@aidanbon Itu informasi yang luar biasa, terima kasih banyak telah berbagi!

Bagi siapa pun yang masih mengalami masalah dengan AWS Application Load Balancer, coba perbarui Kebijakan Keamanan Anda, saya mengalami masalah yang sama meskipun itu berfungsi dengan baik dalam pengaturan yang tepat untuk situs web lain, tetapi perhatikan bahwa kebijakan keamanan tertinggal sekitar 1 tahun. Memperbarui ke yang lebih baru tampaknya telah memecahkan masalah.

@michaelmitchell apakah Anda mengubah sesuatu, atau hanya memperbaruinya tanpa modifikasi?

Saya tidak mengubah apa pun di aplikasi saya, satu-satunya langkah tambahan yang saya ambil adalah menghapus dan menambahkan kembali pendengar HTTPS di ALB karena setelah mengubah ke kebijakan baru tampaknya tidak berfungsi.

Namun saya mengetahui bahwa melihat kesalahan bahkan setelah memperbarui kebijakan keamanan kemungkinan sesi browser saya memegang kebijakan keamanan lama jadi saya tidak yakin apakah menambahkan/menambahkan kembali pendengar benar-benar diperlukan, tetapi membuka penyamaran itu berfungsi dengan baik dan setelahnya menutup semua sesi chrome saya dan membukanya kembali berfungsi dengan baik dan belum melihatnya sejak itu.

Senang mengetahuinya, terima kasih!

Le ven. 31 mars 2017 12:02, Michael Mitchell [email protected] a
écrit:

Saya tidak mengubah apa pun di aplikasi saya, satu-satunya langkah tambahan yang saya lakukan
ambil adalah untuk menghapus dan menambahkan kembali pendengar HTTPS di ALB seperti setelahnya
mengubah ke kebijakan baru tampaknya tidak berhasil.

Namun saya belajar bahwa melihat kesalahan bahkan setelah memperbarui keamanan
kebijakan kemungkinan sesi browser saya memegang kebijakan keamanan lama
jadi saya tidak yakin apakah menambahkan/menambahkan kembali pendengar benar-benar dibutuhkan, tapi
membuka penyamaran itu berfungsi dengan baik dan setelah menutup semua sesi chrome saya
dan membukanya kembali berfungsi dengan baik dan belum melihatnya sejak itu.


Anda menerima ini karena Anda berkomentar.
Balas email ini secara langsung, lihat di GitHub
https://github.com/socketio/socket.io/issues/1846#issuecomment-290672158 ,
atau matikan utasnya
https://github.com/notifications/unsubscribe-auth/ADrIi_SXqccWOLUMIWF1IhClGXvKAGMcks5rrM8sgaJpZM4C0swP
.

Sepertinya utas ini menjadi tempat untuk mencari tahu masalah dengan AWS/socket.io—

Pengaturan saya adalah bahwa klien membuat permintaan HTTPS dengan data untuk koneksi socket.io.
Permintaan HTTPS harus merespons dengan cookie yang diperlukan untuk sesi sticky. Masalahnya adalah saya tidak dapat meneruskan header cookie di koneksi socket.io.

Saya menggunakan ALB dengan pendengar ini:
image

Yang menunjuk ke grup target dengan kekakuan yang dikonfigurasi seperti ini:
image

Saya mencapai titik akhir HTTPS terlebih dahulu dengan:

fetch(`https://${url}/hub/api/spinup/${uuid}`, {
                method: 'GET',
                headers: headers,
            })

kemudian inisialisasi soket dengan

connection = io(`wss://${url}:443/`, {
            path: `/user/${uuid}/spawn`,
        })

Contoh permintaan HTTPS menyentuh _harus_ menjadi contoh koneksi soket hits.

Setelah soket dibuat (jika itu mengenai contoh yang tepat dengan keberuntungan) soket itu tetap di sana dan semuanya berfungsi dengan baik, masalahnya adalah membuat soket web mencapai titik akhir yang sama dengan permintaan HTTPS.

Insting pertamaku adalah menggunakan

connection = io(`wss://${url}:443/`, {
    path: `/user/${uuid}/spawn`,
    extraHeaders: {
        cookie: cookieValueFromFetchResponse
    }
})

Ini berfungsi di node , tetapi di browser cookie adalah header terlarang di XMLHTTPRequests, jadi saya tidak dapat mengirimkannya.

Apakah ada yang melakukan hal serupa?

Saya belum melakukan yang serupa, tetapi, sementara ALB masih belum memiliki perutean berbasis header, mereka -mempunyai perutean berbasis Host. Ini sangat hackish, tetapi pada dasarnya Anda dapat membuatnya sehingga setiap instance di belakang ALB memiliki jalur eksplisit ke sana, yang diketahui oleh instance tersebut. Saat permintaan HTTP awal itu keluar, sebagian dari respons menyertakan jalur, dan koneksi untuk soket web menyertakan jalur itu. Yaitu, permintaan HTTP mencapai instance '5' (berdasarkan kriteria apa pun; UUID yang dihasilkan akan lebih baik), mengembalikan '5' sebagai bagian dari respons, dan soket web dibuka ke url/5. ALB memiliki aturan bahwa url/5 dirutekan ke instance 5.

Jika Anda menggunakan penskalaan otomatis (dan instans Anda adalah ternak, bukan hewan peliharaan), Anda harus menjalankan kode pada instans tersebut untuk mengubah pengaturan ALB untuk merutekan domain yang sesuai ke instans tersebut.

Baca lebih lanjut di sini: https://aws.amazon.com/blogs/aws/new-host-based-routing-support-for-aws-application-load-balancers/

Saya juga akan mengatakan, bagaimanapun, bahwa Anda mungkin ingin menghindari pola yang Anda gunakan jika memungkinkan. Data yang masuk dalam permintaan HTTP harus disimpan dengan cara yang dapat diakses oleh setiap instance (DB atau sejenisnya), atau harus dikirim melalui koneksi websocket setelah dibuat. Karena itu, Anda masih dapat memiliki instance mati di antara permintaan HTTP dan soket web terbuka, dan Anda dapat mengalami masalah yang sama (walaupun jauh lebih jarang)

@lostcolony terima kasih atas sarannya—itu pasti patut dicoba.

permintaan http adalah yang memicu server websocket diputar (sebenarnya dalam wadah buruh pelabuhan, tapi itu diabstraksikan). dua permintaan harus dirutekan ke instance yang sama sehingga server websocket ada pada instance yang sedang terhubung

dengan baris ini, ada baiknya untuk menempatkan server jupyter di belakang elb.

service.beta.kubernetes.io/aws-load-balancer-backend-protocol: tcp

jika seseorang datang ke tiket ini dengan kubernetes di aws.

Saya hanya menonaktifkan HTTP2 maka tidak apa-apa untuk saya. Anda tidak perlu melakukan hal lain tentang ELB.

Screen Shot 2019-12-13 at 16 12 49

Hai,
Saya memiliki masalah yang sama, meskipun saya menggunakan SockJS.
aplikasi saya adalah aplikasi Java Spring 4, bekerja pada mesin pengembangan dan
mendapatkan kesalahan yang sama di AWS.
sepertinya header Upgrade dijatuhkan oleh seseorang, saya bisa melihatnya di klien.

belum bisa menemukan solusi...

Hai @yoav200 ,

SELAMATKAN AKU.
Saya terjebak dalam masalah yang sama. Tolong bantu
Saya menggunakan Springboot 2.x dan SockJs untuk websocket
Saya telah membuat aplikasi Tomcat yang digunakan di aws,
Pohon kacang elastis dengan penyeimbang beban klasik

Sekarang masalahnya adalah
Pengembang iOS tidak dapat terhubung, mencapai backend saya tetapi gagal selama jabat tangan
di bawah ini adalah log yang saya dapatkan di CLB dan ALB


13-12-2019 15:21:22.662 DEBUG 27543 --- [nio-8080-exec-2] oswsDispatcherServlet : GET "/wtchat/websocket", parameter={}
13-12-2019 15:21:22.701 DEBUG 27543 --- [nio-8080-exec-2] oswsssWebSocketHandlerMapping : Dipetakan ke org.springframework.web.socket.sockjs.support. SockJsHttpRequestHandler@30c6a17
13-12-2019 15:21:22.714 DEBUG 27543 --- [nio-8080-exec-2] oswssthDefaultSockJsService : Memproses permintaan transportasi: DAPATKAN http://mydomain.com/wtchat/websocket
13-12-2019 15:21:22.716 ERROR 27543 --- [nio-8080-exec-2] cwcMyHandshakeHandler : Jabat tangan gagal karena header Peningkatan tidak valid: null

13-12-2019 15:21:22.717 DEBUG 27543 --- [nio-8080-exec-2] oswsDispatcherServlet : Selesai 400 BAD_REQUEST

Saya telah mengikuti apa yang Anda katakan
image
image

membuat rekor set di Route 53 yang langsung menunjuk ke load balancer.

Setelah melakukan ini juga saya mendapatkan kesalahan yang sama seperti di atas.

Apa lagi yang perlu saya lakukan?

Apakah halaman ini membantu?
0 / 5 - 0 peringkat