powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Проблема с ConcurrentHashMap
99 сообщений из 99, показаны все 4 страниц
Проблема с ConcurrentHashMap
    #38520610
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Такая проблема. ConcurrentHashMap<Integer, Session> теряет элементы. Дело в том, что с ним работает несколько потоков, какие-то пишут, какие-то читают, а какие-то удаляют элементы. В качестве ключа выступает id сессии из БД. Ключ уникален(автоинкриментное поле). При удалении так же удаляется запись из БД. Но вот проблема! По истечении некоторого времени, по неизвестной причине сессия сохраняется(запись в БД и само подключение клиента), а в HashMap его уже нет. В чем может быть проблема? Спасибо!
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520628
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Проблема в том что ConcurrentHashMap никак не участвует в транзакции на уровне БД. Поэтому очевидно, что так просто гарантировать консистентность состояние в БД и ConcurrentHashMap нельзя. Тем более в многопоточной среде.
Для начала можно релизовать логирование чтобы точно знать что когда и куда записано и удалено.
Вероятность того что ConcurrentHashMap сама по себе что-то там теряет очень мала.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520636
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BlazkowiczПроблема в том что ConcurrentHashMap никак не участвует в транзакции на уровне БД. Поэтому очевидно, что так просто гарантировать консистентность состояние в БД и ConcurrentHashMap нельзя. Тем более в многопоточной среде.
Для начала можно релизовать логирование чтобы точно знать что когда и куда записано и удалено.
Вероятность того что ConcurrentHashMap сама по себе что-то там теряет очень мала.

Я понимаю и поэтому делаю так:
Код: 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.
63.
64.
65.
66.
67.
68.
69.
70.
private void removeSession() { Connection mConnection = null; Statement mStatement = null; try { try { if (sessionType != SessionType.Unknown) { mConnection = getConnection(); mConnection.setAutoCommit(false); } if (sessionType == SessionType.Client) { mStatement = mConnection.createStatement(); mStatement.executeUpdate(String.format("DELETE FROM users_connections WHERE session_id=%s",getSessionId())); mStatement.executeUpdate(String.format("UPDATE connections_log SET disconnect_date_time=NOW() WHERE id=%s",getLogId())); mStatement.executeUpdate(String.format("UPDATE hosts_online SET host_busy=%s WHERE host_id=%s",0, getPartner().getHostId())); mConnection.commit(); getPartner().setPeerToPeer(false); getPartner().sendData(new Packets.Disconnected()); getPartner().setPartner(null); notifyUsers(getPartner().getHostId()); } else if (sessionType == SessionType.Host) { mStatement = mConnection.createStatement(); mStatement.executeUpdate(String.format("DELETE FROM hosts_online WHERE host_id=%s",getHostId())); mStatement.executeUpdate(String.format("UPDATE connections_log SET disconnect_date_time=NOW() WHERE id=%s",getLogId())); mConnection.commit(); if (getPartner() != null) { getPartner().killSession(); } notifyUsers(getHostId()); Hub.HOSTS_SESSIONS.remove(getHostId()); } else if (sessionType == SessionType.User) { mStatement = mConnection.createStatement(); mStatement.executeUpdate(String.format("DELETE FROM users_online WHERE user_session_id=%s",getSessionId())); mConnection.commit(); Hub.USERS_SESSIONS.remove(getSessionId()); } } catch (SQLException e) { LogHelper.logError(e, "removeSession"); if (mConnection != null) {mConnection.rollback();} } } catch (Exception e) { LogHelper.logError(e, "removeSession"); } finally { Hub.SESSONS_COUNT--; try { if (mConnection != null) {mConnection.close();} if (mStatement != null) {mStatement.close();} } catch (SQLException e) { LogHelper.logError(e, "removeSession"); } } }

...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520640
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Более того при выполнении метода LogHelper.logError, мне еще и письмо приходит на мыло. Но дело в том, что этого не происходит... Значит все нормально.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520648
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Фишка в том, что этот метод removeSession вызывается при потере подключения Socket:

Код: 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.
try {
			int receivedBytes=0;
			byte[] dataBuffer = new byte[Hub.SESSION_BUFFER_SIZE];
			InputStream stream=mClientSocket.getInputStream();
			
			//Пока данные есть...
			while ((receivedBytes = stream.read(dataBuffer, 0, dataBuffer.length)) != -1) {
				if(!isPeerToPeer()){
					mPacketSplitter.splitData(dataBuffer, receivedBytes);
				}
				else{
					getPartner().sendRawData(dataBuffer, receivedBytes);
				}
			}

			removeSession();
		}catch (Exception e) {
			removeSession();
		}
		finally{
			try {
				mClientSocket.close();
			} catch (IOException e) {
				System.out.println(String.format("ERROR CLOSE! ID =%s",getHostId()));
				e.printStackTrace();
			}
		}




Но при этом клиент может взаимодействовать с системой. Т.е соединение точно есть. Но из HOSTS_SESSIONS пропадает. Т.е get по ключу возвращает null
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520663
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сделайте меня это развидеть, пожалуйста.
Полиморфизм? Первый раз слышу! Нужен ещё один SessionType? Не беда - скопипастим ещё один if блок.
SQL Injection/binding variables/query cache... Да, ну это всё.
Extract variable. Это где такое?
Логирование? Только для ошибок. Если нет Exception-а, значит всё нормально и логировать незачем.
Hub.SESSONS_COUNT--. В многопоточной системе? Really?
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520675
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GorloPavel ,
Ну как вам уже ответили, вероятность того, что это баг в ConcurrentHashMap, стремиться к нулю. А вот вероятность того, что это гонка у вас в коде, примерно 99,999%. Где именно сидит эта гонка мы не знаем, и знать не можем, так как вы нам показали только одно из мест, где идет работа с этой мапкой.
Но в целом ваш код выглядит очень плохо с точки зрения многопоточности, и я даже с достаточно высокой вероятностью могу предположить следующее:
1) В методе removeSession вы сначала удаляете из базы, а потом удаляете из мапки (это мы видим в том коде, что вы дали).
2) А в методe addSession (или как он у вас называется?) вы сначала пишете в базу, а потом пишете в мапку.
3) Теперь следите за руками, поток 1 вызывает removeSession, поток 2 вызывает addSession, и так получается, что эти операции выполняются в следующем порядке:
Поток 2: создать сессию;
Поток 1: удалить сессию;
Поток 1: Hub.USERS_SESSIONS.remove(id);
Поток 2: Hub.USERS_SESSIONS.put(id, ...).

