while(true) ;

クソNoobな情報系学生のblog。c++やRuby, Railsやってます。perlは猛勉強中。

td-agentを使ってMysqlにLogを格納する Part 2 [td-agentの導入]

前回に続き、

kazunyaaan.hatenablog.com

最近作っているTCPハニーポットのLogをtd-agentを使ってMysqlに格納していきます。

td-agent (fluentd)でmongodbにVPSTCPスキャンログを取っていたのですが、なんとなくMysqlに移行して行こうと思います。

td-agent (Fluentd)って?

Fluentdの安定リリースだそうです。 knowledge.sakura.ad.jp

以下、OSはcentos 6.8です。rubygemでfluentdをインストールする方法もありますが、今回は公式からyumリポジトリを追加し、インストールしました。

td-agentのインストールと起動

$ curl -L https://toolbelt.treasuredata.com/sh/install-redhat-td-agent2.sh | sh

$ sudo service td-agent start
Starting td-agent: td-agent                                [  OK  ]
$ sudo service td-agent status
td-agent is running                                        [  OK  ]

td-agentのmysqlプラグインをインストール

$ sudo td-agent-gem install fluent-plugin-mysql

rubyでテストコードを作成

require 'fluent-logger'

Fluent::Logger::FluentLogger.open(nil, host: 'localhost', port:12345)
Fluent::Logger.post('td.honeypot.log',
{
  TIME: "#{Time.new}",
  IP: "127.0.0.1",
  PORT: "22",
  COUNTRY: "TEST",
  DATA: "hogehoge"
}

td-agentの設定ファイル変更

$ sudo vim /etc/td-agent/td-agent.conf

あらかじめMysqlでcreate tableしておきます。rubyのプログラムに合わせて設定していきます。

<source>
  @type forward
  port 12345
</source>

<match td.honeypot.log>
  @type copy
  <store>
    @type mysql_bulk
    host 127.0.0.1
    port 12346
    username XXXX
    password xxxx
    database honeypot
    table log
    column_names time,ip,port,country,data
    key_names TIME,IP,PORT,COUNTRY,DATA
  </store>
</match>

最後にtd-agentに設定ファイルをreloadさせて終わり。

$ sudo service td-agent reload

これで
 Ruby -> td-agent -> mysql
へLogを渡し、格納していくことができました。

td-agentを使ってMysqlにLogを格納する Part 1 [mysqlの導入]

修士論文も終盤をむかえ、余裕がでてきました。kazunyaaanです。

最近作っているTCPハニーポットのLogをtd-agentを使ってMysqlに格納していきます。

td-agent (fluentd)でmongodbにVPSTCPスキャンログを取っていたのですが、なんとなくMysqlに移行して行こうと思います。

とりあえずmysqlを導入します。

Mysqlのインストール

$ sudo yum install -y mysql-server

設定変更

$ sudo vim /etc/my.cnf

ローカルのみアクセスを許可とポート番号の変更を追記。

[mysqld]
bind-address=127.0.0.1
port=12346

Mysqlの起動と自動起動

$ sudo service mysqld start
Starting mysqld:                                           [  OK  ]

$ sudo chkconfig mysqld on

$ sudo netstat -tlpn | grep mysqld
tcp        0      0 127.0.0.1:12346             0.0.0.0:*                   LISTEN      xxxx/mysqld

あとは適当にデータベース作っときます。

C++で円周率(PI)を1億桁計算してみた Part1

修士課程でプログラムの最適化or高速化という題でプレゼンしてくれということで・・・
なんとなく円周率を計算するプログラムを作成&高速化(※学生レベルの範囲で)してみました!

そもそも1億の円周率の計算になにが必要かを簡単にまとめると、
多倍長整数
・高速な円周率の計算式
・それなりに大きいメモリ
といったかんじですね。

なぜ円周率(3.141592…)の計算に浮動小数点型ではなく整数型なのかというと…

主な理由は「計算の高速化」ですね。浮動小数点演算は整数演算よりコストが大きい傾向があるからです。

それじゃあ多倍長整数をつかおう!

任意桁数あつかえる多倍長整数を1から作ってもいいのですが…高速な四則演算扱える形にするには骨が折れますので、 今回はライブラリを使用していきたいと思います。

有名な物には、 ・GMP
・Boost.Multiprecision
・LibTomMath
などがありますね。

それぞれメモリ効率や演算アルゴリズム等が違い、一長一短があります。 次回Part2でどの多倍長整数をつかうか決めていきたいとおもいます。

そろそろプログラミングを始めよう…

しばらくハードウェアに没頭しておりました…www

昔つくったXbee + ArduinoでRSSIをもとにON/OFFを自動制御するタップ 電力消費とON/OFFを自作サーバーで管理できないか、等を試行錯誤して遊んでました。

趣味のブログだし、ハードウェアも記事にしちゃおうかな…と思考中。

RubyのFork + Socketを利用したプロセス間通信 その1

どうも、kazunyaaanです。

今回は双方向の通信ができるUnixSocketを使ってみます。 インターネットドメインソケットと類似してますが、ネットワークプロトコルは使用していない等のため、
高速な通信を可能としています。(たぶん...後々確認予定...)

初めは、UnixSocketを使った基礎的なプログラムから。 今回はUNIXSocket.pair(Socket::SOCK_DGRAM)とし、コネクションレス型通信(データグラム)を扱います。

以下、実行結果。

$ ruby Test_unixsocket.rb
[P] I am parent processe.
[C] I am child processe.
[P] C -> P : 0
[P] C -> P : 1
[P] C -> P : 2
[P] C -> P : 3
[P] C -> P : 4
[C] P -> C : 0
[P] C -> P : 5
[C] P -> C : 1
[P] C -> P : 6
[P] C -> P : 7
[P] C -> P : 8
[C] P -> C : 2
[P] C -> P : 9
[C] P -> C : 3
[C] P -> C : 4
[C] P -> C : 5
[C] P -> C : 6
[C] P -> C : 7
[C] P -> C : 8
[C] P -> C : 9

こんな感じですかね。やっぱり、Rubyで組むと楽ですね。

多プロセスの場合、やっぱり、unixsocketを共有しちゃうと駄目なのかな...?

RubyにおけるThreadとForkの速度比較

こんばんは、kazunyaaanです。今回は並列処理の速度比較を行います。
(個人的に専門が数値計算で、MPI等でごりごり並列化をおこなっているのでとてもわくわくです(笑))

前回の記事で、RubyにおけるThreadは多くの場合にて
"並行処理となる"
ことに簡単にふれてみました。

今回は、Threadだけでなく、Forkも含めた、
Rubyでのマルチスレッドおよびマルチプロセスのプログラムとその速度比較を行ってみたいとおもいます。

まず実験環境

今回は贅沢に

の計算機サーバを使って、CentOS7、Ruby 2.2.0 の実験環境を用意しました。

コード

今回は、

  • Normal : 普通に書いた場合

  • Thread : Threadを用いたマルチスレッド

  • Fork : Forkを用いたマルチプロセス

の3つの浮動小数点の加算の速度比較を行います。

以下、Rubyにおけるコードです。

これを実行すると、こんな感じで結果が得られます。

$ruby add_speed.rb                                            
        12    0.000    0.001    0.095
        24    0.000    0.001    0.116
        48    0.000    0.001    0.119
        96    0.000    0.001    0.152
       192    0.000    0.001    0.185
       384    0.000    0.001    0.109
       768    0.000    0.001    0.166
      1536    0.000    0.001    0.127
      3072    0.000    0.001    0.093
      6144    0.000    0.002    0.144
結果

では、今回行ったRubyのNormal, Thread, Forkの速度比較の結果を見ていきます。

gnuplotでプロットした結果です。まずはそのまま結果をプロット。

f:id:kazunyaaan:20150117015131p:plain

続いて、Normalに対する速度向上比を見てみます。

f:id:kazunyaaan:20150117005322p:plain

考察

それぞれ普通に書く場合、マルチスレッドの場合、マルチプロセスの場合を比較しました。

やはりRubyのThreadクラスを用いたマルチスレッドでの処理では、仕様上、複数のプロセスを活かす並列処理を行えませんでした。
(詳しくはこちらRubyのスレッド周りの話 - Qiita)

また、ThreadとForkに関してそれぞれの生成コストがとても大きいことがわかりますね。
(rubyにおいて、普通に書いた、シングルスレッドは相当優秀ですね...)*1

ただ、かなり大掛かりな処理になると、Forkは約10倍の速度向上も見られます。

.


以下、個人的なおまけ。(偏見込み)

おk。重い処理はForkで組めばいいのね。

これは、良くない考えかと思います。 Forkでプログラムを組むと確かに、Ruby複数のコアを活かせる処理ができます。
しかし、デメリットとして、

  • マルチプロセスの為、メモリ空間がプロセス毎に分けられる。
  • 結果等を受け取るには、プロセス間通信が必要。(socketやパイプ)
  • 何より、並列化等実装のコストが...

などなど...。
そもそもRubyに処理速度を求めるのは間違いですね。 速さが重要なら、C++等でGPGPUやMPIですかね。

じゃあ、Threadのメリットって?

今回は活かしきれないThreadですが、

  • クローラー
  • Thread + Queue を使ったプログラム 等に、大きなメリットがあるかと思います。

このへんは、後日簡単なプログラムでメリットを見ていきたいとおもいます。

*1:今回は、Threadが活かしにくいプログラムとなっています

Rubyでマルチスレッド <Thread>

どうも、こんにちは。kazunyaaanです。
年は明けましたが、まだまだ、大雪が続いております...

マルチスレッドやマルチプロセス

Haswell世代にて物理18コアを達成したE5-2699v3など、マルチコア化が進む中、
マルチスレッド or マルチプロセスは重要なキーワードではないでしょうか?

そこで、数回にわたってRubyにおけるマルチスレッドプログラミングを取り扱っていこうかと思います。

Rubyにおけるマルチスレッド処理

RubyではThreadクラスを用いて、以下のように比較的簡単に"並列"処理を行うことができます。

a_thread = Thread.new do
  5.times do |i|
    puts "#{i} : I am A."
  end
end

b_thread = Thread.new do
  5.times do |i|
    puts "#{i} : I am B."
  end
end

a_thread.join
b_thread.join

メインスレッド、a_thread、b_threadの3つのスレッドがプログラム実行中に存在し、 実行結果は、マルチスレッドで実行しているため毎回異なりますが、

0 : I am B.
1 : I am B.
2 : I am B.
3 : I am B.
0 : I am A.
4 : I am B.
1 : I am A.
2 : I am A.
3 : I am A.
4 : I am A.

のようになりますね。

Threadクラスを使ったRubyのプログラムは"並列"に処理をしていることが確認できるかと思います。

しかし、Rubyのスレッドはある時点に1つのスレッドを処理しているもので、複数コアでの並列処理はできていないのです。 (topコマンド等で確認してみてください)

Rubyのスレッドに関する(メモ)

(~1.8) -> グリーンスレッド http://docs.ruby-lang.org/ja/1.8.7/doc/spec=2fthread.html

(1.9~) -> ネイティブスレッド http://docs.ruby-lang.org/ja/2.2.0/doc/spec=2fthread.html

2.2.0のThreadクラスの実装の一部を見てみると...

ネイティブスレッドを用いて実装されていますが、 現在の実装では Ruby VM は Giant VM lock (GVL) を有しており、同時に実行される ネイティブスレッドは常にひとつです。

となってるんですよね...

次回、そこらへんを見ていきます。では。