スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

PostgreSQLとRubyを組み合わせてブラックリストチェックの速度を測ってみた。

とある文章がブラックリストに載っているかどうかを判定しようと思っています。ブラックリストが4000レコードもあって、単純に見つかるまで処理すると遅いだろうと思い色々な方法で試して速度を測ってみました。
それぞれ100回回しています。

1. SELECT id FROM dirty_words WHERE 'うんこ' ~* dirty_content
9秒

2. SELECT 'うんこ' ~* string_agg(dirty_content, '|') FROM dirty_words
4秒

3. SELECT string_agg(dirty_content, '|') FROM dirty_words
返ってきた値に対してRubyの正規表現チェック
1秒

4. SELECT dirty_content FROM dirty_words
返ってきた値に対して、Rubyで文字列結合してRubyの正規表現チェック
6秒

5. SELECT dirty_content FROM dirty_words
返ってきた値に対して、それぞれでRubyの正規表現チェック
8秒

ということで、PostgreSQL側で一行にまとめて、Rubyで正規表現チェックするのが早いことがわかりました。
スポンサーサイト

Twitterのcreated_atをPostgreSQLのTIMESTAMP型に変換する

to_timestampではタイムゾーンの解釈ができないけど、Twitterは+0000でしかこないので決め打ちで変換します。
日本時間で管理したい場合は9時間足しておきます。

to_timestamp(
'Fri Feb 26 07:50:35 +0000 2016'
,'Dy Mon DD HH24:MI:SS +0000 YYYY'
)::TIMESTAMPTZ + interval'9 hour'

AnsibleでUbuntuに最新のjemallocをインストール

Ubuntuに最新のjemallocをインストールしたいのですが
なぜかppaにあるのはバージョン3系ばかりで最新の4系が無いんですよ。
なので、Ansibleでソースからインストールするroleを書いてみました。

tasks/main.yaml
- name: "test jemalloc"
command: bash -lc "ls -la {{ src_dir }}|grep {{ jemalloc_name }}"
register: jemalloc_installed
ignore_errors: yes

- name: "get file"
get_url:
url: "{{ jemalloc_url }}"
dest: "{{ src_dir }}"
mode: 0664
when: jemalloc_installed|failed

- name: "unarchive"
unarchive:
copy: no
src: "{{ jemalloc_archive }}"
dest: "{{ src_dir }}"
when: jemalloc_installed|failed

- name: "rm archive"
file:
path: "{{ jemalloc_archive }}"
state: absent
when: jemalloc_installed|failed

- name: "configure"
command: ./configure
args:
chdir: "{{ jemalloc_dir }}"
when: jemalloc_installed|failed

- name: "make"
command: make
args:
chdir: "{{ jemalloc_dir }}"
when: jemalloc_installed|failed

- name: "setting"
template:
src: ld.so.preload.j2
dest: /etc/ld.so.preload
mode: 0644
owner: root
group: root
when: jemalloc_installed|failed
become: yes


templates/ld.so.preload.j2
{{ jemalloc_library }}


vars/main.yaml
jemalloc_version: "4.0.4"
jemalloc_name: "jemalloc-{{ jemalloc_version }}"
jemalloc_url: "https://github.com/jemalloc/jemalloc/releases/download/{{ jemalloc_version }}/{{ jemalloc_name }}.tar.bz2"
jemalloc_dir: "{{ src_dir }}/{{ jemalloc_name }}"
jemalloc_archive: "{{ jemalloc_dir }}.tar.bz2"
jemalloc_library: "{{ jemalloc_dir }}/lib/libjemalloc.so"

開発中にDBに一括で登録するスクリプト

開発中には、以下ような感じでSQLファイル等を分けて管理しています。

db
|- bin
|- erd
|- sql
|- 01schema.sql
|- 02data.sql
|- lib
|- uv_plpgsql.sql
|- ...
|- stored
|- ...
|- table
|- users.sql
|- ...

これを一括でDBに登録するのがめんどくさいです。
なのでスクリプト書きました。
vi bin/config.yaml

default: &default
psql: /usr/bin/psql
base: ../sql
db_host: localhost
db_user: user
db_name: web_development
params:
- name: schema
path: 01schema.sql
command: c
- name: lib
path: lib/*.sql
command: l
- name: table
path: table/*.sql
command: t
- name: stored
path: stored/*.sql
command: s
- name: data
path: 02data.sql
command: d

development:
<<: *default

test:
<<: *default
db_name: web_test


vi bin/make_sql.rb

require 'optparse'
require 'tempfile'
require "yaml"
require "erb"

# ファイルを読み込む
def read_one(path, dst)
open(path) do |file|
dst.puts file.read
end
end

# ディレクトリの中のファイルを読み込む
def read_many(path, dst)
Dir::glob(path).each do |f|
read_one(f, dst)
end
end

# パラメーターをパースする
def parse(params)
ary = []
all = []
params.each do |param|
all << param["command"]
ary << "-#{param["command"]} : #{param["name"]}"
end
ary << "-e : 環境名"
ary << "-#{all.join("")} : all"
[ary.join("\n"), all.join("") + "e:"]
end

# コマンドを生成する
def make_command(environment, file)
"#{environment["psql"]} -h #{environment["db_host"]} -U #{environment["db_user"]} #{environment["db_name"]} < #{file.path}"
end

#
# 処理本体
#

# コンフィグを読み込む
config = open("./config.yaml") do |f|
::YAML::load(::ERB.new(f.read).result)
end

# エラーメッセージと全てのパラメーター取得
error_message, all_parameters = parse(config["development"]["params"])

# 引数が空の時は終了
if ARGV.empty?
puts error_message
exit 0
end
params = ARGV.getopts(all_parameters)

# 環境が無い場合は終了
if params["e"].nil? || "" == params["e"]
puts error_message
exit 0
end

environment = config[params["e"]]
base = environment["base"]

Tempfile.open('makesql') do |file|
targets = environment["params"]
targets.each do |target|
# コマンドが選択されているものだけ処理する
if params[target["command"]]
path = "#{environment["base"]}/#{target["path"]}"
if /\*/ =~ target["path"]
read_many(path, file)
else
read_one(path, file)
end
end
end
file.close
command = make_command(environment, file)
system(command)
end


以下のように実行します。
ruby make_sql.rb -cltsd -e development

RailsでProxy経由の接続で本当のIPアドレスを取得する

WAFなどのプロキシーを通した時にRailsでは発信元のIPを取得することができなくなります。
その対応方法です。

プロキシーのIPアドレスを
1.2.3.4
5.6.7.8
の2つとします。
またAWSのELBではプライベートアドレスで接続してくるので、それも追加しています。

まず、nginxがRailsの前にいる場合はそれから設定します。

set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.16.0.0/12;
set_real_ip_from 192.168.0.0/16;
set_real_ip_from 127.0.0.1/32;
set_real_ip_from 1.2.3.4/32;
set_real_ip_from 5.6.7.8/32;
real_ip_header X-Forwarded-For;

次にRails側です。
vi config/application.rb
config.action_dispatch.trusted_proxies = /(^127\.0\.0\.1$|^(10|172\.(1[6-9]|2[0-9]|30|31)|192\.168)\.)|(1\.2\.3\.4)|(5\.6\.7\.8)/

RailsではIPアドレスの正規表現で設定します。
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。