Hatena::ブログ(Diary)

kameidの備忘録 - Sharpen the Saw! このページをアンテナに追加 RSSフィード

2018-07-11

net.ipv4.tcp_timestamps

おおはまりしたので、記録。


あるシステムでのトラブル。サーバはよそのところ。こっちはクライアント。まったく同一の OS、同一の設定なのに、ホストによってあちらのサーバにアクセスできたりできなかったりする。以前から動いていたホストは問題ない。後から追加したホストがダメ。

http://ya.maya.st/d/200804c.html#s20080430_2

これに近似した状況。

web サーバエラーログだけは出る。

[Mon Jun 11 12:34:08.181627 2018] [proxy:error] [pid 1380] (70007)The timeout specified has expired: AH00957: HTTP: attempt to connect to xx.xx.xx.xx:80 (xx.xx.jp) failed

で、先方に問い合わせてもアクセスの形跡が無いと言われてしまう。

真面目に調べてくれてないだけという可能性もあるけど、そういわれてしまうと証明しないとならない。


2台構成のサービスで、タイムアウトは片方のサーバでしか発生しない。

まずやったことは1台構成に縮退してみる。

結果:1台だとうまいこと動く。


web サーバの設定差を疑ったが、この時点でその線は消えた。

次に、NAT 経由でのアクセスであるため、NAT が怪しいと思い、NAT を交換。

結果:だめ


それでも NAT しかないやろと思い、NAT を1インスタンス1台という、

専用構成にしてみる。インスタンス毎にサブネットを別々にしていたのが幸いし、

これはルートテーブルを差し替えるだけで簡単に試せる。

結果:OK


いやいやそんなことあります?未曾有の経験。つまり NATNAT として

機能している。


次にやったことが、タイムアウトするまでの間に netstat してみる。

[ ~]$ netstat -n -t | grep xx.xx.xx.xx
tcp        0      1 xx.xx.xx.xx:52136           xx.xx.xx.xx:80           SYN_SENT    

ん?SYN_SENT でとまってる・・・。

つまり、TCP のハンドシェイクの時点で待ちになっちゃっているということ。

もし先方までアクセスが到達していたとしても、これじゃアクセスログは残らない・・・。

次。

どこまでアクセスは到達してるのか。

sudo tcpdump host xxx.xxx.xxx.xxx -w nat &
sudo tcpdump host xxx.xxx.xxx.xxx -w 1a &
sudo tcpdump host xxx.xxx.xxx.xxx -w 1c &

tcpdump してみて、プロトコルアナライザで見てみる。

ちなみに、Wireshark を使いました。

結果:

NAT まで到達して、先方までちゃんとアクセスを投げている!

しかし、TCP の SYN を送った後、先方から ACK が返ってこず、

数回リトライしてタイムアウトしている!


・・・この時点で、グーグルさんに登場願う。

nat syn timeout」みたいな適当なキーワードぐぐると、

出てくる出てくる、類似事例が。


一番まとまっているように見えたのが上記の方のページ。

先方の設定を変えてもらうことは出来ないので、各インスタンスに、

sysctl -w net.ipv4.tcp_timestamps=0
cat << 'EOS' > /etc/sysctl.d/tcp_timestamp.conf
net.ipv4.tcp_timestamps = 0
EOS

って感じで設定。


あっさりと問題は解決した。

この感謝の気持ちを込めて、キーワード入りのブログを残す。

お役に立てば幸いです。


その他にも実際にはいろいろ調べたけれども、結局 OS 依存するところが多いため、

あまり参考にならないと思われるので、割愛。

2018-06-28

Java で stackTrace を String で受け取る方法

String stackTrace 
  = Arrays.asList(e.getStackTrace()).stream().collect(Collectors.toStringJoiner(“\n”)));

Java8 だと上記のような感じになると思います。もっとシンプルな方法はないものかね。

「いつこんなの使うの?」という疑問があると思いますが、「例外が起きた時メールで stacktrace 送ってくれ」って言われた時ですw

2018-06-27

suid が利かなくてはまった

