Beberapa kata tentang R2DBC dan PostgreSQL

Baru-baru ini, saya kembali melihat bahwa sensasi telah meningkat di sekitar pemrograman reaktif secara umum, dan kerja reaktif dengan database pada khususnya. Saya punya beberapa ungkapan yang ingin saya katakan tentang ini.

gambar

Biarkan saya mengingatkan Anda apa yang terjadi di seri sebelumnya. Pada akhir 2017, Spring 5 keluar, di mana dukungan untuk pemrograman reaktif muncul. Secara khusus, kita berbicara tentang WebFlux . Semua orang mulai dengan tajam mencoba teknologi ini (kurva sensasi khas), dan kemudian industri menyadari bahwa tidak semua orang membutuhkan reaktivitas. Pelajaran utama yang dipelajari:

  • Pemrograman reaktif lebih sulit untuk di-debug
  • Mengembangkan sistem reaktif lebih sulit daripada yang klasik, menghalangi; jika Anda tidak sengaja memblokir utas, Anda selesai. Itu sebabnya proyek muncul (salah satu penulis -Bsideup )
  • Pemrograman reaktif, dan khususnya elastisitas, diperlukan terutama pada beban tinggi seperti Netflix. Jika Anda memiliki 100 RPS, Anda mungkin harus menulis kode dengan gaya pemblokiran - lebih murah dan lebih mudah

Selain itu, semua orang mengerti satu hal lagi. Agar pemrograman reaktif benar-benar terungkap, Anda perlu seluruh sistem menjadi reaktif, termasuk database Anda. Masalahnya adalah bahwa database bahkan mungkin tidak memiliki API reaktif, atau setidaknya asinkron. Ya, atau API semacam itu mungkin, tetapi mungkin tidak didukung di driver Anda.

Sebenarnya, hampir semua orang di sekitar saya sedang mengembangkan sistem PostgreSQL ketika saya membutuhkan database relasional klasik. Yang sedang berkata, pilihan default. Kami bekerja dengan PostgreSQL menggunakan driver JDBC lama (lebih dari 10 tahun) - pgjdbc . Pengemudi ini baik untuk semua orang. Praktis tidak ada bug. Driver ini sangat meningkat dalam kinerja (terima kasih untuk ini, termasukvladimirsitnikov) Tetapi pgjdbc memiliki satu kesalahan fatal - tidak ada dukungan untuk API asinkron .

Dalam beberapa tahun terakhir, perlombaan besar telah mulai mengembangkan driver alternatif untuk PostgreSQL, yang mencakup pengembangan API asinkron. Bahkan Oracle mencoba melakukan ini, tetapi sudah menutup pengembangan demi proyek Loom dan Seratnya . Tetapi kemudian Oracle berpikir lebih baik dan mulai melakukannya lagi .

Ada 3 solusi saat ini:

  1. https://github.com/jasync-sql/jasync-sql - driver asinkron untuk PostgreSQL, ditulis di Kotlin, di mana Netty adalah transpornya
  2. Solusi yang digunakan Vert.x adalah https://github.com/mauricio/postgresql-async . Perlu dicatat bahwa proyek ini diarsipkan, dan driver jasync-sql sebelumnya menulis ulang sama (meskipun, yang asli ditulis dalam Scala, dan solusi baru ditulis di Kotlin).
    Memperbarui Saya dikoreksi dalam komentar, klien dari Vert.x hidup dan merasa baik dalam benchmark .
  3. Pengemudi dari tim Spring adalah https://github.com/r2dbc/r2dbc-postgresql . Pengemudi ini segera menyediakan API reaktif (dan tidak asinkron), dan Netty digunakan untuk transportasi, seperti pada jasync-sql.

Secara konseptual, driver ini dibangun di atas prinsip yang sama. Semuanya menggunakan fitur PostgreSQL yang sudah ada secara eksklusif:


