Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Menyelesaikan isu keselamatan serentak dalam aplikasi Websocket bahasa Go

Menyelesaikan isu keselamatan serentak dalam aplikasi Websocket bahasa Go

王林
王林asal
2023-12-14 13:47:39656semak imbas

Menyelesaikan isu keselamatan serentak dalam aplikasi Websocket bahasa Go

WebSocket ialah protokol komunikasi rangkaian moden yang boleh mencapai komunikasi dua hala masa nyata yang tinggi. Bahasa Go sememangnya menyokong konkurensi, jadi ia berfungsi dengan baik dalam aplikasi Websocket. Walau bagaimanapun, concurrency juga membawa beberapa masalah Dalam aplikasi Websocket, ini terutamanya ditunjukkan dalam keselamatan concurrency. Dalam artikel ini, kami akan menerangkan dan menunjukkan cara menyelesaikan isu keselamatan serentak dalam aplikasi Go Websocket.

  1. Latar Belakang Masalah

Dalam aplikasi Websocket, pelanggan boleh menghantar mesej kepada pelayan pada bila-bila masa, dan pelayan juga boleh menghantar mesej kepada klien pada bila-bila masa. Oleh itu, isu konkurensi mesti dipertimbangkan semasa memproses mesej Websocket. Dalam bahasa Go, kita boleh menggunakan goroutine untuk memproses mesej websocket secara serentak.

Walau bagaimanapun, concurrency akan menyebabkan beberapa isu keselamatan concurrency, seperti keadaan perlumbaan, kebuntuan, dsb. Keadaan perlumbaan boleh menyebabkan data tidak konsisten dan kebuntuan boleh menyebabkan program menjadi beku. Jadi, dalam aplikasi Websocket, kita mesti menyelesaikan isu keselamatan serentak ini.

  1. Penyelesaian

2.1 Mutex lock

Mutex lock ialah salah satu mekanisme kawalan serentak yang paling biasa dalam bahasa Go. Ia melindungi sumber yang dikongsi dan menghalang berbilang goroutine daripada mengakses sumber yang dikongsi pada masa yang sama, dengan itu memastikan ketepatan dan ketekalan data.

Dalam aplikasi Websocket, kami boleh memastikan keselamatan bersamaan sumber yang dikongsi melalui kunci mutex. Sebagai contoh, kod berikut menunjukkan cara menggunakan kunci mutex untuk memastikan keselamatan berbilang gorouti yang menulis pada peta kongsi pada masa yang sama:

type safeMap struct {
    m map[string]int
    sync.Mutex
}

func (sm *safeMap) Inc(key string) {
    sm.Lock()
    sm.m[key]++
    sm.Unlock()
}

Dalam contoh ini, kami membenamkan penyegerakan.Mutex jenis mutex dalam struktur safeMap Locks digunakan untuk melindungi sumber yang dikongsi. Dalam struktur ini, kami mentakrifkan pembolehubah jenis peta m, yang mewakili sumber untuk dikongsi oleh berbilang goroutine. Kemudian kami menentukan kaedah Inc untuk safeMap untuk melaksanakan operasi kenaikan automatik pada data dalam peta. Dalam kaedah Inc, kami mula-mula mengunci, kemudian melakukan operasi kenaikan, dan akhirnya membuka kunci.

2.2 Keselarasan tanpa kunci

Cara lain untuk menyelesaikan isu keselamatan serentak ialah melalui selaras tanpa kunci. Konkurensi tanpa kunci mengelakkan kehilangan prestasi yang disebabkan oleh kunci mutex dengan menggunakan algoritma bukan penyekat. Ia boleh meningkatkan keselarasan dan daya pemprosesan sistem, dan sering digunakan dalam sistem berprestasi tinggi, kependaman rendah dan tinggi.

Dalam bahasa Go, kita boleh menggunakan fungsi operasi atom bagi penyegerakan/pakej atom untuk mencapai keselarasan tanpa kunci. Sebagai contoh, kod berikut menunjukkan cara menggunakan operasi atom untuk melaksanakan operasi serentak pada pembolehubah dikongsi:

type Counter struct {
    count int32
}

func (c *Counter) Inc() {
    atomic.AddInt32(&c.count, 1)
}

func (c *Counter) Dec() {
    atomic.AddInt32(&c.count, -1)
}

func (c *Counter) Get() int32 {
    return atomic.LoadInt32(&c.count)
}

