Versi API di Monite
Kita semua suka mempunyai alatan baharu yang berkilat tetapi tidak suka tugas untuk sentiasa mengemas kininya. Ini terpakai kepada apa sahaja: sistem pengendalian, apl, API, pakej linux. Ia menyakitkan apabila kod kami berhenti berfungsi kerana kemas kini dan ia adalah dua kali ganda kesakitan apabila kemas kini itu tidak dimulakan oleh kami.
Dalam pembangunan API web, anda sentiasa berisiko untuk memecahkan kod pengguna anda dengan setiap kemas kini baharu. Jika produk anda ialah API, maka kemas kini ini akan menakutkan setiap masa. Produk utama Monite ialah API kami dan SDK label putih kami. Kami adalah syarikat yang mengutamakan API jadi kami mengambil berat untuk memastikan API kami stabil dan mudah digunakan. Oleh itu, masalah pecah perubahan berada di bahagian atas senarai keutamaan kami.
Penyelesaian biasa ialah mengeluarkan amaran penamatan kepada pelanggan anda dan jarang mengeluarkan perubahan yang melanggar. Tiba-tiba, keluaran anda kini boleh mengambil masa berbulan-bulan dan beberapa ciri perlu kekal tersembunyi atau tidak digabungkan sehingga setiap keluaran seterusnya. Ini memperlahankan pembangunan anda dan memaksa pengguna anda mengemas kini penyepaduan mereka setiap beberapa bulan.
Jika anda membuat keluaran lebih cepat, pengguna anda perlu mengemas kini penyepaduan mereka terlalu kerap. Jika anda memanjangkan masa antara keluaran, anda akan bergerak lebih perlahan sebagai sebuah syarikat. Lebih menyusahkan anda untuk pengguna -- lebih mudah untuk anda, dan begitu juga sebaliknya. Ini sememangnya bukan senario yang optimum. Kami mahu bergerak mengikut kadar kami sendiri tanpa melanggar apa-apa untuk pelanggan sedia ada yang mustahil dengan pendekatan penamatan biasa. Inilah sebabnya kami memilih penyelesaian alternatif: Versi API.
Idea yang agak mudah: lepaskan sebarang perubahan yang rosak pada bila-bila masa tetapi sembunyikannya di bawah versi API baharu. Ia memberikan anda yang terbaik dari kedua-dua dunia: Pengguna tidak akan mempunyai integrasi mereka secara rutin dipecahkan dan anda akan dapat bergerak pada sebarang kelajuan yang anda suka. Pengguna akan berhijrah pada bila-bila masa yang mereka mahu -- tanpa sebarang tekanan.
Memandangkan kesederhanaan idea itu, rasanya sesuai untuk mana-mana syarikat. Itulah yang anda harapkan untuk membaca dalam blog kejuruteraan biasa. Malangnya, ia tidak begitu mudah.
Berhati-hati dengan harga
Versi API adalah sukar, sangat sukar. Kesederhanaan ilusinya cepat pudar sebaik sahaja anda mula melaksanakannya. Malangnya, internet tidak pernah memberi amaran kepada anda kerana terdapat sedikit sumber mengenai topik itu. Majoriti mutlak daripada mereka berhujah tentang tempat untuk meletakkan versi API tetapi hanya beberapa artikel yang jarang cuba menjawab: "Bagaimana kita melaksanakannya?". Yang paling biasa ialah:
- meletakkan versi berbeza aplikasi web yang sama ke dalam penempatan berasingan
- menyalin laluan tunggal yang telah berubah antara versi
- menyalin keseluruhan aplikasi versi untuk setiap versi
Penyerahan yang berasingan boleh menjadi sangat mahal dan sukar untuk disokong, menyalin laluan tunggal tidak berskala sangat baik kepada perubahan besar, dan menyalin keseluruhan aplikasi menghasilkan begitu banyak kod tambahan yang anda akan mula tenggelam di dalamnya selepas hanya beberapa versi.
Walaupun anda cuba memilih yang paling murah, beban versi akan menyusul tidak lama lagi. Pada mulanya, ia akan berasa mudah: tambahkan skema lain di sini, cabang lain dalam logik perniagaan di sana, dan salin beberapa laluan pada penghujungnya. Tetapi memandangkan versi yang mencukupi, logik perniagaan anda akan menjadi tidak terurus dengan cepat, ramai pembangun anda akan tersalah anggap versi aplikasi dan versi API, dan akan mula membuat versi data dalam pangkalan data anda dan aplikasi anda akan menjadi mustahil untuk dikekalkan.
Anda mungkin berharap bahawa anda tidak akan mempunyai lebih daripada dua atau tiga versi API pada masa yang sama; bahawa anda akan dapat memadamkan versi lama setiap beberapa bulan. Memang benar jika anda hanya menyokong sebilangan kecil pengguna dalaman. Tetapi pelanggan di luar organisasi anda tidak akan menikmati pengalaman dipaksa untuk meningkatkan setiap beberapa bulan.
Versi API boleh menjadi salah satu bahagian infrastruktur anda yang paling mahal dengan cepat, jadi penting untuk melakukan penyelidikan yang gigih terlebih dahulu. Jika anda hanya menyokong pengguna dalaman, maka anda mungkin mempunyai masa yang lebih mudah dengan sesuatu seperti GraphQL tetapi ia boleh menjadi sama mahal dengan pembuatan versi.
Jika anda seorang pemula, adalah bijak untuk menangguhkan versi API sehingga peringkat akhir pembangunan anda apabila anda mempunyai sumber untuk melakukannya dengan betul. Sehingga itu, penamatan dan strategi perubahan aditif mungkin mencukupi. API anda tidak akan sentiasa kelihatan hebat tetapi sekurang-kurangnya anda akan menjimatkan banyak wang dengan mengelakkan versi eksplisit.
Bagaimanakah kami melaksanakan versi API?
Selepas beberapa percubaan dan banyak kesilapan, kami berada di persimpangan: pendekatan versi terdahulu kami yang kami nyatakan di atas terlalu mahal untuk diselenggara. Hasil daripada perjuangan kami, saya telah mencipta senarai keperluan berikut yang diperlukan untuk rangka kerja versi yang sempurna:
- "Mengekalkan sejumlah besar versi adalah mudah" untuk memastikan versi tidak melambatkan pembangunan ciri kami
- "Memadam versi lama adalah mudah" untuk memastikan kami boleh membersihkan pangkalan kod kami tanpa usaha
- "Mencipta versi baharu bukanlah terlalu mudah" untuk memastikan pembangun kami masih diberi insentif untuk cuba menyelesaikan masalah tanpa versi.
- "Mengekalkan log perubahan antara versi adalah mudah" untuk memastikan bahawa kami dan pelanggan kami sentiasa yakin tentang perbezaan sebenar antara versi
Malangnya, terdapat sedikit atau tiada alternatif kepada pendekatan sedia ada kami. Pada masa inilah idea gila muncul di fikiran saya: bagaimana jika kita mencuba dan membina sesuatu yang canggih, sesuatu yang sesuai untuk kerja itu -- sesuatu seperti versi API Stripe?
Hasil daripada banyak percubaan, kami kini mempunyai Cadwyn: rangka kerja versi API sumber terbuka yang bukan sahaja melaksanakan pendekatan Stripe tetapi membina dengan ketara di atasnya. Kami akan bercakap tentang pelaksanaan Fastapi dan Pydantic tetapi prinsip terasnya ialah bahasa dan rangka kerja agnostik.
Bagaimana Cadwyn berfungsi
Perubahan Versi
Masalah semua pendekatan versi lain ialah kami terlalu banyak menduplikasi. Mengapakah kami akan menduplikasi keseluruhan laluan, pengawal atau juga aplikasi apabila hanya sebahagian kecil kontrak kami dipecahkan?
Dengan Cadwyn, setiap kali penyelenggara API perlu membuat versi baharu, mereka menggunakan perubahan penting pada skema, model dan logik perniagaan mereka yang terkini. Kemudian mereka membuat perubahan versi -- kelas yang merangkumi semua perbezaan antara versi baharu dan versi terdahulu.
Sebagai contoh, katakan sebelum ini pelanggan kami boleh mencipta pengguna dengan alamat tetapi kini kami ingin membenarkan mereka menentukan berbilang alamat dan bukannya satu alamat. Perubahan versi akan kelihatan seperti ini:
class ChangeUserAddressToAList(VersionChange): description = ( "Renamed `User.address` to `User.addresses` and " "changed its type to an array of strings" ) instructions_to_migrate_to_previous_version = ( schema(User).field("addresses").didnt_exist, schema(User).field("address").existed_as(type=str), ) @convert_request_to_next_version_for(UserCreateRequest) def change_address_to_multiple_items(request): request.body["addresses"] = [request.body.pop("address")] @convert_response_to_previous_version_for(UserResource) def change_addresses_to_single_item(response): response.body["address"] = response.body.pop("addresses")[0]
instructions_to_migrate_to_previous_version digunakan oleh Cadwyn untuk menjana kod untuk versi API yang lebih lama bagi skema dan kedua-dua fungsi penukar ialah helah yang membolehkan kami mengekalkan seberapa banyak versi yang kami mahu. Prosesnya kelihatan seperti berikut:
- Cadwyn menukar semua permintaan pengguna daripada versi API lama kepada versi API terkini dengan menggunakan change_address_to_multiple_items converter dan menyalurkannya ke logik perniagaan kami
- Logik perniagaan, respons APInya dan model pangkalan data sentiasa disesuaikan dengan versi API terkini (sudah tentu, ia mesti masih menyokong ciri lama walaupun ia dikeluarkan dalam versi baharu)
- Selepas logik perniagaan menghasilkan respons, Cadwyn menukarnya kepada versi API yang lebih lama yang sedang dihidupkan oleh peminta pelanggan dengan menggunakan penukar_tukar_alamat_kepada_item_tunggal.
Selepas penyelenggara API kami membuat perubahan versi, mereka perlu menambahkannya pada VersionBundle kami untuk memberitahu Cadwyn bahawa VersionChange ini akan disertakan dalam beberapa versi:
VersionBundle( Version( date(2023, 4, 27), ChangeUserAddressToAList ), Version( date(2023, 4, 12), CollapseUserAvatarInfoIntoAnID, MakeUserSurnameRequired, ), Version(date(2023, 3, 15)), )
Itu sahaja: kami telah menambah perubahan besar tetapi logik perniagaan kami hanya mengendalikan satu versi -- terkini. Walaupun selepas kami menambah berdozen versi API, logik perniagaan kami masih bebas daripada logik versi, penamaan semula berterusan, if's dan penukar data.
Rantaian Versi
Perubahan versi bergantung pada antara muka awam API dan kami hampir tidak pernah menambah perubahan pecah ke dalam versi API sedia ada. Ini bermakna sebaik sahaja kami mengeluarkan versi – ia tidak akan rosak.
Oleh kerana perubahan versi menerangkan perubahan pecah dalam versi dan tiada perubahan pecah dalam versi lama, kami boleh yakin bahawa perubahan versi kami tidak berubah sepenuhnya – perubahan itu tidak akan mempunyai sebab untuk berubah. Entiti tidak berubah adalah lebih mudah untuk dikekalkan berbanding jika mereka adalah sebahagian daripada logik perniagaan kerana ia sentiasa berkembang. Perubahan versi juga digunakan satu demi satu -- membentuk rantaian transformer antara versi yang boleh memindahkan sebarang permintaan kepada mana-mana versi yang lebih baharu dan sebarang respons kepada mana-mana versi yang lebih lama.
Kesan sampingan
Kontrak API jauh lebih kompleks daripada sekadar skema dan medan. Ia terdiri daripada semua titik akhir, kod status, ralat, ralat mesej dan juga gelagat logik perniagaan. Cadwyn menggunakan DSL yang sama yang kami nyatakan di atas untuk mengendalikan titik akhir dan kod status tetapi ralat dan gelagat logik perniagaan adalah cerita yang berbeza: ia adalah mustahil untuk diterangkan menggunakan DSL, ia perlu dibenamkan ke dalam logik perniagaan.
This makes such version changes much more expensive to maintain than all others because they affect business logic. We call this property a "side effect" and we try to avoid them at all costs because of their maintenance burden. All version changes that want to modify business logic will need to be marked as having side effects. It will serve as a way to know which version changes are "dangerous":
class RequireCompanyAttachedForPayment(VersionChangeWithSideEffects): description = ( "User must now have a company_id in their account " "if they want to make new payments" )
It will also allow API maintainers to check that the client request uses an API version that includes this side effect:
if RequireCompanyToBeAttachedForPayment.is_applied: validate_company_id_is_attached(user)
No silver bullets
Cadwyn has many benefits: It greatly reduces the burden on our developers and can be integrated into our infrastructure to automatically generate the changelog and improve our API docs.
However, the burden of versioning still exists and even a sophisticated framework is not a silver bullet. We do our best to only use API versioning when absolutely necessary. We also try to make our API correct on the first try by having a special "API Council". All significant API changes are reviewed there by our best developers, testers, and tech writers before any implementation gets moving.
Special thanks to Brandur Leach for his API versioning article at Stripe and for the help he extended to me when I implemented Cadwyn: it would not be possible without his help.
Atas ialah kandungan terperinci Versi API di Monite. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undress AI Tool
Gambar buka pakaian secara percuma

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Stock Market GPT
Penyelidikan pelaburan dikuasakan AI untuk keputusan yang lebih bijak

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Tutorial ini memperincikan bagaimana untuk menggabungkan penyesuai LORA PEFT dengan model asas untuk menghasilkan model yang sepenuhnya bebas. Artikel ini menunjukkan bahawa adalah salah untuk menggunakan transformer.automodel secara langsung untuk memuatkan penyesuai dan menggabungkan berat secara manual, dan menyediakan proses yang betul untuk menggunakan kaedah Merge_and_unload di perpustakaan PEFT. Di samping itu, tutorial juga menekankan pentingnya menangani segmen perkataan dan membincangkan isu dan penyelesaian keserasian versi PEFT.

