Là một phần của ứng dụng Rails của tôi, tôi đã viết một nhà nhập khẩu nhỏ hút dữ liệu từ hệ thống LDAP của chúng tôi và nhồi nhét nó vào bảng Người dùng. Thật không may, mã liên quan đến LDAP rò rỉ một lượng lớn bộ nhớ trong khi lặp lại trên 32 nghìn người dùng của chúng tôi và tôi không thể tìm ra cách khắc phục sự cố.Rò rỉ bộ nhớ trong Ruby net/ldap Module
Sự cố có vẻ liên quan đến thư viện LDAP theo một cách nào đó, như khi tôi xóa các cuộc gọi đến công cụ LDAP, mức sử dụng bộ nhớ ổn định một cách độc đáo. Hơn nữa, các đối tượng được tăng sinh là Net :: BER :: BerIdentifiedString và Net :: BER :: BerIdentifiedArray, cả hai phần của thư viện LDAP.
Khi tôi chạy quá trình nhập, mức sử dụng bộ nhớ cuối cùng đạt mức cao hơn 1 GB. Tôi cần phải tìm một số cách để sửa mã của tôi nếu vấn đề là có, hoặc để làm việc xung quanh các vấn đề bộ nhớ LDAP nếu đó là nơi mà vấn đề nằm. (Hoặc nếu có một thư viện LDAP tốt hơn cho hàng nhập khẩu lớn cho Ruby, tôi mở cửa cho đó là tốt.)
Dưới đây là các bit thích hợp của mã của tôi chúng tôi:
require 'net/ldap'
require 'pp'
class User < ActiveRecord::Base
validates_presence_of :name, :login, :email
# This method is resonsible for populating the User table with the
# login, name, and email of anybody who might be using the system.
def self.import_all
# initialization stuff. set bind_dn, bind_pass, ldap_host, base_dn and filter
ldap = Net::LDAP.new
ldap.host = ldap_host
ldap.auth bind_dn, bind_pass
ldap.bind
begin
# Build the list
records = records_updated = new_records = 0
ldap.search(:base => base_dn, :filter => filter) do |entry|
name = entry.givenName.to_s.strip + " " + entry.sn.to_s.strip
login = entry.name.to_s.strip
email = login + "@txstate.edu"
user = User.find_or_initialize_by_login :name => name, :login => login, :email => email
if user.name != name
user.name = name
user.save
logger.info("Updated: " + email)
records_updated = records_updated + 1
elsif user.new_record?
user.save
new_records = new_records + 1
else
# update timestamp so that we can delete old records later
user.touch
end
records = records + 1
end
# delete records that haven't been updated for 7 days
records_deleted = User.destroy_all(["updated_at < ?", Date.today - 7 ]).size
logger.info("LDAP Import Complete: " + Time.now.to_s)
logger.info("Total Records Processed: " + records.to_s)
logger.info("New Records: " + new_records.to_s)
logger.info("Updated Records: " + records_updated.to_s)
logger.info("Deleted Records: " + records_deleted.to_s)
end
end
end
Cảm ơn trước sự giúp đỡ nào/con trỏ!
Nhân tiện, tôi cũng đã hỏi về điều này trong diễn đàn hỗ trợ net/ldap, nhưng không nhận được bất kỳ gợi ý hữu ích nào ở đó.
Bạn đang hủy liên kết chuỗi kết nối ở đâu? ldap.unbind? – Mike
Xin chào Mike, Các tài liệu không bao gồm một phương pháp không liên kết, cũng như không có mã mẫu nào, vì vậy tôi đã nhận ra rằng không cần thiết. (http://net-ldap.rubyforge.org/) Bên cạnh đó, người ta sẽ không unbind cho đến khi sau khi lặp đi lặp lại thông qua các hồ sơ nào, phải không? Rò rỉ bộ nhớ đang xảy ra trong quá trình lặp lại. Tôi đánh giá cao việc động não. –
Bộ dữ liệu được trả về từ tìm kiếm này bao nhiêu? Tôi giả sử dữ liệu có thể bị trùng lặp một hoặc hai lần. Phiên bản Ruby cũng có thể hữu ích. Hơn nữa, bạn có thể chia sẻ 'bộ lọc' bạn đang sử dụng không? Cuối cùng, không có khả năng xảy ra trường hợp, nhưng tôi đã thấy thư viện ldap trên các nền tảng khác thực hiện rất nhiều lần lặp trên các nhóm lồng nhau - tôi chỉ nhận ra khi nhìn vào một kết nối TCP ... – Brian