LINUX.ORG.RU

Попытка экономии java.sql.Connection в jsp страницах.


0

1

Нужно выявить недостатки описанного тут решения.

Кратко и для Ъ

public interface Function<Y,  X> {
    Y exec(X x);
}

public final class SqlContext {
    private static final ThreadLocal<SqlContext> THREAD_LOCAL = new ThreadLocal<SqlContext>();
    private final Connection connection;

    private SqlContext() {
        //TODO initialize connection
        connection = null;
    }
    
    public static<T> T execute(Function<T, Connection> function) throws Throwable {
        SqlContext sqlContext = THREAD_LOCAL.get();
        boolean weOpened = (sqlContext == null);
        if(weOpened) {
            sqlContext = new SqlContext();
            THREAD_LOCAL.set(sqlContext);
        }
        try {
            T result = function.exec(sqlContext.connection);
            sqlContext.commit();
            return result;
        } catch(Throwable t) {
            sqlContext.rollback();
            throw t;
        } finally {
            if(weOpened) {
                THREAD_LOCAL.remove();
                sqlContext.close();
            }
        }
    }
    // где то тут реализация commit rollback и close

}

Цель сабжа - использовать только одно sql соединение на всю страницу не передавая его явно в бины (которых на странице может быть десяток и они могут друг друга вызывать) и гарантированно закрывая сие по окончании рендеринга страницы.


это либо очень сложно, либо на лоре не осталось спецов

kifer ()

Смотреть

JDBC Connection Pool

iZEN ★★★★★ ()
Ответ на: Смотреть от iZEN

это сложно детка, да, читать топик даже не пытайся

kifer ()

забудьте уже про JSP и JDBC, есть же jsf и jpa. Но если очень уж хочется.

Я могу сказать, что минусом является как минимум то, что в томкате коннекшенов будет столько же, сколько «http-8080-worker-...» потоков, что плохо, потому что например, при стресс тесте в 1000 одновременных коннешенов, таких потоков будет около 500, соответственно, сколько же и коннешенов, в то время как при использовании пула понадобилось бы не более 20-30 коннекшенов. Данные о количестве потоков при стресс тесте и количестве соединений в пуле взяты из реального опыта одного проекта.

JFreeM ★★★☆ ()
Ответ на: комментарий от JFreeM

>как минимум то, что в томкате коннекшенов будет столько же, сколько «http-8080-worker-...» потоков

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

в то время как при использовании пула понадобилось бы не более 20-30 коннекшенов.

Пул никто не запрещает использовать и сейчас.

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

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

забудьте уже про JSP и JDBC, есть же jsf и jpa.

узнай уже про REST и нагрузки когда jpa требует парочку лишних среверов

kifer ()

Идея нормальная, для не сильно нагруженного проекта пойдет, только вот реализация так себе. Вот набросал на коленке, запускать не пробовал:

public class ConnectionContext {
	
	public static interface JdbcAction<T> {
		T perform(Connection conn) throws Exception;
	}
	
	private final static ThreadLocal<Connection> CONNECTION = new ThreadLocal<Connection>();
	
	public static <T> T doInContext(JdbcAction<T> action) throws Throwable {
		Connection current = CONNECTION.get();
		if (valid(current)) {
			// транзакция уже выполняется, просто выполняем экшн
			return action.perform(current);
		} else {
			current = open();
			CONNECTION.set(current);
		}
		try {
			T result = action.perform(current);
			current.commit();
			return result;
		} catch (Throwable e) {
			current.rollback();
			throw e;
		} finally {
			CONNECTION.remove();
			try {
				current.close();
			} catch (Exception ignored) {}
		}
	}
	
	private static boolean valid(Connection conn) {
		if (conn == null)
			return false;
		try {
			if (conn.isClosed())
				return false;
		} catch (SQLException e) {
			return false;
		}
		return true;
	}
	
	private static Connection open() {
		// вот тут нужно получить в соответсвии с настройками
		// если база не доступна, то нужно пытаться подключитьяс через какой-то промержуток времени
		return null;
	}
}

А лучше взять готовый пул и не заниматься фигней.

dizza ★★★★★ ()
Ответ на: комментарий от JFreeM

забудьте уже про JSP и JDBC, есть же jsf и jpa.

Кому-то оно подходит, кому-то нет. Что за детсад.

dizza ★★★★★ ()
Ответ на: комментарий от dizza

Если хочется несколько коннекшнов в треде, то можно ввести параметр в метод doInContext - имя базы.

dizza ★★★★★ ()

не занимайтесь ерундой. используйте jsp как view не пытайтесь в ней вызывать jdbc.
кстати, где-нибудь в спеках на j2ee есть утверждения, что:
1) обработка jsp гарантирована в одном потоке, т.е. что одна jsp-ха в процессе не перейдет с потока на поток.
2) в одном потоке не может быть одновременно двух jsp.

maloi ★★★★★ ()
Ответ на: комментарий от maloi

Если ты бы читал спецификацию сервлетов то глупостей бы не спрашивал. А если бы читал топки то не предлагал бы того что и так используется «используйте jsp как view»

kifer ()
Ответ на: комментарий от dizza

я же говорил что эту фигню стоит использовать с пулом.

У меня к тебе два вопроса - почему «для не сильно нагруженного»

и в чем разница от моего варианта кроме [code]try { if (conn.isClosed()) return false; } catch (SQLException e) { return false; } [/code] это то верный код но я его не указывал из предположения что такая ситуация возможно только если клиент решит закрыть соединение в action.perform (а из логики сего это ошибка и обрабатывать ее имхо над иначе, но это врено обрабатывать надо)

