Spiral: kerangka kerja PHP / Go berkinerja tinggi



Halo Habr. Nama saya Anton Titov, CTO dari Spiral Scout. Hari ini saya ingin memberi tahu Anda tentang gajah PHP kami. Atau lebih tepatnya, tentang versi kedua kerangka PHP / Go full-stack open-source - Spiral .

Spiral adalah kerangka kerja komponen tumpukan penuh yang dikembangkan oleh perusahaan kami selama lebih dari sebelas tahun dan melayani ratusan proyek nyata. Paket perangkat lunak didasarkan pada banyak perpustakaan terbuka dan eksklusif, termasuk RoadRunner dan Cycle ORM .

Kerangka kerja ini kompatibel dengan sebagian besar rekomendasi PSR, mendukung MVC dan berjalan 5-10 kali lebih cepat daripada Laravel / Symfony.

Jika Anda belum pernah mendengar tentang Spiral dan bertanya-tanya apa kerangka PHP / Go dan ke mana versi pertama pergi, selamat datang di cat.

Tentang kerangka kerja


Pengembangan Spiral dimulai pada 2008/09 sebagai kernel portabel untuk aplikasi freelance. Pada 2010, kami akhirnya membentuk perusahaan outsourcing dan sejak itu terlibat dalam meningkatkan tumpukan kami.

Akibatnya, kerangka kerja diubah menjadi seperangkat komponen independen, disatukan oleh lapisan integrasi umum.

Satu-satunya pengumuman publik tentang versi pertama terjadi pada Reddit pada tahun 2017 dan menjelaskan kepada kami bahwa, secara teknis, Spiral tidak benar-benar mengalahkan pesaing pada waktu itu. Kami memperhitungkan umpan balik yang kami terima, pengalaman proyek yang lebih kompleks dan menyelesaikan versi kedua pada Mei 2019.

Setelah satu tahun mendokumentasikan dan menjalankan proyek nyata, kami siap untuk menyerahkan pengembangan ini kepada publik.

Perbedaan utama antara Spiral 2.0 dari generasi kerangka sebelumnya dan, mungkin, dari semua kerangka kerja PHP lainnya yang ada adalah server aplikasi terintegrasi RoadRunner, serta adaptasi arsitektur untuk model eksekusi berumur panjang (mode daemon).

Hibrida Rantheim


Konsep utama dari kerangka kerja adalah simbiosis antara server aplikasi yang ditulis dalam Golang dan inti PHP. Kode aplikasi PHP hanya dimuat sekali ke dalam memori - dengan cara ini Anda mendapatkan penghematan sumber daya yang signifikan, tetapi kehilangan kemampuan untuk menjalankan WordPress.



Anda dapat membaca lebih lanjut tentang model hybrid di sini dan di sini .

Server bertanggung jawab untuk seluruh bagian infrastruktur: HTTP / FastCGI, komunikasi dengan broker antrian, GRPC, WebSockets, Pub / Sub, cache, metrik, dll.

Menulis kode untuk Spiral praktis tidak berbeda dengan kode untuk kerangka kerja lainnya. Namun, prinsip-prinsip SOLID harus lebih bertanggung jawab. Jika sebelumnya caching data pengguna di singleton hanya menyebabkan rasa sakit parah untuk tinjauan kode, sekarang kode seperti itu tidak akan berfungsi dengan benar.

Pengetahuan Golang tidak diperlukan untuk bekerja dengan platform. Namun, setelah mempelajari bahasa kedua, Anda dapat membuat integrasi yang hampir mulus dengan perpustakaan Golang. Misalnya, sematkan mesin pencari teks lengkap atau tulis driver Kafka Anda sendiri.

Untuk menembak di kaki sedikit lebih sulit, diputuskan untuk meninggalkan sistem acara dan kait dan memprioritaskan pekerjaan dengan tumpukan panggilan dalam bentuk eksplisit.

Kerangka kerja ini menyediakan seperangkat alat, seperti penutupan IoC, middleware, spoiler lapisan domain dan layanan yang tidak dapat diubah.