perl スクリプトの中で secure ログを cat するような処理を書いていて、secure ログを cat するには root 権限が必要なので、

その perl スクリプトを suid すればいいよね、と軽く考えていた。

suid はほぼ使う機会が無いので知らなかったのだけど、実はスクリプト系のものには suid は無効らしい。


perl やら ruby やら sh やらのスクリプトは、chmod u+s しても効果がない。バイナリな実行ファイルでないと、OS は setuid/gid フラグを無視してしまって意図した権限で実行してくれない。それを許すと 穴になるからしかたないというのは承知してるけどさ、どーしてもやりたいこともあるわけで、そのたびごとに C のラッパーを書くのはめんどくさい。仕事だからやるけどさ

http://ya.maya.st/d/200908a.html

で、suid で変更したidは起動したプロセスでのみ有効で、内部で別プロセスを生成するときには変更前のidが使われる、と同僚が教えてくれたので、これも初耳。以下、ちょっと検証として、あってるのかあってないのか、微妙なコード。

#include <unistd.h>
#include <pwd.h>
#include <stdio.h>

void main (char* args) {
        struct passwd* pw;
        pw=getpwuid(geteuid());
        printf("%s\n",pw->pw_name);
        system("id");
}
$ gcc a.c;sudo chown root:root a.out; sudo chmod u+s a.out;./a.out
root
uid=501(kamei) gid=501(kamei) groups=501(kamei),10(wheel)

「system("id");」のとこは、合ってるのかどうか自信ない。

ちなみに、perl では、昔は suidperl ってのをインストールすると、suid を使えたようだが、今はたぶん使えなさそう。

あんまりこれをまじめに調べるモチベーションが無いので、すみません、適当にぐぐった結果ですmm

2013-03-02

MySQL 上のログテーブルの扱い方

保存期限を3か月とか、任意の期間で自動削除する仕組みについて。

ログっていうのは、アクセスログとかアクティビティーログを想定している。

単純にログテーブルを作成してデータを入れていくのは簡単だけど、古いデータをどのタイミングで、どのように消すか、というのが問題。

ただこれ調べ始めていきなり結論っぽいものを発見してしまった。

Mobageを支える技術 ~ソーシャルゲームの舞台裏~ (WEB+DB PRESS plus)

Mobageを支える技術 ~ソーシャルゲームの舞台裏~ (WEB+DB PRESS plus)

P216 あたりから、Range パーティションしたテーブルとイベントスケジューラを組み合わせてローテートを行う方法。普通これを使うんだろうな・・・。

MySQLパーティションテーブルについてはこちらがわかりやすい。

高速処理化!MySQLのパーティショニング機能を使ってみよう | 東京上野のWeb制作会社LIG

↓とても詳しい。さすが DeNA のなかのひと。

ソーシャルゲームのためのMySQL入門 - Technology of DeNA

日次等のタイミングでイベントスケジューラを利用して

を行うだけ。

ただし、以下のような事で、IF [NOT] EXISTS は使えないので、ちょっと工夫は必要。

ADD PARTITION と DROP PARTITION は現在 IF [NOT] EXISTS をサポートしていません。パーティションや分割されたテーブルをリネームする事も不可能です。その代わりに、もしパーティションリネームしたいのであれば、パーティションをドロップして再作成する必要があります。そしてもし分割済テーブルをリネームしたければ、全てのパーティションをドロップし、テーブルをリネームし、そしてドロップされたパーティションをもう一度追加する必要があります。

no title

イベント処理については以下。

no title

MySQL :: Page Not Found

レプリケーション考えると面倒が起きそうなので、ウチではイベントスケジューラ使わずに、素直に cron に perl スクリプト仕込む感じでやることにしそう。

2012-08-18

Kyoto Tycoon をマスター・スレーブ構成で起動

起動の為のスクリプトを客先では作ったが、自宅には無いのでとても不便だ・・・。

とりあえず起動。

ktserver -port 1978 -ulog master-ulog -sid 1 master.kch &

ktserver -port 1979 -sid 2 -mhost localhost -mport 1978 -rts slave.rts &

