Mở một kết nối cơ sở dữ liệu là một hoạt động tốn kém và việc gộp kết nối được sử dụng để giữ cho các kết nối cơ sở dữ liệu luôn mở để chúng có thể được sử dụng lại. Điều này tránh phải mở nhiều phiên mạng, xác thực và kiểm tra ủy quyền. Tính năng gộp sẽ giữ cho các kết nối luôn hoạt động để khi kết nối được yêu cầu sau đó, một trong những kết nối đang hoạt động sẽ được sử dụng thay vì phải tạo một kết nối từ đầu.
Tổng hợp kết nối
Tổng hợp kết nối đã trở thành một trong những phương pháp phổ biến nhất để xử lý các kết nối cơ sở dữ liệu trước một yêu cầu truy vấn. Chúng tôi thường nghĩ rằng kết nối với cơ sở dữ liệu là nhanh nhưng không phải vậy, đặc biệt là khi một số lượng lớn khách hàng đang kết nối. Nếu không có kết nối tổng hợp, một yêu cầu sẽ mất tới 35-50 mili giây để kết nối nhưng 1-2 mili giây nếu sử dụng tổng hợp kết nối. Tổng hợp kết nối do đó phân bổ trước các kết nối cơ sở dữ liệu và sau đó tái chế chúng khi các máy khách mới đang kết nối
Lý do tổng hợp kết nối
- Để tránh sự cố máy chủ của bạn. Máy chủ PostgreSQL được giới hạn ở một số máy khách mà chúng xử lý tại một thời điểm tùy thuộc vào tham số bộ nhớ. Nếu con số này bị vượt qua, thì bạn sẽ bị treo máy chủ. Với tính năng tổng hợp kết nối, máy khách sử dụng một số lượng kết nối đã định.
- Tạo điều kiện thuận lợi cho việc xử lý truy vấn. Thông thường, các yêu cầu cơ sở dữ liệu được thực hiện theo cách nối tiếp với tiêu chí nhập trước xuất trước. Với một tập hợp lớn khách hàng, điều này sẽ mất nhiều thời gian để đạt được quá trình này. Do đó, cách tiếp cận nên là tạo một kết nối duy nhất với các yêu cầu liên kết có thể được thực hiện đồng thời thay vì từng yêu cầu một.
- Cải thiện bảo mật. Thông thường, một kết nối bao gồm một cú bắt tay có thể mất trung bình 25-35 ms qua đó SSL được thiết lập, mật khẩu được kiểm tra và chia sẻ thông tin cấu hình. Tất cả công việc này đối với mỗi người dùng được kết nối sẽ dẫn đến việc sử dụng nhiều bộ nhớ. Tuy nhiên, với tính năng gộp kết nối, số lượng kết nối sẽ giảm đi, do đó tiết kiệm trên bộ nhớ.
Các kiểu tổng hợp kết nối
Về cơ bản có hai loại kết nối chung, tuy nhiên, có một loại thứ ba hoạt động giống như một chiến lược tổng hợp kết nối được gọi là kết nối liên tục.
Tổng hợp kết nối liên tục
Cách tiếp cận này dự định giữ cho một kết nối ban đầu hoạt động kể từ thời điểm nó được khởi tạo. Nó không chứa đầy đủ các tính năng tổng hợp kết nối nhưng đủ tốt để cung cấp một số kết nối liên tục. Nó khá hữu ích cho một tập hợp nhỏ các kết nối máy khách có chi phí có thể nằm trong khoảng 25-50 mili giây. Một hạn chế với cách tiếp cận này là nó bị giới hạn ở một số kết nối đến db với thông thường một kết nối duy nhất cho mỗi mục nhập vào máy chủ.
Tổng hợp kết nối khung
Nhóm kết nối khung xảy ra ở cấp ứng dụng, theo đó, bất cứ khi nào tập lệnh máy chủ của bạn được khởi động, nhóm kết nối sẽ được thiết lập để xử lý các yêu cầu truy vấn sẽ đến sau này.
Tổng hợp kết nối độc lập
Đối với mọi kết nối với cơ sở dữ liệu, bộ nhớ trên không từ 5 đến 10 MB được sử dụng hết để phục vụ cho yêu cầu truy vấn. Điều này không hoàn toàn tốt cho một số lượng lớn các kết nối. Việc sử dụng tổng hợp kết nối khung có thể bị giới hạn bởi số lượng kết nối này vì nó có thể gặp phải việc sử dụng kích thước bộ nhớ lớn. Do đó, chúng tôi chọn sử dụng gộp kết nối Độc lập được định cấu hình phù hợp với các phiên, câu lệnh và giao dịch của Postgres. Lợi thế cốt lõi liên quan đến cách tiếp cận này là:chi phí chung tối thiểu khoảng 2kb cho mọi kết nối.
Khi bạn tạo một lớp tổng hợp kết nối, lớp đó phải đáp ứng các yếu tố sau để tăng hiệu suất cơ sở dữ liệu:
- Phân bổ trước các kết nối
- Giám sát các kết nối khả dụng
- Chỉ định các kết nối mới
- Chờ kết nối khả dụng
- Đóng kết nối
Định vị trước các kết nối
Đảm bảo trước nhiều kết nối hơn sẽ tạo điều kiện thuận lợi cho việc xử lý các yêu cầu tại thời điểm ứng dụng đã được khởi động. Ví dụ:nếu máy chủ của bạn được phát triển bằng Java, bạn có thể sử dụng vectơ để lưu trữ các kết nối không hoạt động có sẵn bằng cách sử dụng mã bên dưới.
availableConnections = new Vector(connections);
busyConnections = new Vector();
for(int i=0; i<connections; i++) {
availableConnections.addElement(makeNewConnection());
}
Giám sát các kết nối khả dụng
Lớp sẽ có thể kiểm tra bất kỳ kết nối không hoạt động nào trong danh sách các kết nối bận và trả lại nó. Điều này về cơ bản được thực hiện để sử dụng lại kết nối hoặc đóng các kết nối không được sử dụng. Đôi khi kết nối hết thời gian do đó trong khi trả lại kết nối, điều khá quan trọng là phải kiểm tra xem nó có còn mở hay không. Nếu không, bạn cần phải hủy kết nối này và lặp lại quy trình. Khi kết nối bị hủy, một khe cắm sẽ được mở ra, có thể được sử dụng để xử lý kết nối mới khi đã đạt đến giới hạn. Điều này có thể đạt được với
public synchronized Connection getConnection() throws SQLException {
if (!availableConnections.isEmpty()) { Connection existingConnection =
(Connection)availableConnections.lastElement(); int lastIndex = availableConnections.size() - 1; availableConnections.removeElementAt(lastIndex); if (existingConnection.isClosed()) {
notifyAll(); // Freed up a spot for anybody waiting.
return(getConnection()); // Repeat process. } else {
busyConnections.addElement(existingConnection);
return(existingConnection); }
} }
Chỉ định một kết nối mới
Bạn sẽ có thể bắt đầu một chuỗi nền để chỉ định một kết nối mới nếu không có chế độ rảnh và nếu sắp đạt đến giới hạn kết nối.
if ((totalConnections() < maxConnections) && !connectionPending) { // Pending = connecting in bg
makeBackgroundConnection(); }
try {
wait(); // Give up lock and suspend self.
} catch(InterruptedException ie) {} return(getConnection()); // Try again.
Đang đợi kết nối mới
Khi không có kết nối rỗi và đã đạt đến giới hạn kết nối, cấu hình sẽ có thể đợi kết nối mới khả dụng mà không liên tục gộp chung. Chúng tôi có thể làm như vậy bằng cách sử dụng phương pháp chờ cung cấp khóa đồng bộ hóa chuỗi và tạm dừng chuỗi cho đến khi nhận được thông báo.
try {
wait();
} catch(InterruptedException ie) {}
return(getConnection());
Để có đạo đức ứng dụng tốt, máy khách không nên đợi kết nối trong thời gian thực thay vì bạn sẽ đưa ra một ngoại lệ khi không có kết nối với đoạn mã dưới đây:
throw new SQLException("Connection limit reached");
Đóng kết nối
Khi các kết nối được thu thập rác, bạn nên đóng chúng thay vì làm điều đó một cách rõ ràng. Tuy nhiên, nếu bạn muốn một cách tiếp cận rõ ràng để đóng một kết nối thì bạn có thể sử dụng:
public synchronized void closeAllConnections() {
// The closeConnections method loops down Vector, calling // close and ignoring any exceptions thrown. closeConnections(availableConnections); availableConnections = new Vector(); closeConnections(busyConnections);
busyConnections = new Vector();
}
Kết luận
Tổng hợp kết nối cho PostgreSQL giúp chúng tôi giảm số lượng tài nguyên cần thiết để kết nối với cơ sở dữ liệu và cải thiện tốc độ kết nối với cơ sở dữ liệu. Điều này đạt được bằng cách gộp các kết nối đến DB, duy trì các kết nối này và do đó giảm số lượng kết nối phải được mở.