一点背景
多年来,我一直在使用Apartment gem来运行多租户应用程序。现在最近需要将数据库扩展到单独的主机上,数据库服务器根本无法跟上(读取和写入都变得太多) - 是的,我将硬件扩展到最大(专用硬件、64 核、raid 10 中的 12 个 Nvm-e 驱动器、384Gb ram 等)。
我正在考虑按租户执行此操作(1 个租户 = 1 个数据库连接配置/池),因为这将是一种“简单”且有效的方法,可以在number-of-tenants不进行大量应用程序代码更改的情况下获得更多的容量。
现在,我正在运行 rails 4.2 atm.,很快升级到 5.2。我可以看到 rails 6 添加了对每个模型连接定义的支持,但这并不是我真正需要的,因为我为我的 20 个租户中的每个租户都有一个完全镜像的数据库模式。通常我会根据请求(在中间件中)或每个后台作业(sidekiq 中间件)切换“数据库”,但是目前这很简单,并且可以在 Apartment gem 中处理,因为它只是search_path在 Postgresql 中设置了并且并没有真正改变实际连接。当切换到每租户托管策略时,我需要根据请求切换整个连接。
问题:
ActiveRecord::Base.establish_connection(config)每个请求/后台工作 - 但是,正如我所理解的,这会触发一个全新的数据库连接握手,并在 Rails 中生成一个新的数据库池 - 对吗?我想这将是性能自杀,在对我的应用程序的每个请求上都产生这种开销。我有两个不同的图像:
和
正如您所看到的,从人类的角度来看,两者显然是“相同的”。现在我想以编程方式检测它们是否相同。我一直在通过 ruby gem 使用图像魔法,rmagick如下所示:
img1 = Magick::Image.from_blob(File.read("image_1.jpeg")).first
img2 = Magick::Image.from_blob(File.read("image_2.jpeg")).first
if img1.difference(img2).first < 4000.0 # I have found this to be a good threshold, but does not work for cropped images
puts "they are the same!!!"
end
Run Code Online (Sandbox Code Playgroud)
虽然这适用于具有相同比例/裁剪的图像,但当它们的裁剪略有不同并且已调整为相同宽度时,这并不理想。
有没有办法对不同裁剪的图像进行处理?我对一个解决方案感兴趣,我可以这样说:一个图像包含在另一个图像中,并覆盖了大约 90% 的区域。
附注。如果有帮助,我可以获得更高分辨率的图像(例如双倍)
在进行大数据迁移(几十万行)时,我遇到了巨大的时间和计算能力挑战.我正在开发一种处理rails中大量数据的服务.随着我们对设计的关注越来越多,我们的模型也在不断变化.这导致我们的数据库(Postgres 9.0数据库)进行了大量迁移.这些迁移通常还包括对数据本身的某种迁移.昨天我们发现我们需要将模型上的"text"属性移动到一个单独的模型中,这样该属性不再仅仅是模型上的属性,而是一对多关系.
我的迁移看起来有点像这样:
def self.up
create_table :car_descriptions do |t|
t.integer :car_id
t.text :description
t.timestamps
end
Car.find_each do |car|
if car.description.present?
car.descriptions.build :description => car.description
end
car.save
end
remove_column :cars, :description
end
Run Code Online (Sandbox Code Playgroud)
现在的问题是,这种运行速度非常慢,更糟糕的是,如果我设置一个计数器并打印出进度,我可以看到迁移的运行速度越来越慢.在我的活动监视器中,我可以看到ruby进程占用了越来越多的内存.
所以我的问题是 - 有更好的方法来进行这样的大数据迁移吗?
我有一个非常大的XML文件(300mb),格式如下:
<data>
<point>
<id><![CDATA[1371308]]></id>
<time><![CDATA[15:36]]></time>
</point>
<point>
<id><![CDATA[1371308]]></id>
<time><![CDATA[15:36]]></time>
</point>
<point>
<id><![CDATA[1371308]]></id>
<time><![CDATA[15:36]]></time>
</point>
</data>
Run Code Online (Sandbox Code Playgroud)
现在我需要读取它并遍历point节点为每个节点做一些事情.目前我正在和Nokogiri这样做:
require 'nokogiri'
xmlfeed = Nokogiri::XML(open("large_file.xml"))
xmlfeed.xpath("./data/point").each do |item|
save_id(item.xpath("./id").text)
end
Run Code Online (Sandbox Code Playgroud)
然而,这并不是非常有效,因为它解析了整个拥抱的一切,因此创造了巨大的内存占用(几GB).
有没有办法在块中执行此操作?如果我没弄错的话可能会被称为流式传输?
编辑
使用nokogiris sax解析器的建议答案可能没问题,但是当每个节点中有多个节点point需要从中提取内容并以不同方式处理时,它会变得非常混乱.我宁愿选择point一次访问一个,处理它,然后继续下一个"忘记"前一个,而不是返回大量的条目供以后处理.
我想在我的 Google Analytics 中检查我的用户群中有多大比例使用华为设备,这些设备不再使用谷歌服务,而是使用应用程序库等。
我想知道我是否可以在用户代理等中查找特定的操作系统版本?
user-agent google-analytics huawei-mobile-services huawei-developers
我正在尝试做这样的事情:
cache "api/v1/cars_index/#{I18n.locale}/car/#{car.cache_key}" do
attributes :id, :brand, :model_name, :fuel, :km, :year, :price
node(:color) { |car| car.color.present? ? car.color : '' }
end
Run Code Online (Sandbox Code Playgroud) 问题我有一个运行几百个sidekiq后台进程的rails应用程序.它们都连接到一个PostgreSQL数据库,它对提供250个连接并不十分满意 - 它可以,但如果所有sidekiq进程意外地向db发送查询,它就会崩溃.
选项1我一直在考虑在数据库前添加pgBouncer,但我目前无法使用它的事务模式,因为我高度依赖于search_path在每个作业处理的开头设置以确定哪个"国家"(PostgreSQL模式)工作(公寓宝石).在这种情况下,我将不得不使用基于会话的连接池模式.然而,据我所知,这会要求我在每次作业处理后断开连接,将连接释放回池中,这样做性能真的很高,不是吗?我错过了什么吗?
选项2使用基于应用程序层的连接池也是一个选项,但是我不确定我如何能够使用sidekiq为PostgreSQL做到这一点?
选项3我没有想到的东西?
postgresql connection-pooling pgbouncer sidekiq apartment-gem
我有一些像这样插入的项目:
PutItem:
"TableName": "pets",
"Item": {
"petName": {
"S": "Cat"
},
"hairColor": {
"S": "gray"
},
"nickName": {
"S": "Kitty"
}
}
Run Code Online (Sandbox Code Playgroud)
然而,有时候,pets没有nickname.我对dynamoDB很新,我可以看到,我可以通过两种方式处理这个问题(至少):
1)
"TableName": "pets",
"Item": {
"petName": {
"S": "Cat"
},
"hairColor": {
"S": "gray"
},
"nickName": {
"NULL": "true"
}
}
Run Code Online (Sandbox Code Playgroud)
2)
"TableName": "pets",
"Item": {
"petName": {
"S": "Cat"
},
"hairColor": {
"S": "gray"
}
}
Run Code Online (Sandbox Code Playgroud)
这会给我带来什么不同(例如,之后访问数据时)?什么是最佳做法?
我在postgresql中有一个包含一些汽车+1000000记录的表:
+----+--------+------+---------+-----------+-------------+------------+------------+
| id | price | year | mileage | fuel_type | body_type | brand | model |
+----+--------+------+---------+-----------+-------------+------------+------------+
| 1 | 4894 | 2011 | 121842 | "Benzin" | "Sedan" | "Toyota" | "Yaris" |
| 2 | 4989 | 2012 | 33901 | "Benzin" | "Hatchback" | "Renault" | "Twingo" |
| 3 | 4990 | 2013 | 55105 | "Benzin" | "Hatchback" | "Renault" | "Twingo" |
| 3 | 5290 | 2013 | 20967 | …Run Code Online (Sandbox Code Playgroud) 我有一个运行memcached的专用128GB ram服务器.4个Web服务器连接到那个.它们总共发送大约20k包/秒.
最近我决定改变从web服务器到memcached服务器的连接,从持久的SSH隧道到使用Tinc(为了简化设置和灵活性,只要我需要它们在新端口上进行通信).
这种变化导致网络往返的开销显着增加(见图表).然而,我注意到,使用Tinc支持SSH隧道的网络开销要小得多(甚至比之前的SSH隧道还要快!),当我用它在服务器之间进行通信时(例如我的Postgresql数据库服务器),吞吐量低很多<每秒10k数据包.我试图在更多服务器之间分配memcached负载,突然来自tinc/network的开销显着下降.
现在,我不明白为什么tinc网络开销会随着吞吐量的增加而急剧增加?这就像我打了一个瓶颈(并且它肯定不是CPU,因为Newrelic报告<tinc过程的使用率<0.5%).有什么东西我可以在Tinc设置中调整,还是Tinc只是高吞吐量的坏选择?我应该使用IPsec吗?
ruby ×4
postgresql ×3
api ×1
caching ×1
database ×1
imagemagick ×1
ipsec ×1
multi-tenant ×1
pgbouncer ×1
rabl ×1
rmagick ×1
sidekiq ×1
ssh ×1
ssh-tunnel ×1
tinc ×1
user-agent ×1
xml-parsing ×1