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
() автор топика
Ответ на: Смотреть от 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
() автор топика
Ответ на: комментарий от stevejobs

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

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