데이터베이스를 비동기식으로 호출하는 방법이 있는지 궁금합니다.
예를 들어, 처리하는 데 시간이 오래 걸리는 큰 요청이 있다고 가정합니다. 요청을 보내고 요청이 값을 반환 할 때 알림을 수신하려고합니다 (리스너 / 콜백 또는 기타를 전달하여). 데이터베이스가 응답하기를 기다리는 것을 차단하고 싶지 않습니다.
스레드 풀을 사용하는 것이 확장되지 않기 때문에 솔루션이라고 생각하지 않습니다. 동시 요청이 많은 경우에는 많은 수의 스레드가 생성됩니다.
우리는 네트워크 서버에서 이러한 종류의 문제에 직면하고 있으며 연결 당 하나의 스레드를 피하기 위해 select / poll / epoll 시스템 호출을 사용하여 솔루션을 찾았습니다. 데이터베이스 요청과 비슷한 기능을 갖는 방법이 궁금합니다.
참고 : FixedThreadPool을 사용하는 것이 좋은 해결 방법 일 수 있음을 알고 있지만 아무도 실제로 여분의 스레드를 사용하지 않고 비동기 시스템을 개발하지 않은 것에 놀랐습니다.
** 업데이트 **
실제 실제 솔루션이 없기 때문에 finagle-mysql 라이브러리 (finagle의 일부)를 직접 작성하기로 결정했습니다 . 기본적으로 mysql 요청 / 응답을 디코딩 / 디코딩하고 Finagle / Netty를 사용합니다. 많은 수의 연결로도 확장 성이 뛰어납니다.
답변
Actors, executor 또는 다른 어떤 것에서 JDBC 호출을 래핑하는 제안 된 접근 방식이 어떻게 도움이 될 수 있는지 이해하지 못합니다.
분명히 기본적인 문제는 JDBC 작업이 소켓 IO에서 차단된다는 것입니다. 이 작업을 수행하면 스토리 종료시 스레드 실행이 차단됩니다. 어떤 래핑 프레임 워크를 사용하든간에 동시 요청 당 하나의 스레드가 사용 중 / 차단 상태로 유지됩니다.
기본 데이터베이스 드라이버 (MySql?)가 소켓 생성을 가로 채는 수단을 제공하는 경우 (SocketFactory 참조) JDBC API 위에 비동기 이벤트 기반 데이터베이스 계층을 구축하는 것이 가능할 것이라고 생각하지만 우리는 이벤트 주도 파사드 뒤의 전체 JDBC는 해당 파사드가 (이벤트 주도 후) JDBC처럼 보이지 않습니다. 데이터베이스 처리는 호출자와 다른 스레드에서 비동기 적으로 수행되므로 스레드 선호도에 의존하지 않는 트랜잭션 관리자를 빌드하는 방법을 연구해야합니다.
내가 언급 한 접근법과 같은 것은 단일 백그라운드 스레드조차도 동시 JDBC exec를로드 할 수있게합니다. 실제로 여러 코어를 사용하기 위해 스레드 풀을 실행할 수 있습니다.
(물론 나는 원래 질문의 논리에 대해서는 언급하지 않고 소켓 IO를 차단하는 시나리오에서 동시성이 선택기 패턴을 사용하지 않고도 가능하다는 암시 적 응답에 대해서는 언급하지 않습니다. 일반적인 JDBC 동시성을 해결하고 넣는 것이 더 간단합니다. 올바른 크기의 연결 풀에서).
MySql이 아마도 내가 제안하는 라인을 따라 뭔가를하는 것처럼 보입니다 —
http://code.google.com/p/async-mysql-connector/wiki/UsageExample
답변
JDBC를 통해 데이터베이스 를 비동기식으로 호출하는 것은 불가능 하지만 액터 를 사용하여 JDBC 를 비동기식으로 호출 할 수 있습니다 (예 : 액터 가 JDBC 를 통해 DB를 호출하고 호출이 끝나면 제 3 자에게 메시지를 보냅니다). 또는 파이프 라인 선물 (약속) 과 함께 CPS 를 선호 하는 경우 ( Scalaz Promises 구현 )
스레드 풀을 사용하는 것이 확장되지 않기 때문에 솔루션이라고 생각하지 않습니다. 동시 요청이 많은 경우에는 많은 수의 스레드가 생성됩니다.
스칼라 액터는 기본적으로 이벤트 기반 (스레드 기반이 아님)입니다. 연속 스케줄링을 통해 표준 JVM 설정에서 수백만 액터를 생성 할 수 있습니다.
Java를 대상으로하는 경우 Akka Framework 는 Java 및 Scala 모두에 적합한 API를 가진 Actor 모델 구현입니다.
그 외에도 JDBC의 동기 특성은 나에게 완벽합니다. 데이터베이스 세션 비용은 Java 스레드가 차단되기 전 (또는 백그라운드에서) 응답을 기다리는 것보다 훨씬 높습니다. 실행기 서비스의 기능 (또는 Actor / fork-join / promise 동시성 프레임 워크 래핑)이 충분하지 않아 쿼리가 충분하지 않은 경우 (그리고 너무 많은 스레드를 소비하는 경우) 먼저 데이터베이스로드. 일반적으로 데이터베이스의 응답은 매우 빠르게 되돌아오고 고정 스레드 풀로 백업 된 실행기 서비스는 충분한 솔루션입니다. 오래 실행되는 쿼리가 너무 많으면 야간에 데이터를 다시 계산하는 것과 같은 선행 처리 (사전 처리)를 고려해야합니다.
답변
아마도 IMHO 확장 성이 뛰어난 JMS 비동기 메시징 시스템을 사용할 수있을 것입니다.
-
가입자가 메시지를 수락하고 SQL 프로세스를 실행할 큐에 메시지를 보냅니다. 기본 프로세스는 계속 실행되어 새 요청을 수락 또는 전송합니다.
-
SQL 프로세스가 끝나면 반대 방식으로 실행할 수 있습니다. 프로세스 결과와 함께 ResponseQueue에 메시지를 보내면 클라이언트 측의 리스너가이를 승인하고 콜백 코드를 실행합니다.
답변
JDBC에는 직접적인 지원이 없지만 Java 5의 MDB, MDB와 같은 여러 옵션이 있습니다.
“나는 스레드 풀을 사용하는 것이 확장되지 않기 때문에 솔루션이라고 생각하지 않는다. 동시 요청이 많은 경우에는 매우 많은 수의 스레드가 생성 될 것이다.”
제한된 스레드 풀이 확장되지 않는 이유가 궁금합니다. 요청마다 스레드를 생성하는 것은 요청 당 스레드가 아닌 풀입니다. 나는 이것을 막대한로드 웹 애플리케이션에서 꽤 오랫동안 사용 해 왔으며 지금까지 아무런 문제도 보지 못했습니다.
답변
답변
다른 답변에서 언급했듯이 JDBC API는 본질적으로 비동기가 아닙니다.
그러나 작업의 하위 집합과 다른 API를 사용할 수 있다면 솔루션이 있습니다. 한 가지 예는 MySQL 및 PostgreSQL에서 작동하는 https://github.com/jasync-sql/jasync-sql 입니다.
답변
Ajdbc 프로젝트가 http://code.google.com/p/adbcj/ 이 문제에 답하는 것 같습니다
현재 mysql 및 postgresql에 대해 기본적으로 2 개의 실험용 비동기 드라이버가 있습니다.