Все, сессии в базе нет, а в мапке есть.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520676
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Blazkowicz,

Я конечно понимаю. Но опыт приходит со временем. Если можно, то покажите как правильно. На самом деле String.format для запросов только в этом месте программы. Так везде CallableStatement или PreparedStatement. Hub.SESSONS_COUNT-- как ни странно работает нормально :)
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520683
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjv,
Сессию удалить может только сам поток сессии и put вызывает он же.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520697
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GorloPavelЯ конечно понимаю. Но опыт приходит со временем.

Половину этих вопросов нужно знать через год комерческого программирования на Java.

GorloPavelЕсли можно, то покажите как правильно.
Правильно писать короткие методы. Чтобы не вываливать простыню на форум, а четко понимать в каком методе может быть проблема.
Правильно заменять if\else на полиморфизм, особенно если блоки схожие, то выносить общий код.
Правильно использовать переменные а не вызывать один и тот же метод 4 раза подряд.
Правильно писать понятный самодокументируемый код а не вводить читателя в ступор вот такими пируэтами:
getPartner().setPartner(null);
Правильно держать SQL запросы вне Java кода, либо использовать Query DSL.
Правильно разбирвать проект на абстрактные слои, а не запускать SQL запросы откуда вздумается.
Правильно использовать binding variable для параметров SQL запроса.
Правильно логировать все изменения состояния с разным уровнем логирования, а не только Exception-ы.
Правильно использовать фреймверки логирования, а не LogHelper, который везде вызывается, так что даже не понятно кто писал в лог.

GorloPavelHub.SESSONS_COUNT-- как ни странно работает нормально :)
Правильно изучить многопоточность и атомарные операции, прежде чем пытаться написать что-то пригодное для использования в многопоточной среде.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520699
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GorloPavelcdtyjv,
Сессию удалить может только сам поток сессии и put вызывает он же.
Логируете все операции с session id и тогда по логу будет видно что происходило и почему для конкретного session id, который вы обнаруили в БД.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520727
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Blazkowicz,

Спасибо за ответы. Замечания приняты. Но я все равно не пойму куда могут деться сессии из мапа в этом коде, если put и remove может выполнять только сам поток сессии. Логировать сейчас что-то очень проблемно. Сервис работает и его используют тысячи пользователей. Я просто погрязну в логах на вечно. Может все таки сделать так как вы посоветовали в моей предыдущей теме? Хотелось бы увидеть пример от гуру :)
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520731
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GorloPavel ,
Что такое "сам поток сессии"? Например, у вас 1000 сессий. Что, к каждой постоянно привязан какой-то поток один единственный поток?
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520736
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GorloPavel,

Не понятно как используется SESSONS_COUNT.
Не понятно как вы локализовали проблему в removeSession. Почему другие методы исключены?
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520737
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjv,

Это поток(Thread) сокета. В нем обрабатываются данные от клиента и к примеру при авторизации эта сессия добавляется в HashMap. При потере соединения сессия должна удалить себя из HashMap и БД.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520738
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjv,

Это поток(Thread) сокета. В нем обрабатываются данные от клиента и к примеру при авторизации эта сессия добавляется в HashMap. При потере соединения сессия должна удалить себя из HashMap и БД.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520740
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GorloPavelЯ просто погрязну в логах на вечно.
Зачем в них грязнуть? Пишите в файлы. Храните все файлы за последние несколько дней. Проблема выделить под это дело пару гигабайт HDD?
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520742
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Blazkowicz,

Потому что в других методах нет remove из HashMap. Только в этом методе . В остальных get и put. Про put я уже объяснил, что он тоже в этом потоке. Т.е сессия сама себя добавляет и сама себя удаляет при отключении.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520743
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GorloPavelЭто поток(Thread) сокета. В нем обрабатываются данные от клиента и к примеру при авторизации эта сессия добавляется в HashMap. При потере соединения сессия должна удалить себя из HashMap и БД.
Бляха-муха. Сокет сервер на коленке. Чем готовые решения не угодили-то?
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520746
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BlazkowiczGorloPavel,
Не понятно как используется SESSONS_COUNT.

Да просто чтобы знать сколько сессий активных. Ну и кикать их если достигнут лимит.

Вот кстати как я их "порождаю"

Код: 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.
private class ListenConnections implements Runnable
	{
		public void run() {
			try {
				
				Socket acceptClient = null;
				
				while(true){
					
					acceptClient=mSocketListener.accept();
					
					if(SESSONS_COUNT<SETTINGS.HUB_MAX_CONNECTIONS){
						acceptClient.setSoTimeout(SETTINGS.HUB_TIME_OUT);
						new Thread(new Session(acceptClient,Hub.this)).start();
						SESSONS_COUNT++;
					}else{
						sendData(acceptClient, new Packets.Error(ErrorCodes.SERVER_OVERLOADED));
						acceptClient.close();
					}
					
				}
			}catch(Exception ex){
				ex.printStackTrace();
				if(!mStopServer){
					LogHelper.logError(ex, "ListenConnections");
				}				
			}
		}
	}

