iT邦幫忙

2025 iThome 鐵人賽

DAY 13
0

講完了 Ktor 程式的撰寫、套件的使用、也講過了部署。

今天來講講為什麼我會選擇使用 Ktor,以及我主觀比較 Ktor 和其他後端開發框架的優缺點。

Laravel

我第一個做網頁後端開發的語言是 PHP,目前 PHP 最知名且使用者最多的框架,非 Laravel 莫屬了。

即便是現在,我也依舊認為要快速的進入網頁開發的領域,使用 Laravel 是個很正確的選擇。

不管是撰寫之後立刻就能看結果,不需要再做編輯的流程

或者是非常易於使用的 ORM,舉個例子,這是 Laravel 宣告多對多關係時的程式寫法

// Product

public function tags()
{
    return $this->belongsToMany(Tag::class);
}

// Tag
public function products()
{
    return $this->belongsToMany(Product::class);
}

中介表可以不定義,預設是使用兩個類別的名稱相連接,也就是 product_tag 資料表

使用時的寫法大致是

foreach ($product->tags as $tag) {
    // 針對商品標籤想做的事情
}

這麼簡單的用法,可以說在網頁開發裡面都很少見。

不過,這麼方便的框架,在處理併發事件時,由於 PHP 語言天生的限制,所以會使用進程(Process)進行處理

$pool = Process::pool(function (Pool $pool) {
    $pool->path(__DIR__)->command('bash import-1.sh');
    $pool->path(__DIR__)->command('bash import-2.sh');
    $pool->path(__DIR__)->command('bash import-3.sh');
})->start(function (string $type, string $output, int $key) {
    // ...
});

這在有些任務需要進行併發處理時,會消耗比較多的效能。

雖然有許多後端任務由於實際用量不大,不用太過在意效能,但是遇到狀況時就比較難以處理

這時候由於 Kotlin 搭配語言原生的 coroutine,就可以使用較少的效能,且寫法依舊不失簡潔的處理這種狀況

coroutineScope {
    // Parallel requests
    val firstRequest: Deferred<String> = async { client.get("http://localhost:8080/path1").bodyAsText() }
    val secondRequest: Deferred<String> = async { client.get("http://localhost:8080/path2").bodyAsText() }
    val firstRequestContent = firstRequest.await()
    val secondRequestContent = secondRequest.await()
}

Ktor 開發和 Laravel 比較

除去效能不提,作為一個需要編譯的語言與框架,加上 Ktor 的設計上是將自己定義為一個輕量化的框架,

使用 Ktor 開發一定會比使用 Laravel 多一些步驟

但是由於 Ktor 開發工程師的努力,以及其他套件的加入,所以開發上提升的難度,我認為是在可接受範圍內的

比方說前面所說的資料庫 ORM

Ktor 搭配 Exposed 框架的寫法如下,表會有對應的 object,物件則有對應的 class

object ProductsTable : IntIdTable() {
    val name = varchar("name", MAX_NAME_LENGTH)
}

class ProductEntity(id: EntityID<Int>) : IntEntity(id) {
    companion object : IntEntityClass<ProductEntity>(ProductsTable)

    var name by ProductsTable.name
}

object TagsTable : IntIdTable() {
    val name = varchar("name", MAX_NAME_LENGTH)
}

class TagEntity(id: EntityID<Int>) : IntEntity(id) {
    companion object : IntEntityClass<TagEntity>(TagsTable)

    var name by TagsTable.name
}

多對多資料關係則使用 via 定義,並且要宣告中介表

object ProductsTagsTable : Table() {
    val product = reference("product", ProductsTable)
    val tag = reference("tag", TagsTable)
}

class ProductEntity(id: EntityID<Int>) : IntEntity(id) {
    companion object : IntEntityClass<ProductEntity>(ProductsTable)

    var name by ProductsTable.name
    var tags by TagEntity via ProductsTagsTable
}

class TagEntity(id: EntityID<Int>) : IntEntity(id) {
    companion object : IntEntityClass<TagEntity>(TagsTable)

    var name by TagsTable.name
    var products by ProductEntity via ProductsTagsTable
}

可以看到確實是比較麻煩,但是我認為還在能接受的範圍裡面。

所以,如果今天有個需求是嘗試階段,或者已知流量不會很高,我會非常推薦使用 Laravel 進行開發。

如果今天需求流量已經開始逼近 5k QPS 甚至 10K QPS 了,那我就會推薦嘗試看看 Ktor。

今天的比較就到這邊,我們明天見!


上一篇
Day 12:如何將 Ktor 部署到 GCP 平台上
下一篇
Day 14:Ktor 和 Golang 進行後端開發的比較
系列文
每天一點 Ktor 3.0:一個月學會 Kotlin 後端開發14
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言