2010-08-19 93 views
7

Tôi đang sử dụng Spring MVC để xây dựng một lớp mỏng trên cơ sở dữ liệu SQL Server. Khi tôi bắt đầu thử nghiệm, có vẻ như nó không xử lý căng thẳng rất tốt :). Tôi đang sử dụng Apache Commons DBCP để xử lý kết nối tổng hợp và nguồn dữ liệu.Cách thích hợp để xử lý các kết nối JDBC với Spring và DBCP là gì?

Khi lần đầu tiên thử ~ 10-15 kết nối đồng thời, nó thường bị treo và tôi phải khởi động lại máy chủ (đối với dev tôi đang sử dụng Tomcat, nhưng cuối cùng tôi sẽ phải triển khai trên Weblogic).

Đây là những định nghĩa bean mùa xuân của tôi:

<bean id="dataSource" destroy-method="close" 
     class="org.apache.commons.dbcp.BasicDataSource"> 
    <property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/> 
    <property name="url" value="[...]"/> 
    <property name="username" value="[...]" /> 
    <property name="password" value="[...]" /> 
</bean> 

<bean id="partnerDAO" class="com.hp.gpl.JdbcPartnerDAO"> 
    <constructor-arg ref="dataSource"/> 
</bean> 

<!-- + other beans --> 

Và đây là cách tôi sử dụng chúng:

// in the DAO 
public JdbcPartnerDAO(DataSource dataSource) { 
    jdbcTemplate = new JdbcTemplate(dataSource); 
} 

// in the controller 
@Autowired 
private PartnerDAO partnerDAO; 

// in the controller method 
Collection<Partner> partners = partnerDAO.getPartners(...); 

Sau khi đọc xung quanh một chút, tôi thấy maxWait, maxActivemaxIdle thuộc tính cho số BasicDataSource (từ GenericObjectPool). Đây là vấn đề. Tôi không chắc làm thế nào tôi nên đặt chúng, hiệu quả khôn ngoan. Từ những gì tôi biết, mùa xuân nên quản lý các kết nối của tôi vì vậy tôi không cần phải lo lắng về việc phát hành chúng.

<bean id="dataSource" destroy-method="close" 
     class="org.apache.commons.dbcp.BasicDataSource"> 
    <property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/> 
    <property name="url" value="[...]"/> 
    <property name="username" value="[...]" /> 
    <property name="password" value="[...]" /> 
    <property name="maxWait" value="30" /> 
    <property name="maxIdle" value="-1" /> 
    <property name="maxActive" value="-1" /> 
</bean> 

Trước tiên, tôi đặt maxWait, để nó không treo và thay vào đó ném ngoại lệ khi không có kết nối nào từ hồ bơi. Thông báo ngoại lệ là:

Không thể nhận được kết nối JDBC; lồng nhau ngoại lệ là org.apache.commons.dbcp.SQLNestedException: Không thể có được một kết nối, lỗi hồ bơi Timeout chờ đợi đối tượng nhàn rỗi

Có một số truy vấn dài chạy, nhưng các ngoại lệ được ném không phụ thuộc vào độ phức tạp truy vấn.

Sau đó, tôi đặt maxActive và maxIdle để nó sẽ không ném ngoại lệ ngay từ đầu. Giá trị mặc định là 8 cho maxActivemaxIdle (Tôi không hiểu tại sao); nếu tôi đặt chúng thành -1 thì không có ngoại lệ nào bị ném và mọi thứ có vẻ như để hoạt động tốt.

Xem xét rằng ứng dụng này sẽ hỗ trợ một số lượng lớn các yêu cầu đồng thời là bạn có thể để các cài đặt này thành vô hạn không? Liệu Spring có thực sự quản lý các kết nối của tôi, xem xét các lỗi mà tôi nhận được không? Tôi có nên chuyển sang C3P0 xem xét nó đã chết?

+0

Nếu bạn nhận được bất kỳ ngoại lệ nào, việc đăng chồng ngăn xếp sẽ giúp xác định sự cố dễ dàng, Có bất kỳ truy vấn chạy dài nào mà bạn đang gặp sự cố không? –

+0

Tôi đã cập nhật bài đăng của mình với thông báo ngoại lệ và một số thông tin bổ sung. –

Trả lời

6

Như bạn đã biết, hồ bơi kết nối dbcp mặc định là 8 kết nối, vì vậy nếu bạn muốn chạy 9 truy vấn đồng thời, một trong số chúng sẽ bị chặn.Tôi đề nghị bạn kết nối với cơ sở dữ liệu của bạn và chạy exec sp_who2 sẽ hiển thị cho bạn những gì được kết nối và hoạt động và liệu có bất kỳ truy vấn nào đang bị chặn hay không. Sau đó, bạn có thể xác nhận xem sự cố có nằm trên db hay trong mã của bạn hay không. Miễn là bạn đang sử dụng các đối tượng JdbcTemplate của Spring, các kết nối của bạn sẽ được quản lý như bạn mong đợi, và nếu bạn muốn sử dụng DataSource thô, hãy đảm bảo bạn sử dụng DataSourceUtils để có được một kết nối. Một đề xuất khác - trước mùa xuân 3, không bao giờ sử dụng JdbcTemplate, dính vào SimpleJdbcTemplate, bạn vẫn có thể truy cập cùng một phương thức bằng cách sử dụng SimpleJdbcTemplate.getJdbcOperations(), nhưng bạn sẽ thấy mình viết mã đẹp hơn bằng Generics, và loại bỏ sự cần thiết để tạo các phiên bản JdbcTemplate/NamedParameterJdbcTemplate.

2

Hãy thay đổi phối cảnh.

nhưng ngoại lệ được ném không phụ thuộc vào độ phức tạp truy vấn

Nó có thể là do các bảng hoặc các bản ghi trong bảng, mà bạn đang truy vấn chống lại has been locked (bởi một số giao dịch tích cực khác) và do đó nó lần ra ngoài.

Thử chạy cùng một truy vấn từ máy khách SQLServer và nếu mất nhiều thời gian, bạn có thể chắc chắn rằng đó là bảng hoặc khóa bản ghi đang gây ra lỗi này.

+0

Tôi thấy điểm của bạn, nhưng vấn đề biến mất hoàn toàn khi tôi đặt tham số 'maxActive' và' maxIdle' của nguồn dữ liệu thành giá trị lớn (hoặc thành vô hạn). Điều này khiến tôi nghĩ rằng vấn đề là từ ConnectionPool, như thông báo ngoại lệ nói. –

8

Tham số DBCP maxWait phải được xác định bằng mili giây. 30 ms có giá trị rất thấp, hãy xem xét tăng giá trị này lên 30000 ms và thử lại.

Các vấn đề liên quan