...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520749
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BlazkowiczБляха-муха. Сокет сервер на коленке. Чем готовые решения не угодили-то?
Так вышло. Уже ничего не поделать. Надо решать проблему в этом коде.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520751
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
getSessionId() возвращает final поле?
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520763
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BlazkowiczgetSessionId() возвращает final поле?
Оно не меняется нигде. Только задается однажды(из БД) и все. Нет не final.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520764
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
С каким типом сессий возникает проблема?
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520765
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GorloPavelНет не final.
Зря.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520766
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BlazkowiczС каким типом сессий возникает проблема?
Host
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520771
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BlazkowiczGorloPavelНет не final.
Зря.
Может быть в этом проблема? Но ведь нигде не меняется. Это точно.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520781
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GorloPavelМожет быть в этом проблема? Но ведь нигде не меняется. Это точно.
Может быть что угодно. Вы ничего не логируете ведь. Совершенно не понятно что из каких потоков вызывается.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520788
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BlazkowiczGorloPavelМожет быть в этом проблема? Но ведь нигде не меняется. Это точно.
Может быть что угодно. Вы ничего не логируете ведь. Совершенно не понятно что из каких потоков вызывается.
removeSession вызывает сам поток. Метод в котором put вызывает он же. Т.е поток сам добавляет себя в HashMap и удаляет когда происходит отключение.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520791
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GorloPavel ,
Понятно, тогда есть два варианта:
1) Все операции с конкретным уникальным ID идут только в одном потоке , вы в этом уверены на 100%. Тогда у вас какой-то косяк с отловом исключений при работе с базой, или просто какая-то бага в коде.
2) Все таки не все операции для данного ID идут в одном потоке. Или же все, но ID может быть не уникальным. Тогда это скорее всего баг с concurrency.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520794
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И покажите метод Session.run().
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520795
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjv1) Все операции с конкретным уникальным ID идут только в одном потоке , вы в этом уверены на 100%. Тогда у вас какой-то косяк с отловом исключений при работе с базой, или просто какая-то бага в коде.

Судя по предущему вопросу и этой теме GorloPavel на 100% уверен, что это так. А на самом деле иначе.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520796
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GorloPavelremoveSession вызывает сам поток. Метод в котором put вызывает он же. Т.е поток сам добавляет себя в HashMap и удаляет когда происходит отключение.
Код: java
1.
2.
3.
if (getPartner() != null) {
 getPartner().killSession();
}


Этот код случайно не вызывает removeSession другой сессии из своего потока?
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520799
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
[quot cdtyjv] GorloPavel ,
Понятно, тогда есть два варианта:
1) Все операции с конкретным уникальным ID идут только в одном потоке , вы в этом уверены на 100%. Тогда у вас какой-то косяк с отловом исключений при работе с базой, или просто какая-то бага в коде.
Операция чтения и получения Session может быть в другом потоке. Те вот это к примеру:
Код: java
1.
Session hostSession = Hub.HOSTS_SESSIONS.get(getHostId());//Ищем хост среди подключений
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520804
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BlazkowiczЭтот код случайно не вызывает removeSession другой сессии из своего потока?
Нет. Вот он:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
public void killSession() {
		if (mClientSocket != null) {
			try {
				mClientSocket.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}



После него происходит Exception в потоке cессии и она уже выполняет removeSession.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520809
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvИ покажите метод Session.run().

На первой странице, там где removeSession вызывается. Это и есть метод run, т.к
Session implements Runnable
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520819
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BlazkowiczСудя по предущему вопросу и этой теме GorloPavel на 100% уверен, что это так. А на самом деле иначе.
Ну ведь вы сами видите где removeSession, а put-ы происходят по результатам mPacketSplitter.splitData(dataBuffer, receivedBytes); в методе run. Сам HashMap статическое поле класса Hub.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520829
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BlazkowiczgetSessionId() возвращает final поле?
Не понял кстати. Ведь SessionId устанавливается в процессе работы. Как оно может быть final?
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520832
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GorloPavelНа первой странице, там где removeSession вызывается. Это и есть метод run, т.к
Session implements Runnable Окей, где тогда сессия кладется в ConcurrentHashMap?
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520833
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GorloPavelОперация чтения и получения Session может быть в другом потоке. Те вот это к примеру:Что-то я уже устал, если честно Одно противоречие за другим.
Хорошо, что такое "получение" сессии. Вот какой-то другой поток "получил" сессию, что он может с ней дальше делать?
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520847
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GorloPavelBlazkowiczgetSessionId() возвращает final поле?
Не понял кстати. Ведь SessionId устанавливается в процессе работы. Как оно может быть final?
Устанавливать sessionId в конструкторе session после процесса работы.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520850
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvGorloPavelОперация чтения и получения Session может быть в другом потоке. Те вот это к примеру:Что-то я уже устал, если честно Одно противоречие за другим.
Хорошо, что такое "получение" сессии. Вот какой-то другой поток "получил" сессию, что он может с ней дальше делать?
Я привел пример выше.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520856
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjv,

Вызывать методы в которых не происходят изменения id или удаление сессии из HashMap. Почитайте внимательно тему. remove только в одном месте. Id сессий устанавлтваются единожды при авторизации клиента. Id это автоинкриментное-уникальное поле в БД.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520870
ivanra
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
GorloPavel,
каким образом обеспечивается уникальность getHostId() для каждого потока?
Если по ip, то что будет, если на одном хосте создадут 2 соединения, а потом 1 прибъют?
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520874
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ivanraGorloPavel,
каким образом обеспечивается уникальность getHostId() для каждого потока?
Если по ip, то что будет, если на одном хосте создадут 2 соединения, а потом 1 прибъют?
Не по ip
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520876
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GorloPavelПочитайте внимательно тему.
Такое ощущение, что у нас с cdtyjv косяк к продакшн сервере.

Мне тоже до сих пор не понятно. Откуда уверенность что проблема в удалении, а не в создании.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520907
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GorloPavelПочитайте внимательно тему.Коллега, вот вокруг вас собралось уже 4-5 мемберов, и отчаянно пытаются понять, что у вас там происходит. Как думаете, это мы все тупые и невнимательные или это вы плохо объясняете? Повторю два принципиальных на данный момент вопроса:
1) Каким образом вы гарантируете уникальность идентификатора? Покажите код.
2) Кто и откуда добавляет сессии в мапку? Где вызов ConcurrentHashMap.put()? Ни в одном из предоставленных вами колчков кода его нет.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38520943
chabapok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А можно и я тоже попытаюсь потелепатить?