Dalam contoh ini, kami menggunakan fungsi AddInt32 dan LoadInt32 dalam pakej atom untuk melaksanakan pembilang. Kami mentakrifkan Kaunter struktur, yang mengandungi pembolehubah kiraan jenis int32. Kaunter struktur juga melaksanakan tiga kaedah, iaitu Inc, Dis dan Get. Dalam kaedah Inc dan Dis, kami menggunakan operasi atom AddInt32 untuk menambah dan mengurangkan kiraan pembolehubah yang dikongsi. Dalam kaedah Dapatkan, kami menggunakan operasi atom LoadInt32 untuk mendapatkan nilai kiraan pembolehubah yang dikongsi. . WriteLoop untuk menghantar mesej kepada pelanggan. Dalam aplikasi ini, kami merangkum setiap sambungan pelanggan dalam struktur Sambungan dan membenamkan penyegerakan. Mutex jenis mutex mu. Kami menggunakan mutex ini dalam WriteLoop untuk memastikan keselamatan bersamaan conn.ws sumber yang dikongsi. Dengan menggunakan kunci mutex, kita boleh mengelakkan masalah berbilang goroutine menulis data ke sambungan Websocket yang sama pada masa yang sama.

    Berikut ialah contoh kod untuk aplikasi Websocket yang menggunakan operasi atom untuk mencapai konkurensi tanpa kunci:
  1. package main
    
    import (
        "fmt"
        "net/http"
        "sync"
    
        "github.com/gorilla/websocket"
    )
    
    var upgrader = websocket.Upgrader{
        ReadBufferSize:  1024,
        WriteBufferSize: 1024,
    }
    
    type Connection struct {
        ws *websocket.Conn
        mu sync.Mutex
    }
    
    func main() {
        http.HandleFunc("/", handler)
        http.ListenAndServe(":8080", nil)
    }
    
    func handler(w http.ResponseWriter, r *http.Request) {
        c, err := upgrader.Upgrade(w, r, nil)
        if err != nil {
            fmt.Println(err)
            return
        }
    
        conn := &Connection{ws: c}
    
        go conn.WriteLoop()
        conn.ReadLoop()
    }
    
    func (conn *Connection) ReadLoop() {
        defer conn.ws.Close()
        for {
            _, message, err := conn.ws.ReadMessage()
            if err != nil {
                fmt.Println(err)
                break
            }
    
            fmt.Printf("Received message: %s
    ", message)
        }
    }
    
    func (conn *Connection) WriteLoop() {
        defer conn.ws.Close()
        for {
            conn.mu.Lock()
            err := conn.ws.WriteMessage(websocket.TextMessage, []byte("Hello, world!"))
            conn.mu.Unlock()
            if err != nil {
                fmt.Println(err)
                break
            }
        }
    }
  2. Dalam contoh ini, kami menggunakan fungsi AddInt32 dan LoadInt32 dalam pakej atom untuk melaksanakan pembilang. Kami mentakrifkan Sambungan struktur, yang mengandungi pembolehubah kiraan jenis int32. Sambungan struktur juga melaksanakan dua kaedah, ReadLoop dan WriteLoop. Dalam kaedah WriteLoop, kami menggunakan operasi atom AddInt32 untuk menambah kiraan pembolehubah yang dikongsi. Kemudian kami menentukan sama ada nilai pembilang melebihi 10 dan keluar dari gelung jika ia berlaku. Dalam contoh ini, daripada menggunakan mutex, kami menggunakan operasi atom untuk mencapai konkurensi tanpa kunci.

Kesimpulan

Artikel ini menerangkan cara menyelesaikan isu keselamatan serentak dalam aplikasi Websocket bahasa Go. Kami memberikan dua penyelesaian: kunci mutex dan konkurensi tanpa kunci. Sama ada ia adalah kunci mutex atau konkurensi bebas kunci, keselamatan concurrency boleh dijamin Kaedah yang mana untuk dipilih bergantung pada senario dan keperluan aplikasi tertentu. Kami menunjukkan cara menggunakan teknologi ini melalui kod sampel tertentu, dengan harapan dapat membantu pembaca memahami dan menggunakan teknologi ini dengan lebih baik.

Atas ialah kandungan terperinci Menyelesaikan isu keselamatan serentak dalam aplikasi Websocket bahasa Go. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn