Saya merancang aplikasi web dan saya bertanya-tanya bagaimana merancang arsitektur untuk mengelola pengiriman email otomatis.
Saat ini saya memiliki fitur ini dibangun di aplikasi web saya dan email dikirim berdasarkan input / interaksi pengguna (seperti membuat pengguna baru). Masalahnya adalah bahwa menghubungkan langsung ke server mail membutuhkan beberapa detik. Meningkatkan aplikasi saya, ini akan menjadi leher botol yang signifikan di masa depan.
Apa cara terbaik untuk mengelola pengiriman sejumlah besar email otomatis dalam arsitektur sistem saya?
Tidak akan ada sejumlah besar email yang dikirim (maks. 2000 per hari). Email tidak perlu segera dikirim, lag hingga 10 menit tidak masalah.
Pembaruan: Antrian pesan telah diberikan sebagai jawaban, tetapi bagaimana ini akan dirancang? Apakah ini akan ditangani di aplikasi dan diproses selama periode tenang, atau apakah saya perlu membuat 'aplikasi email' atau layanan web baru untuk hanya mengelola antrian?
Jawaban:
Pendekatan umum, seperti Ozz sudah sebutkan , adalah antrian pesan . Dari perspektif desain, antrian pesan pada dasarnya adalah antrian FIFO , yang merupakan tipe data yang agak mendasar:
Apa yang membuat antrian pesan istimewa adalah bahwa sementara aplikasi Anda bertanggung jawab untuk antrian, proses yang berbeda akan bertanggung jawab untuk antrian. Dalam istilah antrian, aplikasi Anda adalah pengirim pesan, dan proses penghapusan adalah penerima. Keuntungan yang jelas adalah bahwa seluruh proses tidak sinkron, penerima bekerja secara independen dari pengirim, selama ada pesan untuk diproses. Kerugian yang jelas adalah bahwa Anda memerlukan komponen tambahan, pengirim, agar semuanya berfungsi.
Karena arsitektur Anda sekarang bergantung pada dua komponen yang bertukar pesan, Anda dapat menggunakan istilah komunikasi antar-proses yang bagus untuknya.
Bagaimana memperkenalkan antrian mempengaruhi desain aplikasi Anda?
Tindakan tertentu dalam aplikasi Anda menghasilkan email. Memperkenalkan antrian pesan berarti bahwa tindakan tersebut sekarang harus mendorong pesan ke antrian (dan tidak lebih). Pesan-pesan itu harus membawa jumlah minimum informasi mutlak yang diperlukan untuk membangun email ketika penerima Anda memprosesnya.
Format dan isi pesan
Format dan isi pesan Anda sepenuhnya terserah Anda, tetapi Anda harus mengingat semakin kecil semakin baik. Antrian Anda harus secepat mungkin untuk menulis dan memprosesnya, melemparkan sejumlah besar data ke dalamnya mungkin akan membuat kemacetan.
Selain itu beberapa layanan antrian berbasis cloud memiliki batasan ukuran pesan dan dapat membagi pesan yang lebih besar. Anda tidak akan melihat, pesan perpecahan akan disajikan sebagai satu ketika Anda memintanya, tetapi Anda akan dikenakan biaya untuk beberapa pesan (dengan asumsi tentu saja Anda menggunakan layanan yang memerlukan biaya).
Desain penerima
Karena kita berbicara tentang aplikasi web, pendekatan umum untuk receiver Anda adalah skrip cron sederhana. Itu akan berjalan setiap
x
menit (atau detik) dan itu akan:n
jumlah pesan dari antrian,Perhatikan bahwa saya mengatakan pop daripada mengambil atau mengambil, itu karena penerima Anda tidak hanya mendapatkan item dari antrian, tetapi juga menghapusnya (yaitu menghapusnya dari antrian atau menandainya sebagai diproses). Bagaimana persisnya itu akan terjadi tergantung pada implementasi Anda pada antrian pesan dan kebutuhan spesifik aplikasi Anda.
Tentu saja apa yang saya jelaskan pada dasarnya adalah operasi batch , cara paling sederhana untuk memproses antrian. Bergantung pada kebutuhan Anda, Anda mungkin ingin memproses pesan dengan cara yang lebih rumit (yang juga membutuhkan antrian yang lebih rumit).
Lalu lintas
Penerima Anda dapat mempertimbangkan lalu lintas pertimbangan dan menyesuaikan jumlah pesan yang diproses berdasarkan lalu lintas pada saat berjalan. Pendekatan sederhana adalah untuk memprediksi jam lalu lintas tinggi Anda berdasarkan data lalu lintas masa lalu dan dengan asumsi Anda pergi dengan skrip cron yang berjalan setiap
x
menit Anda bisa melakukan sesuatu seperti ini:Pendekatan yang sangat naif & kotor, tetapi berhasil. Jika tidak, baik, pendekatan lain adalah mencari tahu lalu lintas server Anda saat ini di setiap iterasi dan menyesuaikan jumlah item proses yang sesuai. Tolong jangan mengoptimalkan mikro jika itu tidak benar-benar diperlukan, Anda akan membuang-buang waktu.
Penyimpanan antrian
Jika aplikasi Anda sudah menggunakan database, maka satu tabel di atasnya akan menjadi solusi paling sederhana:
Sebenarnya tidak lebih rumit dari itu. Anda tentu saja dapat menjadikannya serumit yang Anda butuhkan, misalnya, Anda dapat menambahkan bidang prioritas (yang berarti bahwa ini bukan lagi antrian FIFO, tetapi jika Anda benar-benar membutuhkannya, siapa yang peduli?). Anda juga bisa membuatnya lebih sederhana, dengan melewatkan bidang yang telah diproses (tetapi kemudian Anda harus menghapus baris setelah Anda memprosesnya).
Tabel basis data akan ideal untuk 2000 pesan per hari, tetapi mungkin tidak akan baik untuk jutaan pesan per hari. Ada sejuta faktor untuk dipertimbangkan, segala sesuatu di infrastruktur Anda berperan dalam skalabilitas keseluruhan aplikasi Anda.
Bagaimanapun, dengan asumsi Anda telah mengidentifikasi antrian berbasis basis data sebagai hambatan, langkah selanjutnya adalah melihat layanan berbasis cloud. Amazon SQS adalah layanan yang saya gunakan, dan melakukan apa yang dijanjikan. Saya yakin ada beberapa layanan serupa di luar sana.
Antrian berdasarkan memori juga sesuatu yang perlu dipertimbangkan, terutama untuk antrian yang berumur pendek. memcached sangat baik sebagai penyimpanan antrian pesan.
Penyimpanan apa pun yang Anda putuskan untuk dijadikan antrian, cerdas dan abstraksi. Baik pengirim maupun penerima Anda tidak terikat pada penyimpanan tertentu, jika tidak beralih ke penyimpanan lain di lain waktu akan menjadi PITA lengkap.
Pendekatan kehidupan nyata
Saya membuat antrian pesan untuk email yang sangat mirip dengan apa yang Anda lakukan. Itu pada proyek PHP dan saya membangunnya di sekitar Zend Queue , komponen dari Zend Framework yang menawarkan beberapa adapter untuk penyimpanan yang berbeda. Penyimpanan saya di mana:
Pesan saya sesederhana mungkin, aplikasi saya membuat array kecil dengan informasi penting (
[user_id, reason]
). Toko pesan adalah versi serial array itu (pertama itu adalah format serialisasi internal PHP, kemudian JSON, saya tidak ingat mengapa saya beralih). Inireason
adalah konstanta dan tentu saja saya punya meja besar di suatu tempat yang memetakanreason
penjelasan yang lebih lengkap (saya berhasil mengirim sekitar 500 email ke klien dengan crypticreason
daripada pesan yang lebih lengkap satu kali).Bacaan lebih lanjut
Standar:
Alat:
Berbunyi menarik:
sumber
Anda membutuhkan semacam sistem antrian.
Salah satu cara sederhana bisa dengan menulis ke tabel database dan memiliki baris proses aplikasi eksternal lain dalam tabel ini, tetapi ada banyak teknologi antrian lain yang bisa Anda gunakan.
Anda bisa memiliki kepentingan pada email sehingga yang tertentu segera ditindaklanjuti (misalnya pengaturan ulang kata sandi), dan yang kurang penting dapat dikumpulkan untuk dikirim nanti.
sumber
Sebagai tambahan untuk antrian, hal kedua yang harus Anda pertimbangkan adalah mengirim email melalui layanan khusus: MailChimp, misalnya (saya tidak berafiliasi dengan layanan ini). Kalau tidak, banyak layanan surat, seperti gmail, akan segera mengirimkan surat Anda ke folder spam.
sumber
Saya telah memodelkan sistem antrian saya di 2 tabel berbeda sebagai;
Ada 1-1 hubungan antara tabel-tabel ini.
Tabel pesan untuk menyimpan konten pesan. Konten aktual (Kepada, CC, BCC, Subjek, Badan, dll.) Diserialisasi ke bidang Grafik dalam format XML. Lainnya Dari, Informasi hanya digunakan untuk melaporkan masalah tanpa deserializing grafik. Memisahkan tabel ini memungkinkan untuk mempartisi konten tabel ke penyimpanan disk yang berbeda. Setelah Anda siap untuk mengirim pesan, Anda perlu membaca semua informasi karena itu tidak ada salahnya membuat cerita bersambung semua konten ke satu kolom dengan indeks kunci utama.
MessageState meja untuk menyimpan keadaan isi pesan dengan tambahan informasi berdasarkan tanggal. Memisahkan tabel ini memungkinkan mekanisme akses cepat dengan indeks tambahan pada penyimpanan IO cepat. Kolom lain sudah cukup jelas.
Anda bisa menggunakan kumpulan utas terpisah yang memindai tabel ini. Jika aplikasi dan kumpulan hidup dalam mesin yang sama Anda bisa menggunakan kelas EventWaitHandle untuk memberi sinyal kumpulan dari aplikasi tentang sesuatu yang dimasukkan tabel ini, jika tidak secara berkala memindai dengan batas waktu adalah yang terbaik.
sumber