Jalankan pipinstall-rrequirements.txt untuk memasang pakej ketergantungan. Adalah disyorkan untuk mencipta dan mengaktifkan persekitaran maya terlebih dahulu untuk mengelakkan konflik, memastikan bahawa laluan fail adalah betul dan PIP telah dikemas kini, dan menggunakan pilihan seperti-tidak-deps atau-pengguna untuk menyesuaikan tingkah laku pemasangan jika perlu.

Python adalah alat ujian yang mudah dan berkuasa di Python. Selepas pemasangan, fail ujian ditemui secara automatik mengikut peraturan penamaan. Tulis fungsi bermula dengan ujian untuk ujian pernyataan, gunakan @pytest.fixture untuk membuat data ujian yang boleh diguna semula, mengesahkan pengecualian melalui pytest.raises, menyokong menjalankan ujian tertentu dan pelbagai pilihan baris arahan, dan meningkatkan kecekapan ujian.

TheargParsemoduleisThereMendingWayOhandLecommand-lineargumentsinpython, menyediakan robrobustparsing, typevalidation, helpmessages, anderrorhandling; usesy.argvforsimplecasesrequiringminiminalsetup.

Artikel ini bertujuan untuk meneroka masalah biasa ketepatan pengiraan yang tidak mencukupi bagi nombor titik terapung di Python dan Numpy, dan menjelaskan bahawa punca akarnya terletak pada batasan perwakilan nombor terapung 64-bit standard. Untuk senario pengkomputeran yang memerlukan ketepatan yang lebih tinggi, artikel itu akan memperkenalkan dan membandingkan kaedah penggunaan, ciri-ciri dan senario yang berkenaan dengan perpustakaan matematik ketepatan tinggi seperti MPMATH, SYMPY dan GMPY untuk membantu pembaca memilih alat yang tepat untuk menyelesaikan keperluan ketepatan yang rumit.