Kyoto Tycoon のインストールメモ

Kyoto Tycoon のインストールメモ

AWS 環境だけど、root さえあれば特に変わるところ無し。

root 無い場合はディレクトリ指定が必要。

今回は指定しなかったので、そこはパス。root あると楽だわ・・・。

ちなみに、AMI は、これ使った。一番普通のやつだと思う。

amzn-ami-pv-2012.03.3.x86_64-ebs (ami-2819aa29)

手順はとても簡単だけど micro インスタンスだと

make に 20 分くらいかかる。micro じゃなくても make は

結構時間かかる。

必要なコマンドをインストール

gcc++ と make が入ってない環境だったので、インストール

sudo yum install gcc

sudo yum install gcc-c++

sudo yum install make

必要なパッケージをゲット

wget http://fallabs.com/kyototycoon/pkg/kyototycoon-0.9.56.tar.gz

wget http://fallabs.com/kyotocabinet/pkg/kyotocabinet-1.2.76.tar.gz

wget http://zlib.net/zlib-1.2.7.tar.gz

zlib のインストール

tar zxvf zlib-1.2.7.tar.gz

cd zlib-1.2.7

./configure

make

make install

cd ..

Kyoto Cabinet のインストール

tar zxvf kyotocabinet-1.2.76.tar.gz

cd kyotocabinet-1.2.76

./configure

make

make install

cd ..

Kyoto Tycoon のインストール

tar zxvf kyototycoon-0.9.56.tar.gz

cd kyototycoon-0.9.56

./configure

make

make install

cd ..

以上。

configure: error: C++ preprocessor "/lib/cpp" fails sanity check

一個、「あれ?」と思ったのが、Kyoto Cabinet インストール中に出た

以下のエラー。


./configure

#================================================================

Configuring Kyoto Cabinet version 1.2.76.

#================================================================

checking for gcc... gcc

checking whether the C compiler works... yes

checking for C compiler default output file name... a.out

checking for suffix of executables...

checking whether we are cross compiling... no

checking for suffix of object files... o

checking whether we are using the GNU C compiler... yes

checking whether gcc accepts -g... yes

checking for gcc option to accept ISO C89... none needed

checking for g++... no

checking for c++... no

checking for gpp... no

checking for aCC... no

checking for CC... no

checking for cxx... no

checking for cc++... no

checking for cl.exe... no

checking for FCC... no

checking for KCC... no

checking for RCC... no

checking for xlC_r... no

checking for xlC... no

checking whether we are using the GNU C++ compiler... no

checking whether g++ accepts -g... no

checking how to run the C++ preprocessor... /lib/cpp

configure: error: in `/root/kyotocabinet-1.2.76':

configure: error: C++ preprocessor "/lib/cpp" fails sanity check

See `config.log' for more details


データベースエラー

で原因判明。c++ コンパイラ入らないのか・・・。

手元の環境では、これを参考に

sudo yum install gcc-c++

してあげると無事 ./configure 通った。

ldconfig

もう一個。インストール直後はライブラリにパスが通ってないので、

Ubuntuにkyoto tycoonをインストールしてみた。 - メイクミラクル 〜大逆転〜

の ldconfig あたりの手順を実行する必要がある。(手抜き)

2012-08-04

DR について

データ欠損ゼロを実現するためには同期コピーが必須となる。

(中略)

一般に、同期コピーが適用可能な距離は100km以内とされている。これ以上の遠距離の構成では、複数のログやトランザクション情報をまとめて転送するなど、データ転送遅延時間の影響を最小化する工夫が必要となる。また、WAN最適化コントローラなどを適用し転送遅延時間を削減することも有効だ。

 システムの要件によっては、データ欠損ゼロを保障する同期コピーのリモートサイトを100km以内の近郊に置き、災害直前のデータ欠損をある程度許容する非同期コピーのリモートサイトを遠隔地に置く3データセンター方式も有効である。

no title

SnapMirrorは、元々ディザスタリカバリー(災害復旧)用のミラーをリモートサイトで作成することを目的とした機能です。

