Melalui artikel ini, kami terutama akan menjelaskan masalah yang dihadapi dalam pemrosesan asinkron Servlet 3.0 dalam pengembangan Java dan solusi. Berikut ini adalah konten spesifik:
Servlet 3.0 telah mulai memberikan asynccontext untuk mendukung pemrosesan permintaan yang tidak sinkron. Jadi apa manfaat yang dapat dibawa oleh pemrosesan permintaan yang tidak sinkron?
Secara umum, cara penanganan wadah web adalah untuk menetapkan utas untuk setiap permintaan. Kita semua tahu bahwa pembuatan utas bukan tanpa biaya, dan kumpulan wadah web memiliki batas atas.
Masalah yang sangat dapat diprediksi adalah bahwa dalam kondisi beban tinggi, kumpulan utas ditempati, sehingga permintaan selanjutnya hanya dapat ditunggu. Jika Anda tidak beruntung, klien akan melaporkan kesalahan batas waktu tunggu.
Sebelum asynccontext muncul, satu -satunya cara untuk menyelesaikan masalah ini adalah dengan memperluas kumpulan utas wadah web.
Tapi masih ada masalah dengan ini, pertimbangkan skenario berikut:
Ada wadah web dengan ukuran kumpulan utas 200. Ada aplikasi web yang memiliki dua servlet, waktu yang dibutuhkan Servlet-A untuk menangani satu permintaan adalah 10s, dan waktu yang dibutuhkan Servlet-B untuk menangani satu permintaan adalah 1s.
Sekarang kami menemukan beban tinggi, dengan lebih dari 200 permintaan untuk Servlet-A. Jika Servlet-B diminta saat ini, kami akan menunggu karena semua utas HTTP telah ditempati oleh Servlet-A.
Pada saat ini, insinyur menemukan masalah dan memperluas ukuran kumpulan benang menjadi 400, tetapi beban terus naik. Sekarang ada 400 permintaan untuk Servlet-A, dan Servlet-B masih belum dapat menanggapi.
Pernahkah Anda melihat masalahnya? Karena utas HTTP dan utas pekerja digabungkan bersama, itu akan mengisi utas HTTP ketika sejumlah besar permintaan dibuat untuk operasi yang memakan waktu, yang mengakibatkan seluruh wadah web tidak dapat merespons.
Namun, jika kita menggunakan asynccontext, kita dapat menyerahkan operasi yang memakan waktu ke utas lain, sehingga utas HTTP akan dilepaskan dan kita dapat menangani permintaan lain.
Perhatikan bahwa hanya menggunakan asynccontext yang dapat mencapai efek yang disebutkan di atas. Jika Anda langsung menggunakan utas baru () atau metode serupa, utas HTTP tidak akan dikembalikan ke wadah.
Berikut adalah contoh resmi:
@WebServlet(urlPatterns={"/asyncservlet"}, asyncSupported=true)public class AsyncServlet extends HttpServlet { /* ... Same variables and init method as in SyncServlet ... */ @Override public void doGet(HttpServletRequest request, HttpServletResponse response) { response.setContentType ("Teks/html; charset = utf-8"); final asynccontext acontext = request.startasync (); acontext.start (new runnable () {public void run () {string param = acontext.getRequest (). getParameter ("param"); string result = resource.process (param); httpservletResponse response = acontext.getResponse (); / * ... cetak respons ... * / }} perangkap
Dalam contoh resmi ini, setiap utas HTTP akan membuka utas pekerja lain untuk memproses permintaan, dan kemudian mengembalikan utas HTTP ke wadah web. Tapi lihatlah metode javadoc dari asynccontext.start ():
Menyebabkan wadah mengirim utas, mungkin dari kumpulan utas yang dikelola, untuk menjalankan runnable yang ditentukan.
Bahkan, tidak ada peraturan di sini dari mana utas pekerja berasal. Mungkin ini adalah kumpulan utas lain selain kumpulan utas http? Atau hanya kumpulan utas HTTP?
Artikel yang terbatas dari asynccontext.start () membaca: wadah web yang berbeda memiliki implementasi yang berbeda untuk ini, tetapi Tomcat sebenarnya menggunakan kumpulan utas HTTP untuk menangani asynccontext.start ().
Ini berarti bahwa kami awalnya ingin melepaskan utas HTTP, tetapi sebenarnya tidak, karena utas HTTP masih digunakan sebagai utas pekerja, tetapi utas ini tidak sama dengan utas HTTP yang menerima permintaan tersebut.
Kita juga dapat melihat kesimpulan ini melalui tolok ukur JMeter dari AsyncServlet1 dan SyncServlet, dan hasil dari dua throughput adalah serupa. Metode Mulai: Mulai Utama, dan kemudian gunakan JMeter untuk memulai Benchmark.jmx (HTTP Thread Pool = 200 di bawah Konfigurasi Default Tomcat).
Menggunakan ExecutorService
Saya melihat sebelumnya bahwa Tomcat tidak mempertahankan kumpulan utas pekerja secara terpisah, jadi kita harus menemukan cara untuk melakukannya sendiri, lihat AsyncServlet2, yang menggunakan ExecutorService dengan kumpulan utas untuk menangani asynccontext.
Cara lain
Oleh karena itu, tidak ada cara tetap untuk menggunakan asynccontext. Anda dapat menggunakan berbagai metode untuk menghadapinya sesuai dengan kebutuhan aktual. Untuk alasan ini, Anda memerlukan pengetahuan tentang pemrograman bersamaan Java.
Kesalahpahaman kinerja
Tujuan dari asynccontext bukan untuk meningkatkan kinerja, juga tidak secara langsung memberikan peningkatan kinerja. Ini memberikan mekanisme untuk memisahkan utas HTTP dan utas pekerja, sehingga meningkatkan responsif wadah web.
Namun, asynccontext dapat meningkatkan kinerja di beberapa titik, tetapi ini tergantung pada bagaimana kode Anda ditulis.
Misalnya: Jumlah kumpulan utas HTTP dalam wadah web adalah 200, dan servlet menggunakan kumpulan utas 300 pekerja untuk menangani asynccontext.
Dibandingkan dengan Metode Sinkronisasi Pekerjaan Thread Pekerja = HTTP Thread Pool = 200, dalam hal ini kami memiliki kumpulan utas pekerja sebesar 300, jadi itu pasti akan membawa beberapa peningkatan kinerja (bagaimanapun juga, ada lebih banyak orang yang bekerja).
Sebaliknya, jika jumlah utas pekerja adalah <= jumlah utas HTTP, tidak akan ada peningkatan kinerja, karena hambatan untuk permintaan pemrosesan ada di utas pekerja.
Anda dapat memodifikasi ukuran kumpulan utas dari asyncservlet2 dan membandingkannya dengan hasil patokan syncservlet untuk memverifikasi kesimpulan ini.
Jangan berpikir bahwa kumpulan utas pekerja harus lebih besar dari kumpulan utas HTTP. Alasannya adalah sebagai berikut:
Dua tanggung jawab berbeda. Salah satunya adalah bahwa wadah web digunakan untuk menerima permintaan eksternal , dan yang lainnya adalah memproses logika bisnis.
Membuat utas datang dengan biaya. Jika kumpulan utas HTTP sudah besar, maka membuat kumpulan utas pekerja yang lebih besar akan menyebabkan terlalu banyak saklar konteks dan overhead memori.
Tujuan dari asynccontext adalah untuk melepaskan utas HTTP untuk menghindari penggunaan operasi jangka panjang dan dengan demikian menyebabkan wadah web tidak dapat merespons.
Jadi dalam kebanyakan kasus, kumpulan utas pekerja tidak akan sangat besar, dan kumpulan utas pekerja yang berbeda akan dibangun sesuai dengan bisnis yang berbeda.
Misalnya: Ukuran kumpulan benang wadah web adalah 200, dan ukuran kumpulan utas pekerja adalah 10 untuk servlet lambat. Dengan cara ini, tidak peduli berapa banyak permintaan yang digunakan untuk memperlambat operasi, itu tidak akan mengisi utas HTTP dan menyebabkan permintaan lain tidak dapat diproses.