Вот вы пишите, что у вас sessionId - это автоинкрементное поле в базе. Но как вы его получаете?
Большинство новичков делают insert, а потом берут это поле при помощи чего-то вроде "SELECT MAX(id) ....". Вот мне почему-то кажется, что вы сделали так (ни разу не встречал ничего другого), но фишка в том, что так делать нельзя! Ведь после insert может сразобтать еще один insert в другом потоке, а только потом select в исходном и другом. В результате вы двух потоках заимеете одинаковый id сессии. Потом один из них завершает сессию и удаляет ваш id из мапы...

А ведь таких потоков может быть и больше 2.

Как быть? В mysql есть функция LAST_INSERT_ID(), в других базах - свои для решения этой проблемы, и еще можно дергать эту функцию через jdbc (гуглить: jdbc last insert id). Надо пользоваться ими. Они возвращают именно то id, которое было только что вставлено в данно коннекшене с базой.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38521201
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvКаким образом вы гарантируете уникальность идентификатора? Покажите код.

Да что тут показывать. Все просто. В БД есть пара логин-пароль, у записи автоинкриментное поле host_id. Клиент посылает данные авторизации выполняется SELECT и в программу возвращается id.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38521202
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chabapokВот вы пишите, что у вас sessionId - это автоинкрементное поле в базе.
Смотрите выше. В других случаях естественно используется last_insert_id .
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38521204
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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.
public void signInHost(Session session,Packets.HelloServer hello) {
		synchronized (mSignInSemaphore) {
			//Connection mConnection=null;
			CallableStatement mStatement = null;
			ResultSet mResult = null;

			try {
				try{
					
					//mConnection=getDbConnection();
					mStatement = mConnection.prepareCall("CALL SIGN_IN_HOST(?,?,?,?,?,?,?,?)");
					mStatement.setString(1, hello.name);
					mStatement.setString(2, hello.password);
					
                                        ....................................................
					....................................................

					mResult = mStatement.executeQuery();
					mConnection.commit();
					
					if (mResult.next()) {

						if (mResult.getString(1).equals("NOT_REGISTERED")) {
							session.sendData(new Packets.Error(ErrorCodes.INVALID_USERNAME_OR_PASSWORD));
							session.killSession();
						} else if (mResult.getString(1).equals("BUSY")) {
							session.killSession();
						} else if (mResult.getString(1).equals("ONLINE")) {
							session.setSessionId(mStatement.getResultSet().getInt(4));
							session.setLogId(mStatement.getResultSet().getInt(3));
							session.setHostId(mStatement.getResultSet().getInt(2));
							session.sessionType = Session.SessionType.Host;
							session.sendData(new Packets.HelloHost());
							session.setEncryptionKey(hello.password.substring(0, 15));
		
							HOSTS_SESSIONS.put(session.getHostId(), session);
						}

					} else {
						session.killSession();
					}
				}
				catch(SQLException e){
					LogHelper.logError(e, "signInHost");
					session.killSession();
					if(mConnection!=null){mConnection.rollback();}
				}
			} catch (Exception e) {
				LogHelper.logError(e, "signInHost");
				session.killSession();
			}
			finally {
				try {
					//if (mConnection!=null){mConnection.close();}
					if (mStatement != null) {mStatement.close();}
					if (mResult != null) {mResult.close();}
				} catch (SQLException e) {
					LogHelper.logError(e, "signInHost");
				}
			}
		}
    }


...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38521225
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
делать запрос в базу захватив лок, это конечно мощно
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38521276
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GorloPavel ,
У меня складывается ощущение, что ваша цель - ни в коем случае не позволить нам оказать вам помощь. Потому что с каждым очередным вашим постом все становится лишь непонятнее Вам попросили сделать две вещи:
1) Показать, как гарантируется уникальность айдишника.
2) Показать, кто и откуда кладет сессии в мапку.
Вы же умудрились написать на каждый из этих вопросов по посту ... но ничего не прояснить.

1) Мы не верим на слово, что у вас все корректно инкрементится. Во-первых, потом что если бы у вас все было хорошо, у вас бы не было этого бага. А во-вторых, потому что качество тех урывков кода, что вы показываете, оставляет желать лучшего. Дайте нам код, который генерирует айдишники .
2) Ответьте наконец на вопрос, кто и когда делает put в мапку с сессиями . Вы мне показали метод signInHost , отлично. Но кто его вызывает ? Из каких потоков он вызывается ? И почему вы синхронизируетесь на mSignInSemaphore ?
Теперь смотрите дальше. Сначала я прошу вас сказать, какие потоки могут изменять мапку с сессиями для конкретного айдишника. Вы отвечаете, что это может сделать только один поток ( 15391534 ). Потом я прошу показать вас код этого "одного потока", т.е. метод Session.run(). Вы отвечаете, что это вот этот код 15391319 . А теперь вы показываете метод signInHost , который тоже изменяет эту мапку. Но я что-то не вижу, что бы этот метод вызывался из Session.run() . Кто и откуда его все таки вызывает? И что это за странный synchronized (mSignInSemaphore) ?
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38521281
0FD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GorloPavel,

А зачем так делать?
session.setSessionId( mStatement.getResultSet() .getInt(4));
session.setLogId( mStatement.getResultSet() .getInt(3));
session.setHostId( mStatement.getResultSet() .getInt(2));
У Вас несколько ResultSet-ов возвращает процедура?
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38521711
0FD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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 показать?
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38521878
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvДайте нам код, который генерирует айдишники[/b].
Все же элементарно! К примеру есть таблица, в ней 3 поля. host_id(автоинкриментное), host_name, host_password. Делается чертов
Код: sql
1.
SELECT host_id FROM hosts WHERE host_name=name AND host_password=password

. Вот этот самый host_id и есть ключ в мапе. Он и возвращается в ResultSet-e

cdtyjv Ответьте наконец на вопрос, кто и когда делает put в мапку с сессиями. Вы мне показали метод signInHost, отлично. Но кто его вызывает? Из каких потоков он вызывается? И почему вы синхронизируетесь на mSignInSemaphore?

Из этого же самого потока! signInHost просто метод в другом классе. mSignInSemaphore нужен для того чтобы эту функцию выполнял только один поток в один момент времени. Представьте что сразу 5к клиентов одновременно пытаются авторизироваться.

