иногда все же вылетает баг, когда при получении клиента по id выдает nil. Из-за чего такое может быть?
type checkQueue struct {
mu sync.Mutex
queue map[int]*Client
}
// Inc increments the counter for the given key.
func (c *checkQueue) Add(value *Client) int {
c.mu.Lock()
idx := len(c.queue) + 1
c.queue[idx] = value
c.mu.Unlock()
return idx
}
func (c *checkQueue) Get(key int) *Client {
return c.queue[key]
}
func (c *checkQueue) Remove(key int) {
c.mu.Lock()
delete(c.queue, key)
c.mu.Unlock()
}
Такого айди не было в мапе или вы в этот ключ сами положили Нил?
А что произойдет, если добавить 2 клиента, потом 1 удалить и добавить ещё Ключи будут такие 1,2 2 2 То есть 3ий юзер перетрет второго.
На Get нет лока
офигеть, и правда надо переписывать логику. Спасибо
а он точно нужен?
И тут лучше rwmutex
А почему мапа для очереди?
первое, что в голову пришло. Есть вариант получше(кроме специализированных баз данных)?
Очередь на map - это как то странно. Обычно связанный список используют. Я делал на container/list.
это не совсем очередь, сделал так, чтобы при последующих запросах на сервер не создавать нового клиента
Ну тогда это кэш.
видимо да, его тоже лучше мапой не реализовывать?
Map для кэша подходит. Есть правда проблема с утечкой памяти.
Только вот с вашим кодом будет гонка. То есть когда в кэше не записи - вполне возможно что несколько потоков захотят добавить одного и того же клиента в кэш.
почему? я ведь использую мютекс при изменении данных
"одного и того же" на сервер приходят запросы, на каждый запрос один клиент
Я не про изменение, а про добавление. Тут только нужно понять, что id у вас представляет.
func randHexID() string { bytes := make([]byte, 4) rand.Read(bytes) return hex.EncodeToString(bytes) } решил вместо числовых айди использовать такой
Ок. Забыли мой наброс. У вас id создаётся внутри Add с локом. Тут все ок.
А почему бы не использовать uuid? Рандому я бы тут не доверял.
Если использовать uuid как ключ, при добавлении/удалении нужно делать блокировку?
Или в каких случаях её не стоит делать?
Тип ключа не влияет на необходимость использовать mutex. Влияет именно то, какие действия совершаются с ресурсом.
Честно говоря не совсем понятно что у вас такое Client. От этого зависят дальнейшие советы.
Он делает запросы на сторонний сервер
Тогда вам нужен не кэш, а пул соединений (клиентов)...
Не ок, т.к. ключ формируется как len + 1, а гарантий что ключ 4 будет удален после ключа 5 нет
Программа, которая делает запросы на мой сервер многопоточна(300 одновременных соединений), в границах одного потока должен быть один и тот же клиент Структура клиента такая type Client struct { Proxy string client *fasthttp.Client User *User }
То есть лучше сделать список и добавлять/удалять оттуда клиентов?
Почитайте про connection pool. Может вам подойдёт. Основная идея - возможность ограничить кол-во одновременно открытых соединений.
Используй для key 4-tuple соединения с клиентом(dst addr:port + src addr:port)
А как ты клиентов между собой различаешь, кстати?
Ну мапу ведь создал, по uuid
Получение, добавление, удаление
На самом деле ещё есть работа с ресурсом. Обычно это изменение. То есть в вашем случае - нужно гарантировать, что другой процесс не сможет работать с уже занятым клиентом.
Обсуждают сегодня