PYPDF2, PDFPlumber dan FPDF adalah perpustakaan teras untuk Python untuk memproses PDF. Gunakan pypdf2 untuk melakukan pengekstrakan teks, penggabungan, pemisahan dan penyulitan, seperti membaca halaman melalui pdfreader dan memanggil extract_text () untuk mendapatkan kandungan; PDFplumber lebih sesuai untuk mengekalkan pengekstrakan teks susun atur dan pengiktirafan jadual, dan menyokong extract_tables () untuk menangkap data jadual dengan tepat; FPDF (disyorkan FPDF2) digunakan untuk menjana PDF, dan dokumen dibina dan dikeluarkan melalui add_page (), set_font () dan sel (). Apabila menggabungkan PDF, kaedah tambahan PDFWriter () dapat mengintegrasikan pelbagai fail

Mendapatkan masa semasa boleh dilaksanakan di Python melalui modul DateTime. 1. Gunakan datetime.now () untuk mendapatkan masa semasa tempatan, 2. Gunakan strftime ("%y-%m-%d%h:%m:%s") untuk memformat tahun, bulan, hari, jam, minit dan kedua, 3 menggunakan datetime.d. UTCNOW (), dan operasi harian dapat memenuhi keperluan dengan menggabungkan datetime.now () dengan rentetan yang diformat.

Import@contextManagerFromContextLibandDefineageneratorfunctionThatTyieldSexactlyonce, whereCodeBeforeyieldActSasenterandCodeAfteryield (PreferitlySinfinal) actsas __