NetApp - Tech OnTap - NetAppの統合データプロテクション:最適なデータ保護ソリューションを選択する方法

LANケーブルや光ファイバの中を信号が伝播する速度は,おおむね 1kmあたり5マイクロ秒とされています。

(中略)

東京から大阪まで光ファイバを敷設した場合,直線距離なら400km程度ですが,ケーブルは一直線に敷設できるわけではないので,ケーブル長としては1000kmくらい必要になると思われます。ということは,片方向で5ミリ秒ほどの遅延が発生しますので,RTTは10ミリ秒になります。

第2回 ネットワーク遅延と高速化:教科書には載っていない ネットワークエンジニアの実践技術|gihyo.jp … 技術評論社

200km あたり 1ms。往復で 100 あたり 1ms。よーするに、RTT は 100km あたり 1ms が目安か。


その他

トランスポート層における Web 最適化 - Life like a clown

2012-06-25

12年後のCAP定理: "法則"はどのように変わったか

12年後のCAP定理: "法則"はどのように変わったか

この記事すごい・・・。もう今まで見たことのないレベルのサマリでびっくり。中には過去に自分が表現したくて苦労した事がわかりやすく表現されている個所もありショック(笑)

原文は、Eric Brewer ご本人の著。

"3つのうち2つ"はいくつかの場面でミスリーディングです。まず、分割は滅多に起きないので、分割のない状態ではCやAは失われません。次に、同じシステムの中でとても細かい粒度で何度もCとAのどちらかを選択する場合があります。サブシステムによって異なる選択をすることもできますし、操作やデータや関係するユーザによって選択を変えることもできます。最後に、3つの属性は満たす/満たせないのふたつの選択肢しかないのではなく、度合いがあります。可用性は明らかに0%から100%まで度合いがありますが、一貫性にも多様なレベルがあります。分割耐性にも同様です。システムに分割があるかどうかについての意見の相違も含んだ度合いがあります。

12年後のCAP定理: "法則"はどのように変わったか

以下が原文

As the "CAP Confusion" sidebar explains, the "2 of 3" view is misleading on several fronts. First, because partitions are rare, there is little reason to forfeit C or A when the system is not partitioned. Second, the choice between C and A can occur many times within the same system at very fine granularity; not only can subsystems make different choices, but the choice can change according to the operation or even the specific data or user involved. Finally, all three properties are more continuous than binary. Availability is obviously continuous from 0 to 100 percent, but there are also many levels of consistency, and even partitions have nuances, including disagreement within the system about whether a partition exists.

感動。是非読んでほしい。

結果整合性の意外な適用場所

ブログを相当長いこと放置していたので、たまには生存確認をかねて、投稿を・・・。

お金が絡むところでは厳密な一貫性が要求され云々言うわけだけども、一貫性を妥協すると全てが得られる。少なくとも高い可用性とスケーラビリティーが。*1

以下のような CAP 定理に関する反証もあるけど、

While the impossibility proof of CAP is mathematically correct, it is based on assumptions that are too strict. By relaxing these assumptions, I found the solution presented here.

Guy’s Blog: A CAP Solution (Proving Brewer Wrong)

「Proving Brewer Wrong」と言っている割には、「CAP の並立不可能性は数学的には正しい」と認めていて、反証だか何だかよくわからない。時間を味方に付ければ CAP が並立することはブリュワーだって否定していないだろう。*2

さて、本題の意外な結果整合性の適用箇所だけど、某大手銀行の Web システム。

  1. A 銀行の Web システムで自分の口座にログインして、B 銀行の自分の口座に送金。
  2. A 銀行の Web システムで「着金完了」を確認。
  3. B 銀行の Web システムで自分の口座にログインして残高を確認するも残高は変わらず。(別にこの時点であわてたりはしない。ここで時差が出るのは普通の事なので。)
  4. B 銀行に電話して、Web 画面での残高を超える金額の送金指示を出す。
  5. 普通に受理される
  6. 送金完了を伝えられ、Web 画面で残高を確認するもまだ変わらず。
  7. 残高ではなく、入出金履歴を見ると入金と送金の履歴が。残高も変わっている。
  8. 再度残高確認画面に行くと、まだ残高は変わっていない・・・。

まあ結局しばらく待っていると残高は正しい数字になったけど、要するにこの銀行はどこで一貫性が取れている必要があるかをちゃんと認識していて、一貫性が取れている必要が無い部分については結果整合性が取れればよしとしているということになる。何の問題もないけど、銀行ってたとえ Web システムだろうが一貫性を重視してる*3んじゃないかっていうような思い込みがあって意外に思ってしまった*4

この事例で学んだことは、「一貫性を保持する範囲を可能な限り絞り込む」こと。CAP 定理により、一貫性を重視することは他の2つの特性(可用性、分割耐性)のうちのどちらかを犠牲にすることにつながる。しかし、時間軸を考慮に入れるなら CAP は成立しうる。そして一貫性を保持する範囲を絞り込むならばさらに可用性と分割耐性を向上させることができる

この辺は何々データベースの導入やら分散データストア製品の何々を導入したらという範疇に話が収まらず、要件定義、基本設計レベルでの考慮が必要になるため、アーキテクトと要件定義者双方に認識が必要。

*1CAP定理 - Wikipediaを参照。

*2:「タイトルは釣り」かもしれない。コメントでも「同時に」がポイントとやんわり突っ込みが・・・。

*3:とはいえ、銀行間の送金にはすごい時間がかかる時がある。月末の送金はその日中に着金が完了しないことも経験済み。これは銀行のシステム間では「結果整合性」が実現されておりかつ、何の問題もないという良い例とも言える

*4:私は金融系のシステムなんて実質未経験みたいなものなんで、まったくの想像だけど、銀行がこういう結果整合性の概念を持っているのはある意味当然というか、実は彼らは結果整合性のエキスパートなのかもしれない。だって歴史的に金融系のシステムってバッチ処理中心に構築されてきただろうし、そのバッチ処理って、要するに非同期処理なわけだし。どこに一貫性が必要でどこに不要か、なんて事はいの一番に考える事なのかも知れない。

2010-08-02

零細システム開発会社における「選択と集中」

XHTML&CSS超高速コーディング術

XHTML&CSS超高速コーディング術

池袋ジュンク堂で偶然手に取った本書。再利用性のたかいCSSのデザインやら、コツの様な話かと思ったらそういう事だけでなく、入稿からスケジュール管理まで含めた牧野工房という会社のワークフロー紹介という、一風変わった本。まあ、会社の宣伝ちゃ宣伝かもしれない。

牧野工房という会社では、通常のホームページ制作会社とは異なり、デザインは完成しているという前提で、出来上がったデザインを入稿してもらい、それをHTML+CSS に落とす、という工程に特化している。

このような特化のため、結果的に数をこなせ、社内の共通化、ルール化、ワークフロー化が進み、ますます数をこなせる、という循環が働いている。

絵に描いたようなドラッカーの「選択と集中」の実践であり、同業の参入が予想されると筆者は書いているものの、ブランド化に成功すればライバル不在になりそうな商売である。

余談だけど、私自身はこれと同様のことを零細のソフトウェア開発会社に所属するエンジニアにもたびたび見ている。(まあウチもそうなんだけど)

彼らの中には、数ヶ月以下という、非常に短期のスパンでコーディング、テストのみを10年近い歳月にわたってやり続けたものまでおり、「Eclipse でソース書いてるはずなんだけど、横で見ていて何しているのかわからない」というレベルに達している人が実在する。

彼らは設計書がなかったり、むちゃくちゃだったりしてもうまくそれを客から聞き出して形にする技術も兼ね備えていたりもするのだ。私などは関心させられることしきりなのだけど。

なかなかこういったことを強みとしてブランド化に成功している会社に出会ったことはないし、オフショア化が進む中、海外勢がこの戦略をとった場合、とんでもないレッドオーシャンに叩き込まれる可能性もなくは無いが(笑)、いくらでも差別化の方向性はあるし、ぜひどこかやってくれないかな。