cdtyjvНо я что-то не вижу, что бы этот метод вызывался из Session.run()
Код: java
1.
mPacketSplitter.splitData(dataBuffer, receivedBytes);


Session реализует интерфейс OnPacketSplitter. В методе просто обрабатываются полученные байты данных и там же вызывается метод signInHost
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38521880
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
0FDGorloPavel,
А зачем так делать?

Уже поправил.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38521936
0FD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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, а возвращает другой?
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38521941
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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, а возвращает другой?
По-моему это очень вероятный вариант. Я о нем тоже вчера думал. Стоит проверять количество измененых записей.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38522027
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BlazkowiczПо-моему это очень вероятный вариант. Я о нем тоже вчера думал. Стоит проверять количество измененых записей.
Не совсем понял о чем вы? getHostId() всегда вернет верный id.

Код: java
1.
2.
3.
4.
5.
6.
7.
mStatement = mConnection.createStatement();
mStatement.executeUpdate(String.format("DELETE FROM hosts_online WHERE host_id=%s",getHostId()));
mStatement.executeUpdate(String.format("UPDATE connections_log SET disconnect_date_time=NOW() WHERE id=%s",getLogId()));
					
mConnection.commit();

Hub.HOSTS_SESSIONS.remove(getHostId());
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38522035
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
0FDтогда SIGN_IN_HOST добавляет запись в hosts_online с одним host_id, а возвращает другой?

Не понял. В процедуре простая строка. При авторизации всегда вернет то что нужно. ID записи.
Код: sql
1.
2.
SELECT host_id INTO host_id
FROM hosts WHERE host_name=name AND host_password=password;
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38522053
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GorloPavelНе совсем понял о чем вы? getHostId() всегда вернет верный id.

Все программы всегда работают правильно. Тут уже несколько спорных мест в коде указали. Причем в простейшем логе можно было бы всё видеть. А у вас логирование, судя по всему, отсутствует и это некоторое принципиальное решение. Поэтому можно прекращать гадать на кофейной гуще. Код кривой. Сценариев которые могут привести к ошибке несколько. Вы по каждому просто отвечаете, что такого не может быть. Ну, не может, так не может. Вам виднее. Смысл тогда на форуме о чем-то спрашивать если вы сами всё знаете?
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38522355
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вроде проблема нашлась. Спасибо за наводку!

Код: java
1.
2.
3.
4.
5.
6.
7.
mStatement = mConnection.createStatement();
mStatement.executeUpdate(String.format("DELETE FROM hosts_online WHERE host_id=%s",getHostId()));
mStatement.executeUpdate(String.format("UPDATE connections_log SET disconnect_date_time=NOW() WHERE id=%s",getLogId()));
					
mConnection.commit();

Hub.HOSTS_SESSIONS.remove(getHostId());



Вообщем проблема в том что в момент(вернее после) DELETE FROM hosts_online WHERE host_id, до Hub.HOSTS_SESSIONS.remove(getHostId()) Может произойти SIGN_IN_HOST и тогда при Hub.HOSTS_SESSIONS.remove(getHostId()) удаляется активная сессия. Происходит это если у клиента нестабильное подключение и происходят постоянные реконнекты.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38522364
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пока просто Hub.HOSTS_SESSIONS.remove(getHostId()); поместил выше запросов в БД... Завтра буду рефакторить по полной. Ждите новых постов ;) Всем ОГРОМНОЕ СПАСИБО!
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38522371
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
а если DELETE FROM hosts_online WHERE host_id=%s не отработает? Тут надо не рефакторить а полностью переписывать имхо.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38522880
chabapok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GorloPavelchabapokВот вы пишите, что у вас sessionId - это автоинкрементное поле в базе.
Смотрите выше. В других случаях естественно используется last_insert_id .

Тут какое-то нездоровое общение. С подобной проблемой топик должен быть переполнен от кода, но кода вы не приводите практически. Те разрозненные куски кода, которые есть - это как обрывки. А как можно найти ошибку без кода - мне не понятно. И что там выше я должен был найти - мне тоже непонятно, потому что поиском по last_insert_id ничего не находится кроме моего сообщения. Вы бы хоть дали ссылку на нужное сообщение. У меня вообще создается впечатление, что вы не очень заинтересованы в том, чтобы вам помогли. Поэтому предположу, что вы last_insert_id используете как-то неправильно.

В каких "других случаях" используется last_insert_id? Почему в других а не во всех и не в данном случае? Кстати, из того кода что вы привели -- вы делаете SESSONS_COUNT++, а кто делает декремент? Если это делается в другом потоке, то это неправильно и так делать нельзя, потому что ++ неатомарно даже на волатилах.

вам нужно что-нибудь почитать про принципы написания многопоточных программ. В гугле полно инфы.

И чтобы вам помогли, надо привести ключевые участки кода. Все. Иначе это все гадание и телепатия. :)
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38523350
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chabapokGorloPavelпропущено...

Смотрите выше. В других случаях естественно используется last_insert_id .

Тут какое-то нездоровое общение. С подобной проблемой топик должен быть переполнен от кода, но кода вы не приводите практически. Те разрозненные куски кода, которые есть - это как обрывки. А как можно найти ошибку без кода - мне не понятно. И что там выше я должен был найти - мне тоже непонятно, потому что поиском по last_insert_id ничего не находится кроме моего сообщения. Вы бы хоть дали ссылку на нужное сообщение. У меня вообще создается впечатление, что вы не очень заинтересованы в том, чтобы вам помогли. Поэтому предположу, что вы last_insert_id используете как-то неправильно.

В каких "других случаях" используется last_insert_id? Почему в других а не во всех и не в данном случае? Кстати, из того кода что вы привели -- вы делаете SESSONS_COUNT++, а кто делает декремент? Если это делается в другом потоке, то это неправильно и так делать нельзя, потому что ++ неатомарно даже на волатилах.

вам нужно что-нибудь почитать про принципы написания многопоточных программ. В гугле полно инфы.

