2014年12月1日月曜日

pt-query-digest --type tcpdumpに3306以外のポートのダンプを食わせる方法

ハマったのでメモ。

サンドボックスな環境でMySQLのポートを64055にしていたら、pt-query-digest --type tcpdumpでそのまま食ってくれなかった。

結論、--portとかじゃなく、--watch-serverで指定するんだった。


$ sudo tcpdump -i any -p /tmp/test.cap -c 100
$ tcpdump -r /tmp/test.cap -n -x -q -tttt | pt-query-digest --type tcpdump
reading from file /tmp/test.cap, link-type LINUX_SLL (Linux cooked)

# No events processed.

あっれぇ。。
取り敢えずまずはPTDEBUG=1にして様子を見てみる。


$ tcpdump -r /tmp/test.cap -n -x -q -tttt | PTDEBUG=1 pt-query-digest --type tcpdump
reading from file /tmp/test.cap, link-type LINUX_SLL (Linux cooked)
# /usr/bin/perl 5.010001
# Linux dev-personal-04 2.6.32-279.19.1.el6.x86_64 #1 SMP Wed Dec 19 07:05:20 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
# Arguments: _[--type]_ _[tcpdump]_
# OptionParser:1522 29673 Option rule: This tool accepts additional command-line arguments. Refer to the SYNOPSIS and usage information for details.
..
# Pipeline:11539 29673 Pipeline restarting early after MySQLProtocolParser
# Pipeline:11527 29673 Pipeline process prep
# Pipeline:11527 29673 Pipeline process input
# Pipeline:11527 29673 Pipeline process TcpdumpParser
# TcpdumpParser:3658 29673 packet: $VAR1 = {
#   ack => 3530724024,
#   complete => 1,
#   data => '',
#   data_len => 0,
#   dgram_len => 40,
#   dst_host => '127.0.0.1',
#   dst_port => '42872',
#   fin => 1,
#   ip_hlen => 5,
#   rst => 0,
#   seq => 2831704995,
#   src_host => '127.0.0.1',
#   src_port => '64055',
#   syn => 0,
#   tcp_hlen => 5,
#   ts => '2014-12-01 16:40:11.599600'
# };
#
# Pipeline:11527 29673 Pipeline process MySQLProtocolParser
# MySQLProtocolParser:3916 29673 Packet is not to or from a MySQL server
# pt_query_digest:13442 29673 No more events, input EOF
..

どばー。
取り敢えず、MySQLProtocolParserの中で"Packet is not to or from a MySQL server"って言われてる。3916行目あたりにダイブ。


3894 my $src_host = "$packet->{src_host}:$packet->{src_port}";
3895 my $dst_host = "$packet->{dst_host}:$packet->{dst_port}";
..
3905 my $packet_from;
3906 my $client;
3907 if ( $src_host =~ m/:$self->{port}$/ ) {
3908 $packet_from = 'server';
3909 $client = $dst_host;
3910 }
3911 elsif ( $dst_host =~ m/:$self->{port}$/ ) {
3912 $packet_from = 'client';
3913 $client = $src_host;
3914 }
3915 else {
3916 PTDEBUG && _d('Packet is not to or from a MySQL server');
3917 return $self->{null_event};
3918 }

パケットの127.0.0.1:64055が$self->{port}を含んでいないのがいけないらしい。$self->{port}は何になってるかというと


$ tcpdump -r /tmp/test.cap -n -x -q -tttt | perl -d /usr/bin/pt-query-digest --type tcpdump
reading from file /tmp/test.cap, link-type LINUX_SLL (Linux cooked)

Loading DB routines from perl5db.pl version 1.32
Editor support available.

Enter h or `h h' for help, or `man perldebug' for more help.

main::(/usr/bin/pt-query-digest:65):
65:     package Percona::Toolkit;
  DB<1> c 3916
MySQLProtocolParser::parse_event(/usr/bin/pt-query-digest:3916):
3916:         PTDEBUG && _d('Packet is not to or from a MySQL server');
  DB<2> p Dumper $self
$VAR1 = bless( {
  fake_thread_id => '4294967296',
  null_event => undef,
..
  }, 'OptionParser' ),
  port => '3306',
  server => undef,
  sessions => {},
  version => '41'
}, 'MySQLProtocolParser' );

3306。オプションで--port 64055とかDSN形式でP=64055とか渡してやってもずっと3306。むぅ。デフォルトで3306になるのはMySQLProtocolParser::newでそうなってるからで、


3870 sub new {
3871 my ( $class, %args ) = @_;
3872
3873 my $self = {
3874 server => $args{server},
3875 port => $args{port} || '3306',
3876 version => '41', # MySQL proto version; not used yet
3877 sessions => {},
3878 o => $args{o},
3879 fake_thread_id => 2**32, # see _make_event()
3880 null_event => $args{null_event},
3881 };
3882 PTDEBUG && $self->{server} && _d('Watching only server', $self->{server});
3883 return bless $self, $class;
3884 }

これがどこから呼ばれてるかというとmainの中のここだった。


13393 my ($server, $port);
13394 if ( my $watch_server = $o->get('watch-server') ) {
13395 # This should match all combinations of HOST and PORT except
13396 # "host-name.port" because "host.mysql" could be either
13397 # host "host" and port "mysql" or just host "host.mysql"
13398 # (e.g. if someone added "127.1 host.mysql" to etc/hosts).
13399 # So host-name* requires a colon between it and a port.
13400 ($server, $port) = $watch_server
13401 =~ m/^((?:\d+\.\d+\.\d+\.\d+|[\w\.\-]+\w))(?:[\:\.](\S+))?/;
13402 PTDEBUG && _d('Watch server', $server, 'port', $port);
13403 }
13404
13405 foreach my $module ( @$type ) {
13406 my $parser;
13407 eval {
13408 $parser = $module->new(
13409 server => $server,
13410 port => $port,
13411 o => $o,
13412 );
13413 };

--portとかじゃなくて、--watch-serverから取ってたのか。。


$ tcpdump -r /tmp/test.cap -n -x -q -tttt | /usr/bin/pt-query-digest --watch-server 127.0.0.1.64055 --type tcpdump
reading from file /tmp/test.cap, link-type LINUX_SLL (Linux cooked)

# 410ms user time, 30ms system time, 25.84M rss, 212.79M vsz
# Current date: Mon Dec  1 17:44:12 2014
# Hostname: xxxx
# Files: STDIN
# Overall: 8 total, 6 unique, 0.35 QPS, 0.02x concurrency ________________
# Time range: 2014-12-01 16:39:48.680810 to 16:40:11.597656
# Attribute          total     min     max     avg     95%  stddev  median
# ============     ======= ======= ======= ======= ======= ======= =======
# Exec time          399ms       0   150ms    50ms   148ms    48ms    65ms
# Rows affecte           3       0       1    0.38    0.99    0.48       0
# Query size           220      16      36   27.50   34.95    6.66   30.22
# Warning coun           0       0       0       0       0       0       0
..

無事食えた。確かにマニュアルにもフツーに書いてあった。。
http://www.percona.com/doc/percona-toolkit/2.2/pt-query-digest.html#cmdoption-pt-query-digest--watch-server

0 件のコメント :

コメントを投稿