Memahami dan Menangani Peristiwa Seumur Hidup Koneksi di SignalR 1.x
oleh Patrick Fletcher, Tom Dykstra
Peringatan
Dokumentasi ini bukan untuk versi terbaru SignalR. Lihat ASP.NET Core SignalR.
Artikel ini memberikan gambaran umum tentang peristiwa koneksi SignalR, koneksi ulang, dan pemutusan yang dapat Anda tangani, serta waktu habis dan pengaturan keepalive yang dapat Anda konfigurasi.
Artikel ini mengasumsikan Anda sudah memiliki beberapa pengetahuan tentang SignalR dan peristiwa seumur hidup koneksi. Untuk pengenalan SignalR, lihat SignalR - Gambaran Umum - Memulai. Untuk daftar peristiwa seumur hidup koneksi, lihat sumber daya berikut ini:
Gambaran Umum
Artikel ini berisi bagian berikut:
Tautan ke topik Referensi API adalah ke API versi .NET 4.5. Jika Anda menggunakan .NET 4, lihat topik API versi .NET 4.
Terminologi dan skenario seumur hidup koneksi
Penanganan OnReconnected
aktivitas di SignalR Hub dapat dijalankan langsung setelah OnConnected
tetapi tidak setelah OnDisconnected
untuk klien tertentu. Alasan Anda dapat memiliki koneksi ulang tanpa pemutusan adalah bahwa ada beberapa cara di mana kata "koneksi" digunakan dalam SignalR.
Koneksi SignalR, koneksi transportasi, dan koneksi fisik
Artikel ini akan membedakan antara koneksi SignalR, koneksi transportasi, dan koneksi fisik:
- Koneksi SignalR mengacu pada hubungan logis antara klien dan URL server, yang dikelola oleh SignalR API dan diidentifikasi secara unik oleh ID koneksi. Data tentang hubungan ini dikelola oleh SignalR dan digunakan untuk membuat koneksi transportasi. Hubungan berakhir dan SignalR membuang data ketika klien memanggil
Stop
metode atau batas waktu habis tercapai saat SignalR mencoba membangun kembali koneksi transportasi yang hilang. - Koneksi transportasi mengacu pada hubungan logis antara klien dan server, yang dikelola oleh salah satu dari empat API transportasi: WebSocket, peristiwa yang dikirim server, bingkai selamanya, atau polling panjang. SignalR menggunakan API transportasi untuk membuat koneksi transportasi, dan API transportasi tergantung pada keberadaan koneksi jaringan fisik untuk membuat koneksi transportasi. Koneksi transportasi berakhir ketika SignalR menghentikannya atau ketika API transportasi mendeteksi bahwa koneksi fisik rusak.
- Koneksi fisik mengacu pada tautan jaringan fisik -- kabel, sinyal nirkabel, router, dll. -- yang memfasilitasi komunikasi antara komputer klien dan komputer server. Koneksi fisik harus ada untuk membuat koneksi transportasi, dan koneksi transportasi harus dibuat untuk membuat koneksi SignalR. Namun, memutuskan koneksi fisik tidak selalu segera mengakhiri koneksi transportasi atau koneksi SignalR, seperti yang akan dijelaskan nanti dalam topik ini.
Dalam diagram berikut, koneksi SignalR diwakili oleh lapisan Hubs API dan PersistentConnection API SignalR, koneksi transportasi diwakili oleh lapisan Transports, dan koneksi fisik diwakili oleh garis antara server dan klien.
Ketika Anda memanggil Start
metode dalam klien SignalR, Anda menyediakan kode klien SignalR dengan semua informasi yang dibutuhkan untuk membuat koneksi fisik ke server. Kode klien SignalR menggunakan informasi ini untuk membuat permintaan HTTP dan membuat koneksi fisik yang menggunakan salah satu dari empat metode transportasi. Jika koneksi transportasi gagal atau server gagal, koneksi SignalR tidak segera hilang karena klien masih memiliki informasi yang diperlukan untuk secara otomatis membuat ulang koneksi transportasi baru ke URL SignalR yang sama. Dalam skenario ini, tidak ada intervensi dari aplikasi pengguna yang terlibat, dan ketika kode klien SignalR membuat koneksi transportasi baru, itu tidak memulai koneksi SignalR baru. Kelangsungan koneksi SignalR tercermin dalam fakta bahwa ID koneksi, yang dibuat ketika Anda memanggil Start
metode , tidak berubah.
Penanganan OnReconnected
aktivitas di Hub dijalankan ketika koneksi transportasi secara otomatis dibuat ulang setelah hilang. Penanganan OnDisconnected
aktivitas dijalankan di akhir koneksi SignalR. Koneksi SignalR dapat berakhir dengan salah satu cara berikut:
- Jika klien memanggil
Stop
metode , pesan berhenti dikirim ke server, dan klien dan server segera mengakhiri koneksi SignalR. - Setelah konektivitas antara klien dan server hilang, klien mencoba untuk terhubung kembali dan server menunggu klien terhubung kembali. Jika upaya untuk terhubung kembali tidak berhasil dan periode batas waktu pemutusan berakhir, klien dan server mengakhiri koneksi SignalR. Klien berhenti mencoba menyambungkan kembali, dan server membuang representasi koneksi SignalR.
- Jika klien berhenti berjalan tanpa sempat memanggil
Stop
metode , server menunggu klien untuk terhubung kembali, lalu mengakhiri koneksi SignalR setelah periode batas waktu pemutusan. - Jika server berhenti berjalan, klien mencoba menyambungkan kembali (membuat ulang koneksi transportasi), lalu mengakhiri koneksi SignalR setelah periode batas waktu pemutusan.
Ketika tidak ada masalah koneksi, dan aplikasi pengguna mengakhiri koneksi SignalR dengan memanggil Stop
metode , koneksi SignalR dan koneksi transportasi dimulai dan berakhir pada waktu yang hampir bersamaan. Bagian berikut ini menjelaskan secara lebih rinci skenario lainnya.
Skenario pemutusan transportasi
Koneksi fisik mungkin lambat atau mungkin ada gangguan dalam konektivitas. Tergantung pada faktor-faktor seperti lamanya gangguan, koneksi transportasi mungkin terputus. SignalR kemudian mencoba membangun kembali koneksi transportasi. Terkadang API koneksi transportasi mendeteksi gangguan dan menghilangkan koneksi transportasi, dan SignalR segera mengetahui bahwa koneksi hilang. Dalam skenario lain, API koneksi transportasi maupun SignalR tidak segera menyadari bahwa konektivitas telah hilang. Untuk semua transportasi kecuali polling panjang, klien SignalR menggunakan fungsi yang disebut keepalive untuk memeriksa hilangnya konektivitas yang tidak dapat dideteksi oleh API transportasi. Untuk informasi tentang koneksi polling panjang, lihat Pengaturan waktu habis dan keepalive nanti dalam topik ini.
Ketika koneksi tidak aktif, secara berkala server mengirim paket keepalive ke klien. Pada tanggal artikel ini sedang ditulis, frekuensi default adalah setiap 10 detik. Dengan mendengarkan paket ini, klien dapat mengetahui apakah ada masalah koneksi. Jika paket keepalive tidak diterima ketika diharapkan, setelah beberapa saat klien mengasumsikan bahwa ada masalah koneksi seperti kelambatan atau gangguan. Jika keepalive masih belum diterima setelah waktu yang lebih lama, klien mengasumsikan bahwa koneksi telah terputus, dan mulai mencoba untuk terhubung kembali.
Diagram berikut mengilustrasikan peristiwa klien dan server yang dimunculkan dalam skenario umum ketika ada masalah dengan koneksi fisik yang tidak segera dikenali oleh API transportasi. Diagram berlaku untuk keadaan berikut:
- Transportasinya adalah WebSocket, bingkai selamanya, atau peristiwa yang dikirim server.
- Ada berbagai periode gangguan dalam koneksi jaringan fisik.
- API transportasi tidak menyadari gangguan, sehingga SignalR bergantung pada fungsionalitas keepalive untuk mendeteksinya.
Jika klien masuk ke mode menyambungkan kembali tetapi tidak dapat membuat koneksi transportasi dalam batas waktu habis pemutusan, server menghentikan koneksi SignalR. Ketika itu terjadi, server menjalankan metode Hub OnDisconnected
dan mengantre pesan pemutusan sambungan untuk dikirim ke klien jika klien berhasil terhubung nanti. Jika klien kemudian terhubung kembali, klien akan menerima perintah putuskan sambungan dan memanggil Stop
metode . Dalam skenario ini, OnReconnected
tidak dijalankan ketika klien terhubung kembali, dan OnDisconnected
tidak dijalankan ketika klien memanggil Stop
. Diagram berikut mengilustrasikan skenario ini.
Peristiwa seumur hidup koneksi SignalR yang mungkin dinaikkan pada klien adalah sebagai berikut:
ConnectionSlow
peristiwa klien.Dimunculkan ketika proporsi prasetel dari periode batas waktu keepalive telah berlalu sejak pesan terakhir atau ping keepalive diterima. Periode peringatan batas waktu keepalive default adalah 2/3 dari batas waktu keepalive. Batas waktu keepalive adalah 20 detik, sehingga peringatan terjadi pada sekitar 13 detik.
Secara default, server mengirim ping keepalive setiap 10 detik, dan klien memeriksa ping keepalive sekitar setiap 2 detik (sepertiga dari perbedaan antara nilai batas waktu keepalive dan nilai peringatan batas waktu keepalive).
Jika API transportasi mengetahui pemutusan sambungan, SignalR mungkin diberi tahu tentang pemutusan sebelum periode peringatan batas waktu keepalive berlalu. Dalam hal ini,
ConnectionSlow
peristiwa tidak akan dinaikkan, dan SignalR akan langsung masuk ke acara tersebutReconnecting
.Reconnecting
peristiwa klien.Dimunculkan ketika (a) API transportasi mendeteksi bahwa koneksi hilang, atau (b) periode batas waktu keepalive telah berlalu sejak pesan terakhir atau ping keepalive diterima. Kode klien SignalR mulai mencoba menyambungkan kembali. Anda dapat menangani peristiwa ini jika Anda ingin aplikasi Anda mengambil beberapa tindakan ketika koneksi transportasi hilang. Periode batas waktu keepalive default saat ini adalah 20 detik.
Jika kode klien Anda mencoba memanggil metode Hub saat SignalR dalam mode menyambungkan kembali, SignalR akan mencoba mengirim perintah. Sebagian besar waktu, upaya tersebut akan gagal, tetapi dalam beberapa keadaan mereka mungkin berhasil. Untuk peristiwa yang dikirim server, bingkai selamanya, dan transportasi polling panjang, SignalR menggunakan dua saluran komunikasi, salah satu yang digunakan klien untuk mengirim pesan dan yang digunakannya untuk menerima pesan. Saluran yang digunakan untuk menerima adalah saluran yang terbuka secara permanen, dan itu adalah saluran yang ditutup ketika koneksi fisik terganggu. Saluran yang digunakan untuk pengiriman tetap tersedia, jadi jika konektivitas fisik dipulihkan, panggilan metode dari klien ke server mungkin berhasil sebelum saluran terima dibuat kembali. Nilai yang dikembalikan tidak akan diterima sampai SignalR membuka kembali saluran yang digunakan untuk menerima.
Reconnected
peristiwa klien.Dimunculkan ketika koneksi transportasi dibangkitkan kembali. Penanganan
OnReconnected
aktivitas di Hub dijalankan.Closed
peristiwa klien (disconnected
peristiwa di JavaScript).Dimunculkan ketika periode batas waktu pemutusan berakhir saat kode klien SignalR mencoba terhubung kembali setelah kehilangan koneksi transportasi. Batas waktu pemutusan sambungan default adalah 30 detik. (Peristiwa ini juga dinaikkan ketika koneksi berakhir karena
Stop
metode dipanggil.)
Gangguan koneksi transportasi yang tidak terdeteksi oleh API transportasi dan tidak menunda penerimaan ping keepalive dari server lebih lama dari periode peringatan batas waktu keepalive mungkin tidak menyebabkan peristiwa seumur hidup koneksi dinaikkan.
Beberapa lingkungan jaringan sengaja menutup koneksi diam, dan fungsi lain dari paket keepalive adalah membantu mencegah hal ini dengan memberi tahu jaringan ini bahwa koneksi SignalR sedang digunakan. Dalam kasus ekstrem frekuensi default ping keepalive mungkin tidak cukup untuk mencegah koneksi tertutup. Dalam hal ini Anda dapat mengonfigurasi ping keepalive untuk dikirim lebih sering. Untuk informasi selengkapnya, lihat Pengaturan batas waktu dan keepalive nanti dalam topik ini.
Catatan
Penting
Urutan peristiwa yang dijelaskan di sini tidak dijamin. SignalR melakukan setiap upaya untuk meningkatkan peristiwa seumur hidup koneksi dengan cara yang dapat diprediksi sesuai dengan skema ini, tetapi ada banyak variasi peristiwa jaringan dan banyak cara di mana kerangka kerja komunikasi yang mendasarinya seperti API transportasi menanganinya. Misalnya, Reconnected
peristiwa mungkin tidak dinaikkan ketika klien terhubung kembali, atau OnConnected
handler di server mungkin berjalan ketika upaya untuk membuat koneksi tidak berhasil. Topik ini hanya menjelaskan efek yang biasanya akan diproduksi oleh keadaan umum tertentu.
Skenario pemutusan sambungan klien
Di klien browser, kode klien SignalR yang mempertahankan koneksi SignalR berjalan dalam konteks JavaScript halaman web. Itulah sebabnya koneksi SignalR harus berakhir ketika Anda menavigasi dari satu halaman ke halaman lain, dan itulah sebabnya Anda memiliki beberapa koneksi dengan beberapa ID koneksi jika Anda terhubung dari beberapa jendela atau tab browser. Saat pengguna menutup jendela atau tab browser, atau menavigasi ke halaman baru atau me-refresh halaman, koneksi SignalR segera berakhir karena kode klien SignalR menangani peristiwa browser tersebut Stop
untuk Anda dan memanggil metode . Dalam skenario ini, atau di platform klien apa pun saat aplikasi Anda memanggil Stop
metode , OnDisconnected
penanganan aktivitas langsung dijalankan di server dan klien menaikkan Closed
peristiwa (peristiwa dinamai disconnected
dalam JavaScript).
Jika aplikasi klien atau komputer yang dijalankannya mengalami crash atau tidur (misalnya, ketika pengguna menutup laptop), server tidak diberi tahu tentang apa yang terjadi. Sejauh yang diketahui server, hilangnya klien mungkin karena gangguan konektivitas dan klien mungkin mencoba untuk terhubung kembali. Oleh karena itu, dalam skenario ini server menunggu untuk memberi klien kesempatan untuk terhubung kembali, dan OnDisconnected
tidak dijalankan sampai periode batas waktu pemutusan berakhir (sekitar 30 detik secara default). Diagram berikut mengilustrasikan skenario ini.
Skenario pemutusan sambungan server
Ketika server offline -- reboot, gagal, domain aplikasi didaur ulang, dll. -- hasilnya mungkin mirip dengan koneksi yang hilang, atau API transportasi dan SignalR mungkin segera tahu bahwa server hilang, dan SignalR mungkin mulai mencoba terhubung kembali tanpa menaikkan ConnectionSlow
peristiwa. Jika klien masuk ke mode menyambungkan kembali, dan jika server pulih atau dimulai ulang atau server baru dibawa online sebelum periode batas waktu pemutusan berakhir, klien akan terhubung kembali ke server yang dipulihkan atau baru. Dalam hal ini, koneksi SignalR berlanjut pada klien dan Reconnected
peristiwa dinaikkan. Pada server pertama, OnDisconnected
tidak pernah dijalankan, dan di server baru, OnReconnected
dijalankan meskipun OnConnected
tidak pernah dijalankan untuk klien tersebut di server tersebut sebelumnya. (Efeknya sama jika klien terhubung kembali ke server yang sama setelah reboot atau daur ulang domain aplikasi, karena ketika server menghidupkan ulang, klien tidak memiliki memori aktivitas koneksi sebelumnya.) Diagram berikut mengasumsikan bahwa API transportasi segera menyadari koneksi yang hilang, sehingga ConnectionSlow
peristiwa tidak dinaikkan.
Jika server tidak tersedia dalam periode batas waktu pemutusan, koneksi SignalR berakhir. Dalam skenario ini, Closed
peristiwa (disconnected
di klien JavaScript) dinaikkan pada klien tetapi OnDisconnected
tidak pernah dipanggil di server. Diagram berikut mengasumsikan bahwa API transportasi tidak menyadari koneksi yang hilang, sehingga terdeteksi oleh fungsionalitas keepalive SignalR dan ConnectionSlow
peristiwa dinaikkan.
Pengaturan waktu habis dan keepalive
ConnectionTimeout
Nilai default , DisconnectTimeout
, dan KeepAlive
sesuai untuk sebagian besar skenario tetapi dapat diubah jika lingkungan Anda memiliki kebutuhan khusus. Misalnya, jika lingkungan jaringan Anda menutup koneksi yang menganggur selama 5 detik, Anda mungkin harus mengurangi nilai keepalive.
connectionTimeout
Pengaturan ini menunjukkan jumlah waktu untuk membiarkan koneksi transportasi terbuka dan menunggu respons sebelum menutupnya dan membuka koneksi baru. Nilai defaultnya adalah 110 detik.
Pengaturan ini hanya berlaku ketika fungsionalitas keepalive dinonaktifkan, yang biasanya hanya berlaku untuk transportasi polling panjang. Diagram berikut mengilustrasikan efek pengaturan ini pada koneksi transportasi polling panjang.
DisconnectTimeout
Pengaturan ini menunjukkan jumlah waktu untuk menunggu setelah koneksi transportasi hilang sebelum menaikkan Disconnected
peristiwa. Nilai default-nya adalah 30 detik. Saat Anda mengatur DisconnectTimeout
, KeepAlive
secara otomatis diatur ke 1/3 dari DisconnectTimeout
nilai.
KeepAlive
Pengaturan ini menunjukkan jumlah waktu untuk menunggu sebelum mengirim paket keepalive melalui koneksi menganggur. Nilai defaultnya adalah 10 detik. Nilai ini tidak boleh lebih dari 1/3 dari DisconnectTimeout
nilai.
Jika Anda ingin mengatur dan DisconnectTimeout
KeepAlive
, atur KeepAlive
setelah DisconnectTimeout
. Jika tidak, pengaturan Anda KeepAlive
akan ditimpa ketika DisconnectTimeout
secara otomatis diatur KeepAlive
ke 1/3 dari nilai batas waktu.
Jika Anda ingin menonaktifkan fungsionalitas keepalive, atur KeepAlive
ke null. Fungsionalitas keepalive secara otomatis dinonaktifkan untuk transportasi polling panjang.
Cara mengubah pengaturan batas waktu dan keepalive
Untuk mengubah nilai default untuk pengaturan ini, atur nilai tersebut di Application_Start
file Global.asax Anda, seperti yang diperlihatkan dalam contoh berikut. Nilai yang ditampilkan dalam kode sampel sama dengan nilai default.
protected void Application_Start(object sender, EventArgs e)
{
// Make long polling connections wait a maximum of 110 seconds for a
// response. When that time expires, trigger a timeout command and
// make the client reconnect.
GlobalHost.Configuration.ConnectionTimeout = TimeSpan.FromSeconds(110);
// Wait a maximum of 30 seconds after a transport connection is lost
// before raising the Disconnected event to terminate the SignalR connection.
GlobalHost.Configuration.DisconnectTimeout = TimeSpan.FromSeconds(30);
// For transports other than long polling, send a keepalive packet every
// 10 seconds.
// This value must be no more than 1/3 of the DisconnectTimeout value.
GlobalHost.Configuration.KeepAlive = TimeSpan.FromSeconds(10);
}
Cara memberi tahu pengguna tentang pemutusan sambungan
Dalam beberapa aplikasi, Anda mungkin ingin menampilkan pesan kepada pengguna ketika ada masalah konektivitas. Anda memiliki beberapa opsi tentang bagaimana dan kapan melakukan ini. Sampel kode berikut adalah untuk klien JavaScript menggunakan proksi yang dihasilkan.
connectionSlow
Tangani peristiwa untuk menampilkan pesan segera setelah SignalR mengetahui masalah koneksi, sebelum masuk ke mode koneksi ulang.$.connection.hub.connectionSlow(function() { notifyUserOfConnectionProblem(); // Your function to notify user. });
reconnecting
Tangani peristiwa untuk menampilkan pesan saat SignalR mengetahui pemutusan dan masuk ke mode menyambungkan kembali.$.connection.hub.reconnecting(function() { notifyUserOfTryingToReconnect(); // Your function to notify user. });
disconnected
Tangani peristiwa untuk menampilkan pesan ketika upaya untuk menyambungkan kembali telah kehabisan waktu. Dalam skenario ini, satu-satunya cara untuk membangun kembali koneksi dengan server lagi adalah dengan memulai ulang koneksi SignalR dengan memanggilStart
metode , yang akan membuat ID koneksi baru. Sampel kode berikut menggunakan bendera untuk memastikan bahwa Anda mengeluarkan pemberitahuan hanya setelah batas waktu koneksi ulang, bukan setelah akhir normal ke koneksi SignalR yang disebabkan oleh panggilanStop
metode .var tryingToReconnect = false; $.connection.hub.reconnecting(function() { tryingToReconnect = true; }); $.connection.hub.reconnected(function() { tryingToReconnect = false; }); $.connection.hub.disconnected(function() { if(tryingToReconnect) { notifyUserOfDisconnect(); // Your function to notify user. } });
Cara terus terhubung kembali
Dalam beberapa aplikasi, Anda mungkin ingin secara otomatis membuat ulang koneksi setelah hilang dan upaya untuk menyambungkan kembali telah kehabisan waktu. Untuk melakukannya, Anda dapat memanggil Start
metode dari penanganan aktivitas Anda Closed
(disconnected
penanganan aktivitas pada klien JavaScript). Anda mungkin ingin menunggu jangka waktu sebelum memanggil Start
untuk menghindari melakukan ini terlalu sering ketika server atau koneksi fisik tidak tersedia. Sampel kode berikut adalah untuk klien JavaScript menggunakan proksi yang dihasilkan.
$.connection.hub.disconnected(function() {
setTimeout(function() {
$.connection.hub.start();
}, 5000); // Restart connection after 5 seconds.
});
Masalah potensial yang perlu diperhatikan di klien seluler adalah bahwa upaya koneksi ulang berkelanjutan ketika server atau koneksi fisik tidak tersedia dapat menyebabkan pengurasan baterai yang tidak perlu.
Cara memutuskan sambungan klien dalam kode server
SignalR versi 1.1.1 tidak memiliki API server bawaan untuk memutus sambungan klien. Ada rencana untuk menambahkan fungsionalitas ini di masa mendatang. Dalam rilis SignalR saat ini, cara paling sederhana untuk memutuskan sambungan klien dari server adalah dengan menerapkan metode pemutusan sambungan pada klien dan memanggil metode tersebut dari server. Sampel kode berikut menunjukkan metode pemutusan sambungan untuk klien JavaScript menggunakan proksi yang dihasilkan.
var myHubProxy = $.connection.myHub
myHubProxy.client.stopClient = function() {
$.connection.hub.stop();
};
Peringatan
Keamanan - Baik metode ini untuk memutuskan koneksi klien maupun API bawaan yang diusulkan tidak akan mengatasi skenario klien yang diretas yang menjalankan kode berbahaya, karena klien dapat terhubung kembali atau kode yang diretas mungkin menghapus stopClient
metode atau mengubah apa yang dilakukannya. Tempat yang sesuai untuk menerapkan perlindungan stateful denial-of-service (DOS) bukan dalam kerangka kerja atau lapisan server, melainkan di infrastruktur front-end.