И чтобы вам помогли, надо привести ключевые участки кода. Все. Иначе это все гадание и телепатия. :)

Проблема решена. SESSONS_COUNT++ и SESSONS_COUNT-- в разных потоках. Какие проблемы могут возникнуть и как правильно сделать?
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38523422
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GorloPavelПроблема решена. SESSONS_COUNT++ и SESSONS_COUNT-- в разных потоках. Какие проблемы могут возникнуть и как правильно сделать?
AtomicInteger
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38523508
chabapok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38525003
Alex Kuznetsov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GorloPavel,

Пожалуйста, хватит пытаться вырезать гланды через анальное отверстие, откажитесь от блокирующей записи в базу и получения идентификатора сессии из БД, для уникальных идентификаторов придуман был GUID, его и используйте до или вообще вместо обращения к БД.
А если уж так необходимо организовать хранение информации о текущих сессиях в базе - используйте для общения с БД отдельную очередь, обрабатываемую отдельным потоком.
Основные "рабочие" потоки могут добавлять в очередь "задачи" для отработки их в базе.

Я понимаю, что Вы взялись за интересную для Вас задачу, тем не менее, прежде чем отрабатывать подобные вещи, нужно, как минимум, продумать общую архитектуру решения, продумать механизмы взаимодействия между слоями, а уж потом начинать "ваять"...
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38525009
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alex Kuznetsov ,
Ну я бы не был так категоричен. Во-первых, автор учится. Ошибается, да. Не всегда может внятно объяснить, что к чему, да. Но не ошибается только тот, кто ничего не делает. Важен не сам факт ошибки или кривой архитектуры, а то, какие выводы автор из этого всего сделает.
Во-вторых, с вашими предложениями по гуидам и работе с базой с одного потока можно поспорить. Все существующие СУБД нормально умеют выдавать уникальные значения, будь то сиквенсы в Оракле, или же айдентити в SQL Server / MySQL. И у автора вроде бы нет с этим особых проблем. Ну да ладно, как генерировать id - это переливание из пустого в порожнее, тут и тот, и тот варианты подойдут. А вот работать с базой через один поток - это решение едва ли может назвать хорошей архитектурой. Масштабируемость на нуле, любой затуп, например долгое ожидание блокировки на определнной строке в СУБД, намертво вешает всю систему. Как по мне, с отсутствием деталей задачи автора, мне здесь видится хорошим решением банальнейшие пессимистичные блокировки:
1) Завинчиваем уровень изоляции до REPEATABLE_READ;
2) Потом делаем SELECT id FROM table FOR UPDATE в явной транзакции;
3) Абсолютно безопасно меняем сессию как нам угодно;
4) Закрываем транзакцию.
Это и с точки зрения многопоточности легко сделать, ибо почти весь гемор автоматом уходит на сторону СУБД, и масштабируемость будет приемлемая.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38525197
Alex Kuznetsov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjv,

Согласен, что автор учится, тем не менее, создаётся впечатление, что слушает, но не слышит...

По поводу одного потока для обработки очереди - конечно это кривоватый подход, тем не менее, что мешает сделать несколько потоков для обработки очереди и использовать пул соединений вместо одного?
Естественно, что даже это не избавляет от проблем блокировки на уровне одного конкретного соединения.

Возьмём к примеру боевые, промышленные серверы приложений - в них уровень работы с БД вынесен в отдельные очереди и потоки, т.е. бизнес логика отвязана от базы данных и помещает задачи БД в очередь, которая и обрабатывается этими самыми потоками. Это в качестве примера...

Можно даже сделать "финт ушами" и в очередь помещать DML запросы, а выборки делать непосредственно из потока бизнес логики. Но и при этом можно нарваться на неприятности... Ну т.е. вывод один - в системах подобного масштаба мелочей не бывает и нужно тщательно продумывать все детали.

По поводу использования GUID я не зря сказал, потому как, судя по предварительным результатам обсуждения, проблема как раз в связке бизнес логики и БД в разрезе разрозненных потоков. В данном случае генерация уникального идентификатора на стороне бизнес логики, а не БД поможет решить проблему идентификации уникальной сессии. Как пример - тот-же идентификатор сессии в servlet контейнерах...
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38525741
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ребята. Нет никакой проблемы с id-шниками и т.д у меня. Сейчас все работает как надо. Всем огромнейшее СПАСИБО! Вопрос в следующем... К примеру у меня 2000 подключений. И вдруг они разом отключаются, мне нужно зарегистрировать это в БД. Сейчас при таком раскладе у меня сразу будет 2000 подключений к БД(та самая функция removeSession которую мы тут обсуждали). Я же хочу чтобы на это дело потоки вставали в очередь... Просто реально нет времени объяснять как устроена и что у меня тут за система. Можете посмотреть по моим темам. Еще раз спасибо!
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38525756
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GorloPavel,
каждый поток пусть сам пишет в БД.
Так же как это делает банальный JSP при модели сервлет-поток.
События конца юзер-сессии не так чАсты, чтобы беспокоиться.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38525930
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petro123GorloPavel,
каждый поток пусть сам пишет в БД.
Так же как это делает банальный JSP при модели сервлет-поток.
События конца юзер-сессии не так чАсты, чтобы беспокоиться.Повбывавбы.
Нет, достаточно количество ядер, конечно и сотни одновременных обновлений одной таблицы разрулят, но за подход - повбывавбы
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38525955
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GorloPavelРебята. Нет никакой проблемы с id-шниками и т.д у меня. Сейчас все работает как надо. Всем огромнейшее СПАСИБО! Вопрос в следующем... К примеру у меня 2000 подключений. И вдруг они разом отключаются, мне нужно зарегистрировать это в БД. Сейчас при таком раскладе у меня сразу будет 2000 подключений к БД(та самая функция removeSession которую мы тут обсуждали). Я же хочу чтобы на это дело потоки вставали в очередь... Просто реально нет времени объяснять как устроена и что у меня тут за система. Можете посмотреть по моим темам. Еще раз спасибо!Хотите - не хотите, но объяснить, зачем вы хотите ставить потоки в очередь, вам придется :-)
Окей, 2000 соединений оборвалось. Первым делом замечу, что с таким количеством клиентов, да если еще и каждому выделено по потоку, вашему приложению уже будет достаточно плоховасто. При таком количестве потоков здесь с большой вероятностью напрашивается NIO-сервер, который бы разруливал все IO и работу с СУБД в ограниченном небольшом количестве потоков.