Web サイトのクライアントサイドに徹底的にこだわる

Web サイトの高速化は、サーバサイドの対処ばかりが実施されることが普通なように思いますが、単純なリクエスト-レスポンスであれば、待ち時間の80%はフロントエンドの処理に費やされているらしい。

よく言われるような「JavaScriptHTML の最後に記述しない」等の基本的なところから、DNS ルックアップの減らし方といったちょっと高度なところまでクライアントサイドに着目して高速化を追及している。


で、上記の続巻が先日翻訳されたんだけど、

大幅に値上がりしており、買うかどうか悩む。非対応ブラウザの関係から、なかなか使いにくい gzip圧縮転送や、サーバープッシュの Comet の解説など、今風の話題が多くて興味は惹かれるんだけど。Comet はサーバ側の課題も多くて、面白い技術だと思っている。

HTML5 で Comet にかわる技術? - kameidの備忘録 - Sharpen the Saw!

Google Sitebricks - kameidの備忘録 - Sharpen the Saw!

2010-06-16

xml schema での datetime の扱い

Time Zones

To specify a time zone, you can either enter a dateTime in UTC time by adding a "Z" behind the time - like this:

<startdate>2002-05-30T09:30:10Z</startdate>

404 - Page not found

soap でやり取りしてる datetime 型が、送信した時刻から9時間ずれて送信されるーー、という事象。

実はずれているのではなく、末尾に 'Z' が付与されている場合、GMTタイムゾーンとして取り扱われているだけ。

特に難しい話ではなさそうなのだが、時にややこしい。

<birthday xsi:type="xsd:dateTime">1971-02-01T15:00:00.000Z</birthday>

この人は、JST では 2月2日が誕生日。だけど、datetime 型でそれを送信する場合、年月日情報に単純に時分秒を0で埋めて、

1971-02-01 00:00:00

JST で設定すると、soap では、GMT(1971-02-01 15:00) で送信される場合がある。二つは同じ意味なので何の問題も無いのだが、timezone の認識が無いとハマる原因になる。

「誕生日」や「カード有効期限」なんかの時分秒までの精度が無い情報は文字列として最初から取り扱ったほうが安全そうだ。


で、疑問点。タイムゾーンの指定(Z とか、-9:00 とか)は optional のようだが、この指定をしない場合、そのデータは GMT として扱われるのだろうか?実装依存なのか、XML Schema で定められているのか、今のところ見つけられていない。

2010-04-07

java で chmod とか使うための 6 つの方法

Not Found

より、

システムコールを使う

    String fileName = "/path/to/file", 
    Process proc = Runtime.getRuntime().exec("chmod 755 " + fileName);

JNA を使う。

JDK1.4 以上であれば、上記の代替として JNA が使える。

    import com.sun.jna.Library;
    import com.sun.jna.Native;
     
    public class ChmodTest {
        private static LinkedOSLibrary linkedLibrary = 
            (LinkedOSLibrary ) Native.loadLibrary("c", LinkedOSLibrary.class);
     
        public static void main(String[] args) {
            linkedLibrary.chmod("/path/to/file", 0755);
        }
    }
     
    interface LinkedOSLibrary extends Library {
        public int chmod(String path, int mode);
    }

JTux を使う

Unix コマンドのラッパライブラリとして JTux(Java To UNix)というのがある。ほとんどの Unix コマンドをラップしている。

    UFile.chmod("/path/to/file/", 0775);

java.io.File を使う。(ただし、Java6 以上)

Java6 以降であれば、java.io.File に setReadable、setWriteable、setExecutable の3つのメソッドが追加されている。ファイルの rwx だけは変更できるようになっている。これ以外のことは出来ないので、限定的な対応といえる。

NIO.2 と Java 7 を使う

JSR 203 が Java 7 の一部として実装されることが決まった。たぶんこれ使えばいい感じに解決する(のか?)

失われたライブラリ(The lost library)を使う

Xenon Soft という会社が、Javaunix という JTux に似たライブラリを昔作っていたが、もはや手に入らない。


以上。詳細は上記記事を参照してくださいませ。