Sayangnya, driver tidak dapat mengubah protokol Kawat Postgres (seolah-olah Oleg Dokuk tidak mau - https://www.youtube.com/watch?v=n9tL2I_Big8 ). Yaitu, Postgres masih memerlukan Koneksi terpisah untuk permintaan SELECT. Selain itu, Postgres juga menciptakan proses baru untuk setiap Koneksi - https://www.postgresql.org/docs/current/tutorial-arch.html .

Namun, ada kabar baik. Memodifikasi permintaan dapat dikirim dalam batch tanpa menunggu hasilnya (menggunakan pipa). Untuk kasus ini, Koneksi tidak diperlukan untuk setiap permintaan.

Artinya, untuk meringkas. Driver PG reaktif (atau asinkron) meningkatkan situasi dalam aplikasi (kami sekarang menggunakan Non-blocking IO berbasis Netty, tidak menghabiskan utas pada permintaan), tetapi secara khusus pada sisi PostgreSQL - semuanya tidak begitu baik (mari berharap untuk peningkatan protokol jaringan dan arsitektur basis data) )

Pengemudi mana yang harus Anda perhatikan lebih dekat? Jika Anda, seperti saya, menggunakan Spring dalam pekerjaan Anda, maka r2dbc-postgresql mungkin merupakan pilihan yang baik. Penting bahwa dalam versi terbaru dari kerangka kerja mereka, orang-orang dari Pivotal mengintegrasikan driver dengan hal-hal yang biasa, misalnya, dengan Spring Data R2DBC(ini masih RC). Akibatnya, kita tidak harus bekerja dengan API driver tingkat rendah dan Connection Pool, yang mengurangi kemungkinan membuat kesalahan dalam proyek yang sedemikian kompleks.

Contoh minimum (yang berhasil saya intip dalam dokumentasi) menggunakan Spring Data R2DBC terlihat cukup akrab:

1. Konfigurasikan kredensial dan kumpulan koneksi:

spring.r2dbc.username=postgres
spring.r2dbc.password=P4$$W0RddD
spring.r2dbc.url=r2dbc:postgresql://localhost:5432/r2dbc
spring.r2dbc.pool.enabled=true
spring.r2dbc.pool.initial-size=10
spring.r2dbc.pool.max-idle-time=1m
spring.r2dbc.pool.max-size=30
spring.data.r2dbc.repositories.enabled=true

2. Buat entitas:

public class Customer {
    @Id
    private Long id;

    private String firstName;

    private String lastName;

    public Customer(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
}

3. Buat Repositori yang biasa:

public interface CustomerRepository extends ReactiveCrudRepository<Customer, Long> {
}

4. Gunakan repositori:

@RestController
@RequestMapping("/")
public class CustomerController {

    private CustomerRepository customerRepository;

    @PostMapping("/customer")
    Mono<Void> create(@RequestBody Publisher<Customer> customerFlux) {
        return customerRepository.saveAll(customerFlux).then();
    }

    @GetMapping("/customer")
    public Flux<Customer> list() {
        return customerRepository.findAll();
    }

    @GetMapping("/customer/{id}")
    public Mono<Customer> findById(@PathVariable Long id) {
        return customerRepository.findById(id);
    }
}

Contoh lengkap dapat ditemukan di repositori ini - https://github.com/Hixon10/spring-boot-r2dbc-postgresql-example .

Akhirnya, mari kita bicara tentang yang penting: apakah Anda perlu menggunakan r2dbc sekarang di aplikasi Anda? Menurut pendapat saya - ini terlalu dini. Saya akan menunggu satu set teknologi (driver, Spring DATA) untuk dirilis, dan untuk mengumpulkan shys pertama. Saya pikir pada tahun 2021 sudah dimungkinkan untuk melihat driver ini lebih dekat.

Keadaan saat ini - seluruh sistem reaktif (driver database Spring WebFlux + R2DBC) terlihat sangat keren. Secara harfiah hari iniolegchirmenerbitkan intisari di mana terdapat tautan ke artikel dengan tolok ukur - https://technology.amis.nl/2020/04/10/spring-blocking-vs-non-blocking-r2dbc-vs-jdbc-and-webflux-vs- web-mvc / . Singkatnya - reaktivitas menang.

All Articles