Как бы то ни было, пуксай у вас стандартные блокирующие сокеты, и по потоку на соединение. Вдруг две тысячи соединений сдохли. Они все начинают разом ломиться в базу. Но если у вас по уму сделана работа с базой, то есть пул соединений, с которым вы работаете через DataSource, то ничего страшного в этом нет - у вас в каждый момент времени будет работать не более N потоков, где N - количество соединений в пуле. То есть это уже и есть некий аналог очереди.

С другой стороны, если у вас нет никаких проблем с блокировками в СУБД, и по факту закрытия соединения вам надо обновить одну строку в СУБД, и больше никогда ее не трогать, то в целях оптимизации можно задуматься о вынесении логики по "закрытию" сессии в СУБД в отдельный поток, который будет фигачить эти обновления батчами. То есть вам надо застартавать поток, который в бесконечном цикле будет смотреть на какую-нибудь коллекцию. А в этой коллекцию вы складываете все айдишники закрытых коннекторв. А поток либо по таймауту, либо по факту превышения коллекцией определенного размера, забирает эти айдишники из коллекции, и далее либо формирует 1 (один) запрос в СУБД, либо же формирует по одному запросу на каждый ID, как это у вас сделано сейчас, но делает bulk update.

Резюмируя:
1) Если вы паритесь о производительности, то вам надо в первую очередь смотреть в сторону NIO, ибо 2000 потоков от 2000 клиентов могут вообще не выжить у вас. Одновременная запись в базу из этих 2000 потоков является намного меньшим злом, чем сам факт наличия этих потоков в таком огромном количестве.
2) Если все равно хочется заоптимизировать закрытия сессии, то попробуйте сделать так, как я описал выше. Одна коллекция. Один поток в бесконечном цикле, который периодически смотрит на эту коллекцию, и применяет накопленные изменения либо через один большой SQL, либо через множество маленьких SQLей, но в bulk режиме.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38525967
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. SidorovPetro123GorloPavel,
каждый поток пусть сам пишет в БД.
Так же как это делает банальный JSP при модели сервлет-поток.
События конца юзер-сессии не так чАсты, чтобы беспокоиться.Повбывавбы.
Нет, достаточно количество ядер, конечно и сотни одновременных обновлений одной таблицы разрулят, но за подход - повбывавбы
именно СУБД заточена на МНОГОпользовательскую ПАРАЛЛьельную работу.
Лишь бы соблюдалось - поток = коннект(соединение).
Так что при чём тут ядра?
Для уменьшения Одновременных соединений (< 3000) есть пул.

Если ты сервер, не суетись под клиентом ))) (с)
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38525968
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjv1) Если вы паритесь о производительности, то вам надо в первую очередь смотреть в сторону NIO, ибо 2000 потоков от 2000 клиентов могут вообще не выжить у вас. Одновременная запись в базу из этих 2000 потоков является намного меньшим злом , чем сам факт наличия этих потоков в таком огромном количествеВыделено мною.
На менее топовом железе пробовали работать?
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38526334
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
может посмотреть в сторону netty ?
Зачем Вам собственный цик с гвоздями ??? возьмите готовый :

http://habrahabr.ru/post/136765/
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38526342
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Atum1может посмотреть в сторону netty ?
Зачем Вам собственный цик с гвоздями ??? возьмите готовый :

http://habrahabr.ru/post/136765/
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38526344
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Atum1может посмотреть в сторону netty ?
Зачем Вам собственный цик с гвоздями ??? возьмите готовый :

http://habrahabr.ru/post/136765/

Было: 15391945

И мне больше вот эта статья нравится
http://habrahabr.ru/post/136456/ ...Уже почти год мы пишем свою реализацию сервера, рассчитанную на больше чем 40 человек... В руки совершенно случайно попала библиотека Netty
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38526356
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Blazkowicz
http://habrahabr.ru/post/136765/

Было: 15391945

И мне больше вот эта статья нравится
http://habrahabr.ru/post/136456/ ...Уже почти год мы пишем свою реализацию сервера, рассчитанную на больше чем 40 человек... В руки совершенно случайно попала библиотека Netty

Эту тоже хотел предложить :) -но потом - чисто Фон Нейманский метод : прочитайте мою статью №1- потом №2 :)

по поводу Было: 15391945 - так не бывает - нужно взять и переписать ,уверен времени займет меньше чем свой велосипед - особенно такого качества :(( и в нем искать ошибку ..

а то получается выстрел в ногу как тут http://habrahabr.ru/post/143074/ и зачем? идти по такому пути?
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38526424
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nio мне точно не подходит. По поводу 2000 потоков.... ерунда у меня их в пике нагрузки под 15к и все работает стабильно и быстро. И все это работает на ОЧЕНЬ скромном железе. В принципе вариант с отдельным потоком для удаления из БД мне подходит. Пул соединений тоже бы подошел, но я так и не нашел пример его реализации :(
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38526573
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GorloPavelNio мне точно не подходит. По поводу 2000 потоков.... ерунда у меня их в пике нагрузки под 15к и все работает стабильно и быстро. И все это работает на ОЧЕНЬ скромном железе. В принципе вариант с отдельным потоком для удаления из БД мне подходит. Пул соединений тоже бы подошел, но я так и не нашел пример его реализации :(

Как вариант - рассмотрите ( хотя бы для тестов ) jetty 9 - хороший сервер - на котором описать ваше решение - не более 50 -100 строк кода .

http://wiki.eclipse.org/Jetty/Tutorial/Embedding_Jetty

Код: java
1.
2.
3.
  Server server = new Server(8080);
        server.start();
        server.join();



Возьмите простой сервлет и к нему реализуйте простой WebListener - скорее всего вам будет достаточно
использовать методы sessionCreated и sessionDestroyed

Если я правильно понял вашу задачу.

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
@WebListener()
public class ServletListener implements ServletContextListener , HttpSessionListener , HttpSessionAttributeListener{
...
    @Override
    public void sessionCreated(HttpSessionEvent event) {
        System.out.println("---- ServletListener sessionCreated ----"); 
        System.out.println("session created: " + event.getSession().getId());
         if(event.getSession().isNew()){
          inc();
         }
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent event) {
        System.out.println("---- ServletListener sessionDestroyed ----"); 
        System.out.println("session destroyed: " + event.getSession().getId());
            dec();
    }



по поводу пула - посмотрите хотя бы c3p0

http://www.mchange.com/projects/c3p0/

http://www.mkyong.com/hibernate/how-to-configure-the-c3p0-connection-pool-in-hibernate/
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38526588
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Atum1,
Откуда там взяться сервлетам, если к автора нет HTTP?
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38526654
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvAtum1,
Откуда там взяться сервлетам, если к автора нет HTTP?

TCP протокол ? protobuf ?
https://code.google.com/p/protobuf/

все равно можно смотреть в сторону веб-сокетов и jetty


http://www.jansipke.nl/websocket-tutorial-with-java-server-jetty-and-javascript-client/
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38526694
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Atum1 ,
А protobuf здесь причем? :-) Ни HTTP, ни protobuf автору никак не поможет. В его ситуации это просто ненужные навороты сверху, которые не решать ни одной из его проблем. А какие-то вещи могут даже усугубить. Например, если у него сервер работает не по принципу request-response, а сам что-то шлет клиентам без запроса с их стороны.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38526742
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GorloPavelПул соединений тоже бы подошел, но я так и не нашел пример его реализации :(
не может быть). Где искал?
Тормозит ли бд при записи Поток - Соединение - Запись проверил?
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38526747
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjv Atum1 ,
А protobuf здесь причем? :-) Ни HTTP, ни protobuf автору никак не поможет. В его ситуации это просто ненужные навороты сверху, которые не решать ни одной из его проблем. А какие-то вещи могут даже усугубить. Например, если у него сервер работает не по принципу request-response, а сам что-то шлет клиентам без запроса с их стороны.

Какая то мифическая разработка - которая работает на нагрузке 15k? да еще и сама что то рассылает ?

авторерунда у меня их в пике нагрузки под 15к и все работает стабильно и быстро. И все это работает на ОЧЕНЬ скромном железе

сложно помочь когда не знаешь архитектуры ,что делает приложение и как оно должно работать ...
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38526897
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Atum1Какая то мифическая разработка - которая работает на нагрузке 15k? да еще и сама что то рассылает ?

Нет. Сервис аналог TeamViewer.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38527010
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GorloPavelAtum1Какая то мифическая разработка - которая работает на нагрузке 15k? да еще и сама что то рассылает ?

Нет. Сервис аналог TeamViewer.
субд какая, шифровальщик ты наш? )))
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38527152
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petro123GorloPavelпропущено...

Нет. Сервис аналог TeamViewer.
субд какая, шифровальщик ты наш? )))
MySQL. имеется в виду не 15к соединений к MySQL, а клиентских потоков.
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38527174
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GorloPavelMySQL. имеется в виду не 15к соединений к MySQL, а клиентских потоков.
разумеется). Зачем нам технические потоки.
У тебя проблема - иметь актуальную табличку в СУБД с актуальными реальными клиентами.
Напрашивается вывод - если приравнять сессию клиента к сессии СУБД, то сам коннект в БД и будет этой табличкой.
В оракле всегда можно посмотреть количество активный соединений (сессий).
При масштабировании и выходе твоего приложения на уровень гугла - вставляем пул для СУБД.
Подходит? Не вижу проблемы для 5-ой страницы топика. Переписывать свою ИС ты всё равно будешь)).
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38527273
chabapok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GorloPavelПросто реально нет времени объяснять как устроена и что у меня тут за система. Можете посмотреть по моим темам.

Ну чтож, спасибо, что хоть без регистрации и смс! Но все равно мы смотреть не будем. Просто реально нет времени обьяснять где там у вас ошибки, можете посмотреть по гуглу типичные ошибки.

ps. Судя по 5 станицам воды, у вас очень много времени
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38527589
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chabapokGorloPavelПросто реально нет времени объяснять как устроена и что у меня тут за система. Можете посмотреть по моим темам.

Ну чтож, спасибо, что хоть без регистрации и смс! Но все равно мы смотреть не будем. Просто реально нет времени обьяснять где там у вас ошибки, можете посмотреть по гуглу типичные ошибки.

ps. Судя по 5 станицам воды, у вас очень много времени

Ну это хотябы увлекательно нам дают кусочек кода а мы должны угадать где ошибка в огромной системе. )

Хоть какое то разнообразие .
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38527684
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ребята. Я уже писал ранее что проблемы больше нет. Ошибка найдена и исправлена. Я уже другой вопрос задал :)
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38527688
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GorloPavelРебята. Я уже писал ранее что проблемы больше нет. Ошибка найдена и исправлена. Я уже другой вопрос задал :)

Сладко поете:) Я конечно желаю чтобы у вас действительно все было тип-топ, но вероятность того что у вас все работает гаратированно правильно чуть больше нуля(без обид)
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38527722
Alex Kuznetsov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GorloPavelРебята. Я уже писал ранее что проблемы больше нет. Ошибка найдена и исправлена. Я уже другой вопрос задал :)Для других вопросов создаются отдельные темы... это правило хорошего тона...
...
Рейтинг: 0 / 0
Проблема с ConcurrentHashMap
    #38527798
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alex KuznetsovGorloPavelРебята. Я уже писал ранее что проблемы больше нет. Ошибка найдена и исправлена. Я уже другой вопрос задал :)Для других вопросов создаются отдельные темы... это правило хорошего тона...
Просто он в том же контексте.
...
Рейтинг: 0 / 0
99 сообщений из 99, показаны все 4 страниц
Форумы / Java [игнор отключен] [закрыт для гостей] / Проблема с ConcurrentHashMap
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]