Hari ini saya akan memberi tahu Anda mengapa pengiriman outsourcing tidak selalu baik, mengapa Anda memerlukan transparansi proses dan bagaimana kami membuat platform dalam satu setengah tahun yang membantu kurir kami mengirimkan pesanan. Saya juga akan membagikan tiga cerita dari dunia pembangunan.
Dalam foto adalah tim platform kurir sepuluh bulan lalu. Pada masa itu, dia ditempatkan di satu ruangan. Sekarang ada 5 kali lebih banyak dari kita.
Mengapa kami melakukan semua ini
Saat mengembangkan platform kurir, kami ingin meningkatkan tiga hal utama.
Yang pertama adalah kualitas . Ketika kami bekerja dengan layanan pengiriman eksternal, kualitas tidak dapat dikontrol. Perusahaan kontraktor berjanji bahwa akan ada pengiriman ini dan itu, tetapi sejumlah pesanan mungkin tidak terkirim. Dan kami ingin mengurangi persentase keterlambatan seminimal mungkin, sehingga hampir semua pesanan dikirim tepat waktu.
Kedua adalah transparansi... Ketika terjadi kesalahan (ada transfer, tenggat waktu), maka kami tidak tahu mengapa itu terjadi. Kita tidak bisa pergi dan berkata: "Teman-teman, mari kita lakukan seperti ini." Kami sendiri tidak melihat, dan kami tidak dapat menunjukkan hal tambahan apa pun kepada klien. Misalnya, pesanan akan sampai bukan pada pukul delapan, melainkan dalam waktu 15 menit. Ini karena tidak ada tingkat transparansi dalam proses tersebut.
Ketiga adalah uang... Saat kami bekerja dengan kontraktor, ada kontrak yang menjelaskan jumlahnya. Dan kami dapat mengubah angka-angka ini dalam kerangka kontrak. Dan ketika kami bertanggung jawab atas seluruh proses dari a hingga z, maka Anda dapat melihat bagian mana dari sistem yang dirancang tidak menguntungkan secara ekonomi. Dan Anda dapat, misalnya, mengubah penyedia SMS atau format alur dokumen. Atau Anda mungkin memperhatikan bahwa kurir memiliki jarak tempuh yang terlalu tinggi. Dan jika Anda membangun rute lebih dekat, maka pada akhirnya Anda akan dapat mengirimkan lebih banyak pesanan. Berkat ini, Anda juga dapat menghemat uang - pengiriman akan menjadi lebih efisien.
Ini adalah tiga gol yang kami tetapkan di atas segalanya.
Seperti apa platform itu
Mari kita lihat apa yang kita punya.
Gambar menunjukkan diagram proses. Kami memiliki gudang besar yang menampung ratusan ribu pesanan. Truk-truk yang penuh dengan pesanan meninggalkan setiap gudang pada malam hari. Mungkin ada 5-6 ribu pesanan. Truk-truk ini berjalan ke gedung-gedung kecil yang disebut pusat pemilahan. Di dalamnya, dalam beberapa jam, tumpukan besar pesanan berubah menjadi tumpukan kecil untuk kurir. Dan ketika kurir tiba dengan mobil di pagi hari, setiap kurir tahu bahwa dia perlu mengambil banyak dengan kode QR ini, memasukkannya ke mobilnya dan pergi untuk mengirim.
Dan backend yang ingin saya bicarakan di artikel ini adalah tentang bagian terakhir dari proses saat pesanan dibawa ke pelanggan. Semua itu sebelum ini, untuk saat ini, kita akan kesampingkan.
Bagaimana kurir melihatnya
Kurir memiliki aplikasi Android yang ditulis dalam React Native. Dan dalam aplikasi ini, mereka melihat sepanjang hari. Mereka memahami dengan jelas urutannya: alamat mana yang harus dituju terlebih dahulu, yang mana nanti. Kapan harus menelepon pelanggan, kapan menerima pengembalian ke pusat penyortiran, bagaimana memulai hari, bagaimana mengakhirinya. Mereka melihat semuanya dalam aplikasi dan secara praktis tidak mengajukan pertanyaan yang tidak perlu. Kami banyak membantu mereka. Pada dasarnya mereka hanya mengerjakan tugas.
Selain itu, ada kontrol di platform. Ini adalah panel admin multifungsi yang kami gunakan kembali dari layanan Yandex lain. Di area admin ini, Anda dapat mengonfigurasi status sistem. Kami mengunggah data tentang kurir baru di sana, mengubah interval kerja. Kami dapat menyesuaikan proses pembuatan tugas untuk besok. Hampir semua yang Anda butuhkan diatur.
Ngomong-ngomong, tentang backend. Kami di Pasar sangat menyukai Java, kebanyakan versi 11. Dan semua layanan backend, yang akan dibahas, ditulis dalam Java.
Arsitektur
Ada tiga node utama dalam arsitektur platform kami. Yang pertama bertanggung jawab untuk komunikasi dengan dunia luar. Aplikasi kurir βmengetukβ penyeimbang, yang dibawa keluar, berkomunikasi dengannya menggunakan API HTTP JSON standar. Faktanya, node ini bertanggung jawab atas semua logika hari ini, ketika kurir mentransfer sesuatu, membatalkan sesuatu, mengeluarkan pesanan, menerima tugas baru.
Node kedua adalah layanan yang berkomunikasi dengan layanan internal Yandex. Semua layanan adalah layanan RESTful klasik dengan komunikasi standar. Ketika Anda memesan di Market, setelah beberapa saat sebuah dokumen dalam format JSON akan datang kepada Anda, di mana semuanya akan tertulis: kapan kami mengirimkan, kepada siapa kami mengirimkan, pada interval berapa. Dan kami akan menyimpan status ini ke database. Itu mudah.
Selain itu, node kedua juga berkomunikasi dengan layanan internal lainnya, bukan Market, tetapi Yandex. Misalnya, untuk memperjelas geocoordinate, kita pergi ke geoservice. Untuk mengirim notifikasi push, kita masuk ke layanan yang mengirimkan push dan SMS. Kami menggunakan layanan lain untuk otorisasi. Layanan lain untuk menghitung perutean untuk besok. Dengan demikian, semua komunikasi dengan layanan internal dilakukan.
Node ini juga merupakan titik masuk, ia memiliki API yang diketuk oleh panel admin kami. Ia memiliki titik akhirnya sendiri, yang disebut, katakanlah, / partner. Dan panel admin kami, seluruh status sistem, dikonfigurasi melalui komunikasi dengan layanan ini.
Node ketiga adalah basis tugas latar belakang. Di sini Quartz 2 digunakan, ada tugas yang diluncurkan pada mahkota dengan kondisi berbeda untuk titik berbeda, untuk pusat penyortiran berbeda. Ada tugas memperbarui hari, tugas menutup hari, memulai hari baru.
Dan di pusat segalanya adalah database, yang, pada kenyataannya, menyimpan semua negara bagian. Semua layanan termasuk dalam satu database.
toleransi kesalahan
Yandex memiliki beberapa pusat data, dan layanan kami didistribusikan secara regional di tiga pusat data. Seperti apa rupanya.
Basis data terdiri dari tiga host, masing-masing di pusat datanya sendiri. Satu tuan rumah adalah tuannya, dua lainnya adalah replika. Kami menulis kepada master, kami membaca dari baris. Semua layanan Java lainnya juga merupakan proses Java yang berjalan di beberapa pusat data.
Salah satu node adalah API kami. Ini berjalan di ketiga pusat data, karena aliran pesan lebih besar daripada dari layanan internal. Selain itu, tata letak seperti itu memungkinkan Anda untuk menskalakan secara horizontal dengan cukup mudah.
Misalnya, jika lalu lintas masuk Anda meningkat sembilan kali lipat, Anda dapat mengoptimalkan, tetapi Anda juga dapat "membanjiri" bisnis ini dengan besi dengan membuka lebih banyak node yang akan memproses lalu lintas masuk.
Penyeimbang hanya perlu membagi lalu lintas menjadi lebih banyak poin yang memenuhi permintaan. Dan sekarang, misalnya, kami tidak memiliki satu node, tetapi dua node di setiap pusat data.
Arsitektur kami memungkinkan kami untuk mengatasi bahkan kasus-kasus seperti penutupan salah satu pusat data. Misalnya, kami memutuskan untuk melakukan latihan dan mematikan pusat data di Vladimir - dan layanan kami tetap bertahan, tidak ada yang berubah. Host database yang ada di sana menghilang, dan layanan tetap beroperasi.
Penyeimbang memahami setelah beberapa saat: ya, saya tidak memiliki satu pun host langsung yang tersisa di pusat data ini, dan tidak lagi mengalihkan lalu lintas ke sana.
Semua layanan di Yandex diatur dengan cara yang sama, kita semua tahu cara bertahan dari kegagalan salah satu pusat data. Kami telah menjelaskan bagaimana ini diterapkan, apa degradasi yang anggun, dan bagaimana layanan Yandex menangani penutupan salah satu pusat data .
Jadi itulah arsitektur. Dan sekarang ceritanya dimulai.
Cerita pertama - tentang Yandex.Rover
Baru-baru ini kami mengadakan Konferensi lain, di mana Rover mendapat banyak perhatian. Saya akan melanjutkan topik.
Suatu ketika orang-orang dari tim Yandex.Rover mendatangi kami dan menawarkan untuk menguji hipotesis bahwa orang ingin menerima pesanan dengan cara yang luar biasa.
Yandex.Rover adalah robot kecil seukuran anjing biasa. Anda dapat menaruh makanan di sana, beberapa kotak pesanan - dia akan berkeliling kota dan membawa pesanan tanpa bantuan manusia. Ada lidar, robot mengerti posisinya di luar angkasa. Dia tahu bagaimana mengirimkan pesanan kecil.
Dan kami berpikir: mengapa tidak? Kami mengklarifikasi detail eksperimen: pada saat itu perlu dilakukan pengujian hipotesis bahwa orang-orang akan menyukainya. Dan kami memutuskan untuk mengirimkan 50 pesanan dalam satu setengah minggu dalam mode yang sangat ringan.
Kami datang dengan alur yang paling sederhana, ketika seseorang menerima SMS dengan proposal untuk metode pengiriman non-standar - bukan kurir yang akan membawanya, tetapi Rover. Seluruh eksperimen berlangsung di halaman Yandex. Pria itu memilih pintu masuk yang akan dilalui Rover. Ketika robot tiba, tutupnya dibuka, klien mengambil pesanan, menutup tutupnya, dan Rover pergi untuk memesan pesanan baru. Itu mudah.
Kemudian kami pergi ke tim Rover untuk menegosiasikan API.
Ada metode sederhana dalam Rover API: buka tutupnya, tutup tutupnya, pergi ke titik tertentu, dapatkan status. Klasik. Juga JSON. Sangat sederhana.
Yang juga sangat penting: cerita kecil dan cerita besar lainnya paling baik dilakukan melalui fitur flags. Faktanya, Anda memiliki tombol untuk mengaktifkan cerita ini dalam produksi. Saat Anda tidak lagi membutuhkannya, percobaan berhasil diselesaikan atau tidak berhasil, atau Anda melihat beberapa bug, Anda baru saja menebangnya. Dan Anda tidak perlu melakukan penerapan lain dari versi baru kode untuk produksi. Hal ini membuat hidup jauh lebih mudah.
Tampaknya semuanya sederhana dan semuanya harus berfungsi. Bahkan tidak ada yang bisa dikembangkan di sana selama dua minggu, Anda bisa melakukannya dalam beberapa hari. Tapi lihat di mana anjing itu dikuburkan.
Semua proses sebagian besar sinkron. Pria itu menekan tombol, tutupnya terbuka. Pria itu menekan tombol, tutupnya menutup. Tetapi salah satu dari proses ini tidak sinkron. Pada saat Rover mendatangi Anda, Anda perlu memiliki semacam proses latar belakang yang akan melacak bahwa robot telah kembali ke intinya.
Dan saat ini kami akan mengirim SMS ke orang tersebut, misalnya, bahwa Rover sedang menunggu di tempat itu. Ini tidak dapat dilakukan secara serempak, dan Anda harus menyelesaikan masalah ini dengan cara apa pun.
Ada banyak pendekatan berbeda. Kami telah membuatnya sesederhana mungkin.
Kami memutuskan bahwa kami dapat menjalankan thread atau tugas Java latar belakang yang paling umum di Executer. Utas latar belakang ini segera diluncurkan untuk melacak prosesnya. Dan segera setelah proses selesai, kami mengirimkan notifikasi.
Misalnya, tampilannya seperti ini. Ini praktis merupakan salinan dari kode produksi, dengan pengecualian komentar yang dihilangkan. Tapi ada tangkapan. Anda tidak dapat membuat sistem yang serius dengan cara ini. Katakanlah kami meluncurkan versi baru ke backend. Host reboot, status hilang, dan hanya itu, Rover pergi ke tak terhingga, tidak ada orang lain yang melihatnya.
Tapi kenapa? Jika kami tahu bahwa tujuan kami adalah mengirimkan 50 pesanan dalam satu setengah minggu, kami memilih waktu ketika kami memantau backend. Jika terjadi kesalahan, Anda dapat mengubah sesuatu secara manual. Untuk tugas seperti itu, solusi ini lebih dari cukup. Dan inilah pesan moral dari cerita pertama.
Ada situasi di mana Anda perlu membuat versi minimum dari fungsionalitas tersebut. Tidak perlu memagari taman dan melakukan rekayasa berlebihan. Lebih baik membuatnya seasing mungkin. Agar tidak terlalu banyak mengubah logika objek internal. Dan kompleksitas yang berlebihan, hutang teknis yang tidak perlu tidak menumpuk.
Cerita kedua - tentang database
Tapi pertama-tama, beberapa kata tentang bagaimana entitas utama disusun. Ada layanan Yandex.Routing yang membuat rute untuk kurir di penghujung hari.
Setiap rute terdiri dari titik-titik di peta. Dan di setiap titik kurir memiliki tugas. Ini bisa menjadi tugas untuk mengeluarkan pesanan, atau menelepon klien, atau di pagi hari memuat di pusat penyortiran, mengambil semua pesanan.
Selain itu, klien menerima tautan pelacakan di pagi hari. Mereka dapat membuka peta dan melihat bagaimana kurir tersebut pergi ke tempat mereka. Klien juga dapat memilih pengiriman melalui Rover, yang saya sebutkan sebelumnya.
Sekarang mari kita lihat bagaimana entitas ini dapat ditampilkan di database. Ini dilakukan, misalnya, seperti ini.
Ini adalah model data yang sangat rapi. Kami tidak menemukan satu entitas baru, dan kami tidak meruntuhkan entitas yang sudah ada dengan kuat.
Diagram menunjukkan bahwa panah dari bawah ke atas menunjukkan rute kurir, tahu siapa kurir itu rutenya. Tanda rute kurir berisi tautan ID kurir. Dan pelat atas tidak mengetahui hal ini. Kami memiliki konektivitas yang paling sederhana, tidak ada persimpangan besar antar entitas. Ketika semua orang tahu tentang setiap orang, itu lebih sulit dikendalikan dan, kemungkinan besar, akan ada redundansi. Oleh karena itu, kami memiliki skema yang paling sederhana.
Satu-satunya "pembunuhan berlebihan" yang kami buat di awal pembuatan platform adalah ini. Kami memiliki satu jenis tugas pengiriman. Tapi kami sadar di masa depan akan ada tugas lain. Dan kami memasukkan sedikit fleksibilitas arsitektural: kami memiliki tugas, dan salah satu jenis tugas tersebut adalah pengiriman pesanan.
Kemudian kami menambahkan pelacakan dan Rover. Hanya dua tablet. Dalam pelacakan, kurir mengirimkan koordinatnya, kami mencatatnya di piring terpisah. Dan ada order tracking dengan model negaranya sendiri, ada tambahannya, seperti "SMS tersisa / tidak kunjung hilang". Anda tidak boleh menambahkan ini langsung ke tugas. Lebih baik meletakkannya di piring terpisah, karena pelacakan ini tidak diperlukan untuk semua jenis tugas.
Di Rover - koordinat dan pengirimannya. Pengiriman kami oleh Rover seperti melacak Rover. Anda dapat menambahkannya ke urutan pelacakan, tetapi mengapa? Lagi pula, saat kami menyingkirkan eksperimen ini, saat dimatikan, opsi ini akan selamanya tetap menjadi inti dari pelacakan. Akan ada bidang kosong.
Mungkin timbul pertanyaan: mengapa membuat pelat dengan koordinat? One Rover mengirimkan lima pesanan sehari. Anda tidak perlu menyimpan koordinat dalam database, Anda cukup membuka Rover API dan mendapatkannya saat runtime.
Intinya adalah ini dilakukan pada awalnya. Tanda ini tidak ada, kami segera pergi ke kebaktian dan mengambil semuanya. Namun selama pengujian, kami melihat banyak orang membuka peta dengan rolling Rover, dan beban pada layanan ini meningkat berkali-kali lipat. Katakanlah tujuh orang membukanya. Dan ada di halaman setiap dua detik Java Script meminta koordinat. Dan rekan kerja menulis kepada kami dalam obrolan: βDari mana datangnya beban seperti itu? Anda memiliki satu orang di sana untuk bermain skate. "
Dan setelah itu kami menambahkan tanda. Kami mulai menambahkan koordinat di sana, waktu penerimaannya. Dan sekarang, jika orang datang kepada kami terlalu sering untuk koordinat dan dua detik belum berlalu sejak penerimaan terakhir, kami mengambilnya dari piring. Ternyata cache seperti itu di tingkat database.
Cerita ini bisa diselesaikan dengan 20 tabel. Dua meja dapat digunakan: kurir dan pesanan. Tetapi dalam kasus pertama, itu akan menjadi rekayasa yang berlebihan, dan dalam kasus kedua, akan terlalu sulit untuk dipertahankan. Logika yang kompleks, sulit untuk diuji.
Dan selanjutnya. Struktur basis data, yang kami buat satu setengah tahun yang lalu, inti dari entitas ini tetap tidak berubah hingga hari ini. Dan kami sangat beruntung bahwa kami dapat memilih entitas seperti itu yang basisnya tidak perlu dilakukan ulang. Tidak perlu menggambar ulang database secara signifikan, melakukan migrasi kompleks, kemudian menggulung rilis ini, mengujinya untuk waktu yang sangat lama, dan kemudian mengubah struktur root.
Inti dari cerita ini adalah bahwa ada aspek-aspek yang lebih baik diperhatikan secara ekstra. Yang pertama adalah memberikan perhatian khusus pada struktur API dan database . Cobalah untuk memperhatikan entitas seperti apa yang Anda miliki dalam kehidupan nyata. Cobalah untuk mendigitalkan struktur ini dengan cara yang sama. Cobalah untuk tidak memendekkannya terlalu banyak, jangan terlalu banyak mengembangkannya.
Kedua, ada kesalahan yang mahal untuk diperbaiki . Kesalahan di tingkat API lebih sulit diperbaiki daripada kesalahan di tingkat database karena biasanya ada banyak klien yang menggunakan API. Dan ketika Anda banyak mengubah API, Anda harus:
- menjangkau semua klien, memastikan kompatibilitas ke belakang;
- luncurkan API baru, alihkan semua klien ke API baru;
- potong kode lama tentang klien, potong kode lama di backend.
Ini sangat mahal.
Kesalahan dalam kode umumnya tidak masuk akal dibandingkan dengan ini. Anda baru saja menulis ulang kodenya, menjalankan tes. Tes berwarna hijau - Anda telah mendorong ke master. Berikan perhatian khusus pada API database.
Dan tidak peduli seberapa keras Anda mencoba melacak database, lama kelamaan akan berubah menjadi sesuatu yang tidak bisa diatur. Pada tangkapan layar, Anda dapat melihat sepersepuluh dari database kami, yang sekarang sudah ada.
Ada satu nasihat. Saat Anda mengembangkan sesuatu dengan sangat cepat, ada ketidakakuratan dalam database, terkadang kunci asing hilang atau bidang duplikat muncul. Karena itu, terkadang, setiap dua atau tiga bulan sekali, lihat saja di pangkalan. Intellij IDEA yang sama dapat menghasilkan sirkuit yang dingin. Dan di sana Anda bisa melihat semuanya.
Database Anda harus memadai. Sangat mudah untuk membuat daftar enam tiket dalam satu jam: tambahkan kunci asing di sini, di sana indeks. Tidak peduli seberapa keras Anda mencoba, beberapa puing pasti akan menumpuk.
Cerita ketiga tentang kualitas
Ada hal-hal yang paling baik dilakukan dengan baik sejak awal. Penting untuk bertindak sesuai dengan prinsip "lakukan secara normal, itu akan baik-baik saja".
Misalnya, kami memiliki satu proses yang penting untuk platform. Sepanjang hari kami mengumpulkan pesanan untuk besok, tetapi di malam hari muncul catatan bahwa setelah pukul 22:00 kami tidak mengumpulkan pesanan, tetapi sebelum pukul 01:00 kami bersiap untuk besok. Kemudian distribusi pesanan ke pusat penyortiran dimulai. Kami pergi ke Yandex. Perutean, itu membangun rute.
Dan jika pekerjaan persiapan ini gagal, seluruh hari esok dipertanyakan. Besok kurir tidak punya tempat tujuan. Mereka belum menciptakan negara. Ini adalah proses paling kritis dalam platform kami. Dan proses penting seperti itu tidak dapat dilakukan dengan basis sisa, dengan sumber daya yang minimal.
Saya ingat kami memiliki waktu ketika proses ini gagal, dan selama beberapa minggu hampir setengah dari tim dalam obrolan menyelesaikan masalah ini, semua orang menghemat hari, mengerjakan ulang sesuatu, memulai kembali.
Kami memahami bahwa jika proses tidak selesai dari pukul sepuluh malam hingga satu pagi, maka pusat penyortiran bahkan tidak akan tahu cara menyortir pesanan, ke dalam tumpukan mana. Semuanya akan menganggur di sana. Kurir akan keluar nanti dan kami akan mengalami kegagalan kualitas.
Lebih baik melakukan proses tersebut sebaik mungkin segera, memikirkan setiap langkah di mana ada sesuatu yang salah. Dan letakkan sedotan dalam jumlah maksimal di mana-mana.
Saya akan memberi tahu Anda tentang salah satu opsi bagaimana Anda dapat menyiapkan proses semacam itu.
Proses ini multi-komponen. Penghitungan rute dan publikasinya dapat dipecah menjadi beberapa bagian dan, misalnya, antrean dapat dibuat. Kemudian kami memiliki beberapa antrian yang bertanggung jawab atas bagian pekerjaan yang diselesaikan. Dan ada konsumen dalam antrian ini yang duduk dan menunggu pesan.
Misalnya, hari sudah berakhir, kami ingin menghitung rute untuk besok. Kami mengirim permintaan pertama-tama: buat tugas dan mulai penghitungan. Konsumen mengambil pesan pertama, pergi ke layanan perutean. Ini adalah API asinkron. Konsumen menerima tanggapan bahwa tugas telah diambil untuk bekerja.
Dia meletakkan ID ini di pangkalan, dan menempatkan pekerjaan baru dalam antrian dengan tugas dalam pemrosesan. Dan itu saja. Pesan menghilang dari antrian pertama, konsumen kedua "bangun". Dia mengambil tugas kedua untuk diproses, dan tugasnya adalah secara teratur pergi ke perutean dan memeriksa apakah tugas ini belum selesai untuk perhitungan.
Tugas tingkat "membuat rute untuk 200 kurir yang akan mengirimkan beberapa ribu pesanan di Moskow" membutuhkan waktu setengah jam hingga satu jam. Ini memang tugas yang sangat sulit. Dan orang-orang dari layanan ini sangat keren, mereka memecahkan masalah algoritmik paling rumit yang membutuhkan banyak waktu.
Akibatnya, konsumen antrian kedua hanya akan memeriksa, memeriksa, memeriksa. Setelah beberapa waktu, tugas tersebut akan selesai. Ketika tugas selesai, kami menerima jawaban berupa struktur rute dan shift esok hari yang diperlukan untuk kurir.
Kami menempatkan apa yang telah dihitung pada prioritas ketiga. Pesan tersebut menghilang dari antrian kedua. Dan konsumen ketiga "bangun", mengambil konteks ini dari layanan Yandex.Routing dan, atas dasarnya, menciptakan keadaan besok. Dia membuat pesanan untuk kurir, dia membuat pesanan, membuat shift. Ini juga banyak pekerjaan. Dia menghabiskan beberapa waktu untuk ini. Dan ketika semuanya dibuat, transaksi ini berakhir dan pekerjaan dihapus dari antrian.
Jika terjadi kesalahan di mana pun dalam proses ini, server akan dimulai ulang. Setelah pemulihan berikutnya, kita hanya akan melihat titik di mana kita berakhir. Misalkan fase pertama dan kedua telah berlalu. Dan mari kita lanjutkan ke yang ketiga.
Dengan arsitektur ini, dalam beberapa bulan terakhir, semuanya berjalan lancar, tidak ada masalah. Tapi sebelumnya ada uji coba yang solid. Tidak jelas di mana proses gagal, status apa yang diubah dalam database, dan seterusnya.
Ada hal-hal yang tidak boleh Anda hemat. Ada hal-hal yang dengannya Anda akan menyelamatkan diri dari sekelompok sel saraf jika Anda melakukan semuanya dengan baik segera.
Apa yang telah kami lakukan secara offline
Saya telah menjelaskan sebagian besar dari apa yang terjadi di platform kami. Tapi ada sesuatu yang tertinggal di belakang layar.
Kami belajar tentang perangkat lunak yang membantu kurir mengirimkan pesanan dalam satu hari. Tapi seseorang harus membuat tumpukan ini untuk kurir. Di pusat pemilahan, orang harus memilah mesin pesanan besar menjadi tumpukan kecil. Bagaimana itu dilakukan?
Ini adalah bagian kedua dari platform. Kami menulis semua perangkat lunak itu sendiri. Kami sekarang memiliki terminal di mana pemilik toko membaca kode dari kotak dan meletakkannya di sel yang sesuai. Ada logika yang agak rumit. Backend ini tidak jauh lebih sederhana dari yang sudah saya bicarakan.
Potongan teka-teki kedua ini diperlukan untuk memungkinkan, bersama dengan yang pertama, untuk memperluas proses ke kota-kota lain. Jika tidak, kami harus mencari kontraktor di setiap kota baru yang dapat mengatur pertukaran beberapa Excel melalui surat, atau berintegrasi dengan API kami. Dan itu akan menjadi waktu yang sangat lama.
Ketika kita memiliki potongan teka-teki pertama dan kedua, kita cukup menyewa gedung, menyewa mobil kurir. Beri tahu mereka cara mendorong, apa yang harus didorong, cara memilih, kotak mana yang harus diletakkan di mana, dan hanya itu. Berkat ini, kami telah meluncurkan di tujuh kota, kami memiliki lebih dari sepuluh pusat penyortiran.
Dan pembukaan platform kami di kota baru hanya membutuhkan sedikit waktu. Selain itu, kami telah belajar tidak hanya untuk mengirimkan pesanan kepada orang-orang tertentu. Kami tahu cara mengirimkan pesanan ke titik penjemputan dengan bantuan kurir. Kami juga menulis perangkat lunak untuk mereka. Dan pada titik ini kami juga mengeluarkan perintah kepada orang-orang.
Hasil
Pada awalnya, saya mengatakan mengapa kami mulai membuat platform kurir kami sendiri. Sekarang saya akan memberi tahu Anda apa yang telah kami capai. Ini luar biasa, tetapi dengan menggunakan platform kami, kami dapat mendekati hampir 100% mencapai interval. Misalnya, selama seminggu terakhir kualitas pengiriman di Moskow sekitar 95β98%. Ini berarti bahwa dalam 95β98% kasus kami tidak terlambat. Kami menyesuaikan dengan interval yang dipilih oleh klien. Dan kami bahkan tidak dapat memimpikan ketepatan seperti itu ketika kami hanya mengandalkan layanan pengiriman eksternal. Oleh karena itu, kami sekarang secara bertahap memperluas platform kami ke semua wilayah. Dan kami akan meningkatkan kemampuan pengiriman.
Kami mendapat transparansi yang tidak realistis. Kami juga membutuhkan transparansi ini. Semuanya dicatat dengan kami: semua tindakan, seluruh proses mengeluarkan pesanan. Kami memiliki kesempatan untuk kembali ke sejarah selama lima bulan dan membandingkan beberapa metrik dengan metrik saat ini.
Tapi kami juga memberikan transparansi ini kepada klien. Mereka melihat seorang kurir mendatangi mereka. Mereka bisa berinteraksi dengannya. Mereka tidak perlu menghubungi layanan dukungan, katakan: "Di mana kurir saya?"
Selain itu, ternyata untuk mengoptimalkan biaya, karena kami memiliki akses ke semua elemen rantai. Hasilnya, sekarang biayanya seperempat lebih murah untuk mengirimkan satu pesanan dibandingkan sebelumnya saat kami bekerja dengan layanan eksternal. Ya, biaya pengiriman pesanan turun 25%.
Dan jika Anda merangkum semua ide yang dibahas, berikut ini bisa dibedakan.
Anda harus memahami dengan jelas pada tahap pengembangan layanan Anda saat ini, proyek Anda saat ini. Dan jika ini adalah bisnis mapan, digunakan oleh jutaan orang, digunakan, mungkin di beberapa negara, Anda tidak dapat melakukan semuanya pada tingkat yang sama seperti dengan Rover.
Tetapi jika Anda memiliki eksperimen ... Eksperimen itu berbeda dalam setiap saat, jika kami tidak menunjukkan hasil yang dijanjikan, kami dapat ditutup. Itu tidak lepas landas. Dan tidak apa-apa.
Dan kami berada di rezim ini selama sekitar sepuluh bulan. Kami memiliki interval pelaporan, setiap dua bulan kami harus menunjukkan hasilnya. Dan kami berhasil.
Dalam mode ini, menurut saya Anda tidak berhak melakukan sesuatu dengan berinvestasi dalam jangka panjang dan tidak mendapatkan apa pun dalam jangka pendek. Tidak mungkin meletakkan dasar yang kuat untuk masa depan dalam format pekerjaan ini, karena masa depan mungkin tidak akan datang.
Dan setiap pengembang yang kompeten, pemimpin teknis harus selalu memilih antara mengerjakan kruk atau langsung membangun pesawat luar angkasa.
Singkatnya, cobalah membuatnya sesederhana mungkin, sambil menyisakan ruang untuk ekspansi.
Ada tingkat pertama ketika Anda perlu melakukannya dengan cukup sederhana. Dan ada tingkat pertama dengan tanda bintang, bila Anda membuatnya tetap sederhana, tetapi sisakan setidaknya sedikit ruang untuk bermanuver sehingga dapat diperluas. Dengan pola pikir ini, menurut saya hasilnya akan jauh lebih baik.
Dan hal terakhir. Saya berbicara tentang Rover bahwa sebaiknya melakukan proses seperti itu menggunakan tanda fitur. Saya menyarankan Anda untuk mendengarkan ceramah Maria Kuznetsova dari pertemuan Java. Dia memberi tahu bagaimana pengaturan flag fitur di sistem dan pemantauan kami.