kifer ()
Ответ на: комментарий от kifer

человек дело говорит. Выкинь всю логику из JSP и используй их только как шаблоны. Все бины - выкинуть, любые переходы делать только по юзкейзам из контроллера, внешние данные разрешать получать только через контроллер в виде скаляров и POJO. А конкретные данные пусть рассчитывает движок, который вообще никак на страницы не завязан, и у него может быть всего один пул, зато на всех сразу. Круто помогает выкинуть JSP и перейти на какой-нибудь Velocity, где делать хрень технически невозможно.

ну да, у тебя поди 100500 бинов, которые в классическом PHP-стайл работают на постбэках, и слезть с них уже не получится ;) Так что совет сделать нормальную архитектуру воспринимай как тонкую иронию и искрометный юмор ;)

stevejobs ★★★★☆ ()
Ответ на: комментарий от stevejobs

>человек дело говорит. Выкинь всю логику из JSP и используй их только как шаблоны.

Человек бредит, а ты вторишь ему, он тупо не осилил прочитать топки и понять что в JSP только логика отображения - типа [code] <c:forEach items=«thin.items» var=«items»> <div class='row'>${items}</div> </c:forEach> [/code] И все, детко.

Все бины - выкинуть ... POJO

у меня для тебя новости... плохие. Дело в том, что применение MVC несет больше вреда чем пользы. У тебя будет на каждую страницу строго специфический класс контроллер, строго специфически класс модели, и современем, может придет осознание того что этот паттерн работает только сам для себя пожиря кучу кода и ресурсов ради только идеи.

Круто помогает выкинуть JSP и перейти на какой-нибудь Velocity, где делать хрень технически невозможно.

Как и вообще что либо делать, плавали, знаем.

ну да, у тебя поди 100500 бинов, которые в классическом PHP-стайл работают на постбэках

телпаты таки телепаты, они всегда пытаются решать чужие проблемы. Ты не догадываешься что ее давно нету?

kifer ()
Ответ на: комментарий от kifer

наверное, в том, что ты делаешь, совсем нет автоматических тестов. И не практикуется test driven development. Иначе преимущества чистого MVC имели бы большое значение.

stevejobs ★★★★☆ ()
Ответ на: комментарий от stevejobs

Ты опять оправдываешь парадигму - MVC, другой парадигмой - экстремальным программированием (тестирование оттуда растет). Но бины можно тестировать даже проще чем MVC, ибо тестируется только логика получения данных, а не аццкая моемесь модели и контроллера (при том что тестирование представления-jsp тот еще атас )

kifer ()
Ответ на: комментарий от kifer

Но бины можно тестировать даже проще чем MVC, ибо тестируется только логика получения данных, а не аццкая моемесь модели и контроллера
ибо тестируется только логика получения данных

из этого напрашиваются вопросы.

1) почему тестируется _только_ логика получения данных? Куда девалось всё остальное, например, просто логика? :)

2) для того, чтобы бин получил данные в «честном» формате, нужно сформировать ServletRequest, и дать бину писать Response. А Request и Response - часть реализации конкретного сервлет-контейнера. То есть нам нужно реализовать симулятор контейнера, как самый минимум request и response с возможностью взаимодйествия (ты знаешь какую-нибудь свободную универсальную реализацию?), или вообще запускать на живом контейнере (здравствуй Jakarta Cactus и Selenium. Теперь наворачиваем на это возможность того что бинов «на странице может быть десяток и они могут друг друга вызывать», т.е. еще и мокнутые бины со всеми комбинациями их взаимодействия. Теперь добавляем к этому то, что в JSP какой-нибудь веб-дизайнер все же может подмешать логику, и возможно нужно заморочиться над симуляцией еще и JSP.

Чото как-то страшно всё это звучит. И особенно если я действительно использую (и оправдываюсь :) TDD/XP, эти тесты нужно написать _до_ реализации конкретного кода, до написания бинов и JSP.

Я когда-то немножко писал сайтики на основе бинов+жсп, и указанная выше проблема съедала моск на 120%, приводя в ужас и гнев. Возможно я просто писал их достаточно недолго, чтобы понять как их правильно варить...

(при том что тестирование представления-jsp тот еще атас )

вот поэтому jsp не нужно ;)

stevejobs ★★★★☆ ()
Ответ на: комментарий от stevejobs

>1) почему тестируется _только_ логика получения данных? Куда девалось всё остальное, например, просто логика? :)

- не могу понять что это но видимо связанно с алкоголем.

- Хорошо, доктор, я приду когда вы протрезвеете.

2) для того, чтобы бин получил данные в «честном» формате, нужно сформировать ServletRequest, и дать бину писать Response.

У тебя какието укуренные бины, наверное их в детстве мама роняла. Я тебе расскажу IRL в java существует только два вида бинов: JavaBeans (это POJO написанные по некоторым правилам), и EJB, это хирня тебе ненужная. Ни один из этих видов не требует ServletRequest, на чем твой диагноз можно и определить.

kifer ()
Ответ на: комментарий от kifer

а ничего что у бинам, запускающимся из JSP можно таки передать request и response, чем все активно пользуются?

stevejobs ★★★★☆ ()
Ответ на: комментарий от stevejobs

Давай не будем о твоих знакомых извращенцах под коими ты понимаешь слово «все».

kifer ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.