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.
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.
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.
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 } } }
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!