|
|
|
Проблема с ConcurrentHashMap
|
|||
|---|---|---|---|
|
#18+
cdtyjv2) Кто и откуда добавляет сессии в мапку? Где вызов ConcurrentHashMap.put()? Ни в одном из предоставленных вами колчков кода его нет. Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.01.2014, 04:05 |
|
||
|
Проблема с ConcurrentHashMap
|
|||
|---|---|---|---|
|
#18+
делать запрос в базу захватив лок, это конечно мощно ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.01.2014, 05:17 |
|
||
|
Проблема с ConcurrentHashMap
|
|||
|---|---|---|---|
|
#18+
GorloPavel , У меня складывается ощущение, что ваша цель - ни в коем случае не позволить нам оказать вам помощь. Потому что с каждым очередным вашим постом все становится лишь непонятнее Вам попросили сделать две вещи: 1) Показать, как гарантируется уникальность айдишника. 2) Показать, кто и откуда кладет сессии в мапку. Вы же умудрились написать на каждый из этих вопросов по посту ... но ничего не прояснить. 1) Мы не верим на слово, что у вас все корректно инкрементится. Во-первых, потом что если бы у вас все было хорошо, у вас бы не было этого бага. А во-вторых, потому что качество тех урывков кода, что вы показываете, оставляет желать лучшего. Дайте нам код, который генерирует айдишники . 2) Ответьте наконец на вопрос, кто и когда делает put в мапку с сессиями . Вы мне показали метод signInHost , отлично. Но кто его вызывает ? Из каких потоков он вызывается ? И почему вы синхронизируетесь на mSignInSemaphore ? Теперь смотрите дальше. Сначала я прошу вас сказать, какие потоки могут изменять мапку с сессиями для конкретного айдишника. Вы отвечаете, что это может сделать только один поток ( 15391534 ). Потом я прошу показать вас код этого "одного потока", т.е. метод Session.run(). Вы отвечаете, что это вот этот код 15391319 . А теперь вы показываете метод signInHost , который тоже изменяет эту мапку. Но я что-то не вижу, что бы этот метод вызывался из Session.run() . Кто и откуда его все таки вызывает? И что это за странный synchronized (mSignInSemaphore) ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.01.2014, 08:32 |
|
||
|
Проблема с ConcurrentHashMap
|
|||
|---|---|---|---|
|
#18+
GorloPavel, А зачем так делать? session.setSessionId( mStatement.getResultSet() .getInt(4)); session.setLogId( mStatement.getResultSet() .getInt(3)); session.setHostId( mStatement.getResultSet() .getInt(2)); У Вас несколько ResultSet-ов возвращает процедура? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.01.2014, 08:35 |
|
||
|
Проблема с ConcurrentHashMap
|
|||
|---|---|---|---|
|
#18+
0FDGorloPavel, А зачем так делать? session.setSessionId( mStatement.getResultSet() .getInt(4)); session.setLogId( mStatement.getResultSet() .getInt(3)); session.setHostId( mStatement.getResultSet() .getInt(2)); У Вас несколько ResultSet-ов возвращает процедура? Несколько ResultSet не причем, нет вызовов getMoreResults. Хотя в документации и написано getResultSet(): Retrieves the current result as a ResultSet object. This method should be called only once per result. проблем при множественном вызове вроде не должен вызывать. GorloPavel а можно SIGN_IN_HOST показать? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.01.2014, 12:30 |
|
||
|
Проблема с ConcurrentHashMap
|
|||
|---|---|---|---|
|
#18+
cdtyjvДайте нам код, который генерирует айдишники[/b]. Все же элементарно! К примеру есть таблица, в ней 3 поля. host_id(автоинкриментное), host_name, host_password. Делается чертов Код: sql 1. . Вот этот самый host_id и есть ключ в мапе. Он и возвращается в ResultSet-e cdtyjv Ответьте наконец на вопрос, кто и когда делает put в мапку с сессиями. Вы мне показали метод signInHost, отлично. Но кто его вызывает? Из каких потоков он вызывается? И почему вы синхронизируетесь на mSignInSemaphore? Из этого же самого потока! signInHost просто метод в другом классе. mSignInSemaphore нужен для того чтобы эту функцию выполнял только один поток в один момент времени. Представьте что сразу 5к клиентов одновременно пытаются авторизироваться. cdtyjvНо я что-то не вижу, что бы этот метод вызывался из Session.run() Код: java 1. Session реализует интерфейс OnPacketSplitter. В методе просто обрабатываются полученные байты данных и там же вызывается метод signInHost ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.01.2014, 13:53 |
|
||
|
Проблема с ConcurrentHashMap
|
|||
|---|---|---|---|
|
#18+
0FDGorloPavel, А зачем так делать? Уже поправил. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.01.2014, 13:53 |
|
||
|
Проблема с ConcurrentHashMap
|
|||
|---|---|---|---|
|
#18+
GorloPavel, А почему не может быть так, а сразу ConcurrentHashMap<Integer, Session> теряет элементы: mStatement.executeUpdate(String.format("DELETE FROM hosts_online WHERE host_id=%s",getHostId())); <-- тут не удалили ... Hub.HOSTS_SESSIONS.remove(getHostId()); <-- удалил тогда SIGN_IN_HOST добавляет запись в hosts_online с одним host_id, а возвращает другой? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.01.2014, 14:19 |
|
||
|
Проблема с ConcurrentHashMap
|
|||
|---|---|---|---|
|
#18+
0FDА почему не может быть так, а сразу ConcurrentHashMap<Integer, Session> теряет элементы: mStatement.executeUpdate(String.format("DELETE FROM hosts_online WHERE host_id=%s",getHostId())); <-- тут не удалили ... Hub.HOSTS_SESSIONS.remove(getHostId()); <-- удалил тогда SIGN_IN_HOST добавляет запись в hosts_online с одним host_id, а возвращает другой? По-моему это очень вероятный вариант. Я о нем тоже вчера думал. Стоит проверять количество измененых записей. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.01.2014, 14:21 |
|
||
|
Проблема с ConcurrentHashMap
|
|||
|---|---|---|---|
|
#18+
BlazkowiczПо-моему это очень вероятный вариант. Я о нем тоже вчера думал. Стоит проверять количество измененых записей. Не совсем понял о чем вы? getHostId() всегда вернет верный id. Код: java 1. 2. 3. 4. 5. 6. 7. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.01.2014, 14:53 |
|
||
|
Проблема с ConcurrentHashMap
|
|||
|---|---|---|---|
|
#18+
0FDтогда SIGN_IN_HOST добавляет запись в hosts_online с одним host_id, а возвращает другой? Не понял. В процедуре простая строка. При авторизации всегда вернет то что нужно. ID записи. Код: sql 1. 2. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.01.2014, 14:56 |
|
||
|
Проблема с ConcurrentHashMap
|
|||
|---|---|---|---|
|
#18+
GorloPavelНе совсем понял о чем вы? getHostId() всегда вернет верный id. Все программы всегда работают правильно. Тут уже несколько спорных мест в коде указали. Причем в простейшем логе можно было бы всё видеть. А у вас логирование, судя по всему, отсутствует и это некоторое принципиальное решение. Поэтому можно прекращать гадать на кофейной гуще. Код кривой. Сценариев которые могут привести к ошибке несколько. Вы по каждому просто отвечаете, что такого не может быть. Ну, не может, так не может. Вам виднее. Смысл тогда на форуме о чем-то спрашивать если вы сами всё знаете? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.01.2014, 15:03 |
|
||
|
Проблема с ConcurrentHashMap
|
|||
|---|---|---|---|
|
#18+
Вроде проблема нашлась. Спасибо за наводку! Код: java 1. 2. 3. 4. 5. 6. 7. Вообщем проблема в том что в момент(вернее после) DELETE FROM hosts_online WHERE host_id, до Hub.HOSTS_SESSIONS.remove(getHostId()) Может произойти SIGN_IN_HOST и тогда при Hub.HOSTS_SESSIONS.remove(getHostId()) удаляется активная сессия. Происходит это если у клиента нестабильное подключение и происходят постоянные реконнекты. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.01.2014, 17:59 |
|
||
|
Проблема с ConcurrentHashMap
|
|||
|---|---|---|---|
|
#18+
Пока просто Hub.HOSTS_SESSIONS.remove(getHostId()); поместил выше запросов в БД... Завтра буду рефакторить по полной. Ждите новых постов ;) Всем ОГРОМНОЕ СПАСИБО! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.01.2014, 18:04 |
|
||
|
Проблема с ConcurrentHashMap
|
|||
|---|---|---|---|
|
#18+
а если DELETE FROM hosts_online WHERE host_id=%s не отработает? Тут надо не рефакторить а полностью переписывать имхо. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.01.2014, 18:07 |
|
||
|
Проблема с ConcurrentHashMap
|
|||
|---|---|---|---|
|
#18+
GorloPavelchabapokВот вы пишите, что у вас sessionId - это автоинкрементное поле в базе. Смотрите выше. В других случаях естественно используется last_insert_id . Тут какое-то нездоровое общение. С подобной проблемой топик должен быть переполнен от кода, но кода вы не приводите практически. Те разрозненные куски кода, которые есть - это как обрывки. А как можно найти ошибку без кода - мне не понятно. И что там выше я должен был найти - мне тоже непонятно, потому что поиском по last_insert_id ничего не находится кроме моего сообщения. Вы бы хоть дали ссылку на нужное сообщение. У меня вообще создается впечатление, что вы не очень заинтересованы в том, чтобы вам помогли. Поэтому предположу, что вы last_insert_id используете как-то неправильно. В каких "других случаях" используется last_insert_id? Почему в других а не во всех и не в данном случае? Кстати, из того кода что вы привели -- вы делаете SESSONS_COUNT++, а кто делает декремент? Если это делается в другом потоке, то это неправильно и так делать нельзя, потому что ++ неатомарно даже на волатилах. вам нужно что-нибудь почитать про принципы написания многопоточных программ. В гугле полно инфы. И чтобы вам помогли, надо привести ключевые участки кода. Все. Иначе это все гадание и телепатия. :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.01.2014, 12:49 |
|
||
|
Проблема с ConcurrentHashMap
|
|||
|---|---|---|---|
|
#18+
chabapokGorloPavelпропущено... Смотрите выше. В других случаях естественно используется last_insert_id . Тут какое-то нездоровое общение. С подобной проблемой топик должен быть переполнен от кода, но кода вы не приводите практически. Те разрозненные куски кода, которые есть - это как обрывки. А как можно найти ошибку без кода - мне не понятно. И что там выше я должен был найти - мне тоже непонятно, потому что поиском по last_insert_id ничего не находится кроме моего сообщения. Вы бы хоть дали ссылку на нужное сообщение. У меня вообще создается впечатление, что вы не очень заинтересованы в том, чтобы вам помогли. Поэтому предположу, что вы last_insert_id используете как-то неправильно. В каких "других случаях" используется last_insert_id? Почему в других а не во всех и не в данном случае? Кстати, из того кода что вы привели -- вы делаете SESSONS_COUNT++, а кто делает декремент? Если это делается в другом потоке, то это неправильно и так делать нельзя, потому что ++ неатомарно даже на волатилах. вам нужно что-нибудь почитать про принципы написания многопоточных программ. В гугле полно инфы. И чтобы вам помогли, надо привести ключевые участки кода. Все. Иначе это все гадание и телепатия. :) Проблема решена. SESSONS_COUNT++ и SESSONS_COUNT-- в разных потоках. Какие проблемы могут возникнуть и как правильно сделать? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.01.2014, 08:34 |
|
||
|
Проблема с ConcurrentHashMap
|
|||
|---|---|---|---|
|
#18+
GorloPavelПроблема решена. SESSONS_COUNT++ и SESSONS_COUNT-- в разных потоках. Какие проблемы могут возникнуть и как правильно сделать? AtomicInteger ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.01.2014, 13:03 |
|
||
|
Проблема с ConcurrentHashMap
|
|||
|---|---|---|---|
|
#18+
GorloPavel, Как сказал кто-то выше - следите за руками! Например так: потоки А и Б работают одновременно. В вашу переменную записана двойка - т.к. есть два потока. Потоки завешаются одновременно. 1. Поток А загружает в регистр процессора из ячейки памяти значение переменной. В регистр попала двойка. 2. Поток Б загружает в регистр процессора из ячейки памяти значение переменной. В регистр попала двойка. 3. Поток А делает декремент своего регистра. Теперь в регистре потока А единциа. 4. Поток Б делает декремент своего регистра. Теперь в регистре потока Б тоже единциа. 5. Поток А записывает свой регистр в память и завершает работу. 6. Поток Б записывает свой регистр в память и завершает работу. итог - завершилось два потока, а декремент по факту произошел на 1 а не на 2, и в вашей переменной единица. Или так: Поток А завершает работу, а в это время в потоке где у вас accept вы делаете ++ (назовем его поток Б). В переменной единица. 1. Поток А загружает в регистр процессора единицу 2. Поток Б загружает в регистр процессора единицу. 3. поток А делает декремент, получается 0. 4. поток Б делает ++, получается 2. 5. поток А записывает свой регистр в память 6. поток Б записывает свой регистр в память итог - один поток завершился, один создался, а в вашей переменной 2. Или -- то же самое, но в последнем примере 5 и 6 поменяны местами. Итог - один поток завершился, один создался, а в вашей переменной 0. Общий итог - если нет опыта создания многопоточных приложений, то вот так сходу, даже если кажется что все заработало, скорей всего есть еще некоторое кол-во скрытых ошибок, которые обязательно проявят себя при определенном стечении обстоятельств. Описаная выше проблема - одна из тех, с которыми сталкиваешься при написании многопоточных приложений (есть и другие), подобная ситуация называется состояние гонки данных (race condition). Так и гуглите... И вот сюда тоже сходите ru.wikipedia.org/wiki/%D0%A1%D0%BE%D1%81%D1%82%D0%BE%D1%8F%D0%BD%D0%B8%D0%B5_%D0%B3%D0%BE%D0%BD%D0%BA%D0%B8 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.01.2014, 15:26 |
|
||
|
Проблема с ConcurrentHashMap
|
|||
|---|---|---|---|
|
#18+
GorloPavel, Пожалуйста, хватит пытаться вырезать гланды через анальное отверстие, откажитесь от блокирующей записи в базу и получения идентификатора сессии из БД, для уникальных идентификаторов придуман был GUID, его и используйте до или вообще вместо обращения к БД. А если уж так необходимо организовать хранение информации о текущих сессиях в базе - используйте для общения с БД отдельную очередь, обрабатываемую отдельным потоком. Основные "рабочие" потоки могут добавлять в очередь "задачи" для отработки их в базе. Я понимаю, что Вы взялись за интересную для Вас задачу, тем не менее, прежде чем отрабатывать подобные вещи, нужно, как минимум, продумать общую архитектуру решения, продумать механизмы взаимодействия между слоями, а уж потом начинать "ваять"... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.01.2014, 20:32 |
|
||
|
Проблема с ConcurrentHashMap
|
|||
|---|---|---|---|
|
#18+
Alex Kuznetsov , Ну я бы не был так категоричен. Во-первых, автор учится. Ошибается, да. Не всегда может внятно объяснить, что к чему, да. Но не ошибается только тот, кто ничего не делает. Важен не сам факт ошибки или кривой архитектуры, а то, какие выводы автор из этого всего сделает. Во-вторых, с вашими предложениями по гуидам и работе с базой с одного потока можно поспорить. Все существующие СУБД нормально умеют выдавать уникальные значения, будь то сиквенсы в Оракле, или же айдентити в SQL Server / MySQL. И у автора вроде бы нет с этим особых проблем. Ну да ладно, как генерировать id - это переливание из пустого в порожнее, тут и тот, и тот варианты подойдут. А вот работать с базой через один поток - это решение едва ли может назвать хорошей архитектурой. Масштабируемость на нуле, любой затуп, например долгое ожидание блокировки на определнной строке в СУБД, намертво вешает всю систему. Как по мне, с отсутствием деталей задачи автора, мне здесь видится хорошим решением банальнейшие пессимистичные блокировки: 1) Завинчиваем уровень изоляции до REPEATABLE_READ; 2) Потом делаем SELECT id FROM table FOR UPDATE в явной транзакции; 3) Абсолютно безопасно меняем сессию как нам угодно; 4) Закрываем транзакцию. Это и с точки зрения многопоточности легко сделать, ибо почти весь гемор автоматом уходит на сторону СУБД, и масштабируемость будет приемлемая. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.01.2014, 20:42 |
|
||
|
Проблема с ConcurrentHashMap
|
|||
|---|---|---|---|
|
#18+
cdtyjv, Согласен, что автор учится, тем не менее, создаётся впечатление, что слушает, но не слышит... По поводу одного потока для обработки очереди - конечно это кривоватый подход, тем не менее, что мешает сделать несколько потоков для обработки очереди и использовать пул соединений вместо одного? Естественно, что даже это не избавляет от проблем блокировки на уровне одного конкретного соединения. Возьмём к примеру боевые, промышленные серверы приложений - в них уровень работы с БД вынесен в отдельные очереди и потоки, т.е. бизнес логика отвязана от базы данных и помещает задачи БД в очередь, которая и обрабатывается этими самыми потоками. Это в качестве примера... Можно даже сделать "финт ушами" и в очередь помещать DML запросы, а выборки делать непосредственно из потока бизнес логики. Но и при этом можно нарваться на неприятности... Ну т.е. вывод один - в системах подобного масштаба мелочей не бывает и нужно тщательно продумывать все детали. По поводу использования GUID я не зря сказал, потому как, судя по предварительным результатам обсуждения, проблема как раз в связке бизнес логики и БД в разрезе разрозненных потоков. В данном случае генерация уникального идентификатора на стороне бизнес логики, а не БД поможет решить проблему идентификации уникальной сессии. Как пример - тот-же идентификатор сессии в servlet контейнерах... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.01.2014, 08:59 |
|
||
|
Проблема с ConcurrentHashMap
|
|||
|---|---|---|---|
|
#18+
Ребята. Нет никакой проблемы с id-шниками и т.д у меня. Сейчас все работает как надо. Всем огромнейшее СПАСИБО! Вопрос в следующем... К примеру у меня 2000 подключений. И вдруг они разом отключаются, мне нужно зарегистрировать это в БД. Сейчас при таком раскладе у меня сразу будет 2000 подключений к БД(та самая функция removeSession которую мы тут обсуждали). Я же хочу чтобы на это дело потоки вставали в очередь... Просто реально нет времени объяснять как устроена и что у меня тут за система. Можете посмотреть по моим темам. Еще раз спасибо! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.01.2014, 15:18 |
|
||
|
Проблема с ConcurrentHashMap
|
|||
|---|---|---|---|
|
#18+
GorloPavel, каждый поток пусть сам пишет в БД. Так же как это делает банальный JSP при модели сервлет-поток. События конца юзер-сессии не так чАсты, чтобы беспокоиться. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.01.2014, 15:26 |
|
||
|
Проблема с ConcurrentHashMap
|
|||
|---|---|---|---|
|
#18+
Petro123GorloPavel, каждый поток пусть сам пишет в БД. Так же как это делает банальный JSP при модели сервлет-поток. События конца юзер-сессии не так чАсты, чтобы беспокоиться.Повбывавбы. Нет, достаточно количество ядер, конечно и сотни одновременных обновлений одной таблицы разрулят, но за подход - повбывавбы ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.01.2014, 16:57 |
|
||
|
|

start [/forum/topic.php?fid=59&msg=38523350&tid=2127814]: |
0ms |
get settings: |
8ms |
get forum list: |
11ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
191ms |
get topic data: |
7ms |
get forum data: |
2ms |
get page messages: |
46ms |
get tp. blocked users: |
1ms |
| others: | 248ms |
| total: | 518ms |

| 0 / 0 |