$container->runScope(
    [UserContext::class => $user],
    function () use ($container) {
        dump($container->get(UserContext::class);
    }
);

Meskipun pendekatan semacam itu membebankan overhead tambahan, kemampuan untuk tidak membongkar inti program, koneksi ke basis data dan soket dari memori lebih dari mencakup keterbatasan ini.

Performa


Di kelas penuh-tumpukan kerangka kerja PHP, Spiral terutama bersaing dengan majelis berbasis Swoole dan beberapa kerangka kerja mikro.



Benchmark lengkap tersedia di sini dan di sini .

Bagi kami, kinerja adalah efek samping dari arsitektur yang dipilih. Kami yakin bahwa dengan konfigurasi yang tepat dan mengganti PSR-7 dengan abstraksi yang lebih ringan, produktivitas dapat ditingkatkan sebesar 50-80% (ini dibuktikan dengan contoh ubiquity-roadrunner ).

Swoole. Swoole RoadRunner, PHP ++. , Go. , .

RoadRunner ( ), , Windows.

Spiral Swoole, !

PSR-*


Sebagian besar komponen Spiral adalah opsional untuk bangunan Anda, perbedaan antara bangunan mikro dan penuh hanya ada di konten composer.json. Jika perlu, Anda bisa menggunakan antarmuka untuk mengganti pustaka standar dengan implementasi alternatif.

Lapisan HTTP kerangka ditulis dengan mempertimbangkan standar PSR-7/15/17, Anda dapat dengan aman mengubah router , implementasi pesan, dll.

Sebagian besar framework framework dapat digunakan di luar framework. Misalnya, RoadRunner bekerja sangat baik dengan Symfony dan Laravel , dan Cycle ORM akan tersedia di Yii3.

Komponen server


Selain komponen PHP, rakitan RoadRunner mencakup beberapa perpustakaan yang ditulis dalam Golang. Sebagian besar layanan server dapat dikelola dari dalam PHP.

Secara khusus, ada komponen antrian yang mendukung pekerjaan dengan broker AMQP, Amazon SQS dan Beanstalk. Perpustakaan dapat dengan benar berhenti, menyambung kembali dan mendistribusikan sejumlah antrian yang masuk ke beberapa pekerja.

Di luar kotak ada pemantauan pada Prometheus dan titik pemeriksaan kesehatan, reboot panas dan batas memori. Untuk proyek terdistribusi, ada server dan klien GRPC. Ada soket web, mereka dapat diotorisasi dari aplikasi PHP dan terhubung ke bus-sub-bus (dalam memori atau pada Redis). Driver Key-Value saat ini sedang diuji.

INFO[0154] 10.42.5.55:51990 Ok {2.28ms} /images.Service/GetFiles
INFO[0155] 10.42.3.95:50926 Ok {11.3ms} /images.Service/GetFiles
INFO[0156] 10.42.5.55:52068 Ok {3.60ms} /images.Service/GetFiles
INFO[0158] 10.42.5.55:52612 Ok {2.30ms} /images.Service/GetFiles
INFO[0166] 10.42.5.55:52892 Ok {2.23ms} /images.Service/GetFiles
INFO[0167] 10.42.3.95:49938 Ok {2.37ms} /images.Service/GetFiles
INFO[0169] 10.42.5.55:52988 Ok {2.22ms} /images.Service/GetFiles




Portabilitas


Kerangka kerja ini tidak memerlukan PHP-FPM dan NGINX. Dan semua komponen Golang memiliki driver untuk bekerja tanpa ketergantungan eksternal. Dengan demikian, Anda dapat menggunakan antrian, soket web, metrik tanpa menginstal pialang atau program eksternal.

./spiral serve -v -d

Spiral tidak masalah jika Anda menulis aplikasi terdistribusi besar atau situs kecil mengirim "menulis kepada kami" di latar belakang. Bagaimanapun, Anda dapat menggunakan alat yang sama, menyatukan perilaku lingkungan lokal dan produksi.

Karena lapisan HTTP bersifat opsional, Anda dapat menulis aplikasi konsol yang memproses data di latar belakang menggunakan paket antrian. Kami menggunakan program tersebut untuk migrasi data.

Siklus ORM


Sebagai ORM di luar kotak, datang Siklus ORM . Mesin Data Mapper ini sangat mirip fungsinya dengan Doktrin, tetapi sangat berbeda secara arsitektur.

Seperti Doctrine, Cycle dapat bekerja dengan model domain murni, menghasilkan migrasi secara mandiri dan mengatur kunci asing. Skema pemetaan dapat dijelaskan dengan kode atau dikumpulkan dari anotasi. Tetapi alih-alih DQL, Query Builders klasik digunakan.

//    
//        
$users = $orm->getRepository(User::class)
    ->select()
    ->where('active', true)
    ->load('orders', [
        'method' => Select::SINGLE_QUERY, // force LEFT JOIN
        'load'   => function($query) {
            $query->where('paid', true)->orderBy('timeCreated', 'DESC');
        }
    ])
    ->fetchAll();

$transaction = new Transaction($orm);

foreach($users as $user) {
    $transaction->persist($user);
}

$transaction->run();

Siklus berjalan lebih cepat daripada Ajaran pada pilihan, tetapi lebih lambat bertahan. Engine mendukung kueri kompleks dengan beberapa strategi pemuatan, kelas proksi, embedding dan menyediakan transaksi portabel alih-alih EntityManager global.

Rincian lebih lanjut dapat didengar di PHP Russia 2020 .

"Fitur" utama ORM adalah kemampuan untuk mengubah pemetaan data dan tautan dalam runtime. Dengan kata-kata sederhana, Anda dapat memungkinkan pengguna untuk secara independen menentukan skema data (DBAL mendukung introspeksi dan deklarasi skema database).

Anda dapat membaca lebih lanjut tentang membandingkan Cycle, Eloquent, dan Doctrine 2 di sini .

Prototyping cepat


Spiral mencakup beberapa alat untuk mempercepat dan menyederhanakan pengembangan. Yang utama adalah injeksi dependensi otomatis, konfigurasi otomatis, dan pencarian model otomatis menggunakan analisis statis. Perintah konsol memungkinkan Anda menghasilkan sebagian besar kelas yang diperlukan dan mudah disesuaikan.

Untuk integrasi ke dalam IDE ada sistem prototyping cepat. Menggunakan magic PrototypeTrait, Anda bisa mendapatkan akses cepat ke tips di IDE.



Ciri tersebut secara otomatis menemukan repositori ORM, komponen standar dan dapat mengindeks layanan Anda dengan anotasi. Di bawah tenda, metode sulap __get digunakan , yang menjamin Anda tinjauan kode cepat.

Cukup jalankan perintah `php app.php prototype: inject -r`, dan sistem prototyping akan secara otomatis menghapus semua keajaiban:

namespace App\Controller;

use App\Database\Repository\UserRepository;
use Spiral\Views\ViewsInterface;

class HomeController
{
    /** @var ViewsInterface */
    private $views;

    /** @var UserRepository */
    private $users;

    /**
     * @param ViewsInterface $views
     * @param UserRepository $users
     */
    public function __construct(ViewsInterface $views, UserRepository $users)
    {
        $this->users = $users;
        $this->views = $views;
    }

    public function index()
    {
        return $this->views->render('profile', [
            'user' => $this->users->findByName('Antony')
        ]);
    }
}

Di bawah tenda, PHP-Parser digunakan .

Keamanan


Karena sebagian besar aplikasi kami dikembangkan untuk segmen B2B, masalah keamanan harus ditanggapi dengan serius.

Komponen untuk memvalidasi permintaan kompleks (Permintaan Filter), CSRF dan enkripsi (berdasarkan defuse / php-enkripsi ) akan tersedia untuk Anda . Bekerja dengan cookie dan sesi mendukung anti-perusakan dan penandatanganan data di sisi server.

Kerangka kerja ini menyediakan komponen otentikasi berbasis token yang kedaluwarsa. Sebagai pengemudi, Anda dapat menggunakan sesi, database, atau bahkan JWT murni.

Atau semua jenis token pada saat yang sama, jika persyaratan β€œsegera sambungkan SAML / SSO / 2FA!” Tiba-tiba terbang ke Anda :(

Otorisasi akses dilakukan melalui komponen RBAC dengan beberapa peningkatan yang memungkinkan pengoperasian dalam mode DAC dan ABAC. Ada dukungan untuk banyak peran, anotasi untuk melindungi metode pengontrol, dan sistem aturan.

Bekerja dengan lapisan domain terjadi melalui lapisan pencegat menengah . Jadi, Anda dapat membuat batasan khusus pada sekelompok pengontrol, melakukan pra-validasi data, dan membungkus kesalahan.

Mesin Templat


Jika Anda hanya menyukai Twig - Anda dapat menggulir bagian ini, cukup instal ekstensi dan gunakan alat yang sudah dikenal. :)

Keluar dari kotak datang mesin template Stemper, atau lebih tepatnya, perpustakaan untuk membuat markup DSL Anda sendiri. Secara khusus, ada lexer lengkap, beberapa tata bahasa, parser dan akses ke AST (mirip dengan PHP-Parser Nikita).

Dimungkinkan untuk menguraikan beberapa tata bahasa bersarang. Jadi, misalnya, Anda dapat menggunakan arahan Laravel Blade dan markup DSL Anda sendiri (dalam bentuk tag HTML) dalam template yang sama. Ternyata sesuatu seperti komponen web di sisi server.

Kami menggunakan komponen ini untuk menggambarkan antarmuka yang kompleks menggunakan primitif dan aturan sederhana.

<extends:admin.layout.tabs title="User Information"/>
<use:bundle path="admin/bundle"/>

<ui:tab id="info" title="Information">
  User, {{ $user->name }}
</ui:tab>

<ui:tab id="data" title="User Settings">
  <grid:table for={{ $user->settings }}>
    <grid:cell title="Key">{{ $key }}</grid:cell>
    <grid:cell title="Value">{{ $value }}</grid:cell>
  </grid:table>
</ui:tab>

Ini mendukung pelolosan otomatis dengan dukungan konteks (misalnya, output dari PHP di dalam blok JS secara otomatis mengkonversi data ke JSON), sumber-peta untuk bekerja dengan kesalahan. Template dikompilasi ke dalam kode PHP yang dioptimalkan dan kemudian diberikan langsung dari memori aplikasi.
Stemper dapat sepenuhnya bekerja dengan DOM dokumen (walaupun lebih lambat jika Anda menggunakan alat khusus).

Pengembangan Kerangka


Tentu saja, dalam lebih dari satu dekade mengembangkan alat ini, kami telah melakukan banyak kesalahan. Beberapa dari mereka dikoreksi untuk rilis versi kedua, sementara bagian lainnya memerlukan revisi konsep beberapa komponen.

Kami juga tidak akan menyangkal bahwa beberapa hal memerlukan file. Dan beberapa pertanyaan mungkin terdengar bagi kami untuk pertama kalinya. Meskipun dokumentasi mencoba untuk menutupi maksimum komponen, masih dapat melorot di beberapa tempat.

Kami terbuka untuk kritik dan saran, karena kami sendiri aktif menggunakan alat ini. Tumpukan besar peningkatan perlahan-lahan disortir oleh tim kami dan komunitas.

Banyak pekerjaan akan diperlukan untuk meningkatkan dan mempercepat Siklus, serta menulis ulang Filter Permintaan sesuai dengan RFC terbaru. Dalam pengembangan adalah komponen untuk bekerja dan meniru basis data Nilai-Kunci.

Kami sama sekali tidak berhasil menerjemahkan banyak hal dari versi pertama. Rencananya adalah mengembalikan paket ODM, panel admin, menulis profiler yang baik, dll.

Komunitas dan Tautan


Anda dapat masuk ke komunitas Perselisihan kecil kami . Saluran telegram .


Semua kode didistribusikan di bawah lisensi MIT dan tidak memiliki batasan untuk penggunaan komersial.

Terimakasih atas perhatiannya. Saya harap alat kami berguna dalam proyek Anda!

All Articles