centos7でunix domain socketが読めない
最近、goji(golang web framework)触り始めていて、
centos7のnginxからunix domain socket経由で、
gojiに繋ごうとしても繋がらなかった。
原因はすごい下らない単純な理由だったが、メモ。
※ちなみに、よくあるsocketファイルのuser/権限の話ではない。systemdの話
事象
nginxでdomain socketを指定してbrowserアクセスすると、以下エラー
- web上
502 Bag Gateway
- nginx の error log
connect() to unix:/tmp/go.sock failed (2: No such file or directory) while connecting to upstream, client: **.**.**.**, server: _, request: "GET / HTTP/1.1", upstream: "http://unix:/tmp/go.sock:/", host: "localhost:8080"
原因
/tmp配下にdomain socket置くのがよくないらしい
詳細
domain socketの記事でよく/tmp/***.sock経由で通信するものがあるが、
最近のfedora系はsecurityの都合上、/tmp経由のsocket通信を禁止してるらしい。
つい少し前のcentosでは/tmpでもdomain socket動いていた記憶があるのだが
いつの間にやら最近のcentosも、同じく/tmpのdomain socketはダメな様子。
nginx の起動ファイル
もう少し調べていくと、具体的にはcentos7のsystemd管理の話らしく、
nginxの以下の起動ファイルのPrivateTmp=trueによる挙動らしい。
# cat /etc/systemd/system/multi-user.target.wants/nginx.service [Unit] ・・・略・・・ [Service] ・・・略・・・ PrivateTmp=true [Install] ・・・略・・・
参考記事
- http://serverfault.com/questions/463993/nginx-unix-domain-socket-error
- http://www.torutk.com/projects/swe/wiki/Redmine%E3%82%92CentOS_7%E4%B8%8A%E3%81%A7%E5%8B%95%E3%81%8B%E3%81%99%E3%83%BCUnicorn%E3%81%A8Nginx%E7%B7%A8
- http://conecuh.com/2013/04/making-fedora-1-unicorn-and-nginx-work-together/
対応
参考記事に習って、
/tmpでなく、/runに
domain socket入れたら動いた
補足
ちなみに、/runに手動で追加したdirの内容は再起動するとなくなってしまうので、
以下の手順で、systemdからの登録が必要。
- 一時ファイル用の設定を追加
$ vim /etc/tmpfiles.d/my_app.conf # 以下、追加 d /var/run/my_app 0755 user_name user_name -
$ systemd-tmpfiles --create /etc/tmpfiles.d/my_app.conf $ systemctl daemon-reload
参考記事
ソース
goji
gojiはdocumentどこにあるかわからず(まだ全然ない?)
srcから辿って以下でdomain socket指定した。
goji.ServeListener(bind.Socket("/run/my_app/go.sock"))
nginx
いつものやつ。
upstream backend { server unix:/run/my_app/go.sock; } server { listen 80; server_name _; root /usr/share/nginx/html; location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_pass http://backend/; } }
varcharとtextの違い(mysql innodb)
mysqlの可変長文字列を扱う、varchar型とtext型の違いの話。
古い情報が混在していたので、ちょっと整理してメモ。
myisamの頃の話
- sizeが違う
- 行の中身がdataか(varchar)、dataへのポインタか(text)
- 参照挟むので、performanceの違いがあった(varcharが早い)
今 net でぐぐって、ひっかかる情報の大半がこの話。
最近のinnodbの話
- 最大sizeは一緒。64kb(但し、TINYTEXT型、MEDIUMTEXT型、LONGTEXT型は名前の通り違う)
- varcharもtextも、中身は同じ仕組み(BLOB field / off page column)
- 行にdata入れるのも、外部(overflow page)への参照にするのも、行フォーマット次第(row format)
- 5.6で行formatのdefault は COMPACT
- COMPACT : カラムの値が小さいとB treeにそのままデータ格納、768byte以上でoverflow page作る。5.0以降のdefaultで互換性維持の為、今もdefault
- 仕組み一緒なので、performanceも変わらないらしい
違い
type | 初期値 | 最大文字長 | 最大sizeの数の意味 |
---|---|---|---|
varchar | 指定可 | 指定可 | 文字数で指定(日本語でも、最大65535文字まで入る) |
text | 指定不可 | 指定不可 | byteで指定(1文字3byteのutf8で日本語入れたら65535 の 1/3文字 入る) |
※他、sql標準規格に含まれるか?(=varchar)含まれず独自拡張か?(=text)という違いもある
結論
- ほぼ、varchar一択で良いのでは。
- text型のメリットは、varchar以上のsizeを入れる型もある事(MEDIUMTEXT/LONGTEXT)と、型で最大文字長が明示できる点?(TINY/MEDIUM...etc)。普通に使う分には要らない。
- ちなみに、どちらにせよ、innodbは8kbの壁と言われる行サイズの制限にひっかかる可能性がある。その時は、まずは行formatをcompressかdynamicに
参考
androidのcanvasのCORSが動かない
経緯
canvasを画像に変換したかった。(toDataURL)
しかし、canvas内の画像をCDN経由にすると、
後述のとおり、ブラウザのsecrity policyにひっかかり画像に変換できない。
そこで、Cross Origin Resource Sharing(CORS)を使って、これを回避したかった。
これは、そのメモ。
結論
先に結論を書いておくと、androidだけ無理だったので諦めた。
canvasでの画像変換でのCORS対応は、まだまだ未整備な感じ。
ブラウザのsame origin policy
ブラウザには、same origin policy 同一生成元ポリシーというルール(RFC)がある。
これは、
- 同じprotocol
- 同じポート
- 同じホスト
ではない、ページ間の操作やアクセスを制限するというもの
xhrやiframeなど、ブラウザの幾つかの機能で、上記の制約が入っているが、
その中に、canvasもこの制約が含まれている。
canvasでのsame origin policy
canvasは、toDataURL()をすると、
canvasの内容を画像データ(base64のdataスキーマuri)に変換できる。
この時、documentと異なるhostから取得した画像をcanvasに入れていると、
ブラウザのsame origin policyに抵触してしまい、
canvasが汚染(taint)して、画像に変換する事ができない。
コンソールにエラーが出てくる。
回避するには
回避するには、
- Reverse Proxy
- CORS
といった、やり方があるが、
わざわざこれだけのために、Reverse Proxy組みたくないので、
CORS使う事が一般的。
CORS
CORSは、Cross Origin Resource Sharingの事。
異なるホストのURLを事前に教えてこの制約から特別に回避してしまおうという話。
サーバー側と、クライアント側と両方に対応が必要。
以下、今回の、canvasの画像変換に限って書くと、
CORS サーバー対応
例えば、documentはくhttp://nantoka-host-aと、
その画像をはく、http://nantoka-host-bがあったとして、
画像の方のレスポンスのヘッダーに、
Access-Control-Allow-Origin: *
を追加する。(* がワイルドカード。ここに、host入れる)
他、幾つか、ヘッダがある。
CORS クライアント側対応
画像を追加する時に、crossOrigin属性を指定すれば良い。
var img = new Image(); img.src = “http://nantoka-host-b” img.crossOrigin = “Anonymous”;
結果
androidとCORS
一応、caniuse見ても、android端末は古くからCORS対応されている事になっている。
ところが、2.3系、4.x系の端末で、
サーバー側のレスポンスヘッダー微調整したり、クライアント側の記述もいろいろ微調整して、
試行錯誤してみたが、結局、ずっと、以下のエラーが出る。
DOM Exception: SECURITY_ERR (18)
androidのcanvasのCORSは機能していないようにみえる。
※全端末ではないかもしれないが、少なくとも、自分が見た端末は動かなかった。
stack over flow
stack over flow見てみると、やっぱり、皆動いてない。
ちなみに、自分の場合、はじめ古いios(5だったと思う)も動かなかったが、
Access-Control-Allow-MethodsとAccess-Control-Allow-Headersを追加したら、
とりあえず、古いiosも動くようになった。
androidとbase64?
ググると、androidは、画像をxhr経由のblob(android2は無理なのだが)で取得して、
それをbase64に変換すると、policy突破できるような記述があり、
試してみると、確かに動く!
のだが、これ、実は、NGらしい。
same origin policyは、uriスキーマの違いもチェックしているので、
documentのhostにあたる、httpと、base64画像の、data uri schemeは
異なるスキーマなので、仕様上は、NGにしなくてはいけないらしい。
これをちゃんと実装しているのが、chromeらしく、それ以外の多くが実装されていないみたい。
確かに同じソースをandroidのchromeで見ると、エラーになった。
chromeでエラーになる時点でOUTで、デフォルトのブラウザもいつ実装変わるのかわからないので、諦めた。
結局
androidの問題あるので、CORS諦めて、
documentと同じhostから画像をとるように妥協した。
但し、当然、そこだけ負荷かかるので、
ページの作り工夫することにした。
(本当に必要な時だけ、documentから画像を取得したい。。。)
createjs,canvasでハマるところ2014
経緯
先日、初めてcreatejs使ったスマホ向けwebアプリ作ってリリースした。
まあ、予想通り、createjs、canvasにいろいろハマった。
はまったところは、gistにメモしておいたので、ここにも整理して乗っけておく。
なお、類似blog記事多数あり、俺もほとんど8割位それらの記事で助かりました。
ここで、参考にlink貼った記事書かれた方々に感謝します。
そして、次にcreatejs使う人のために、
既出の物、あまり他の記事に見ない物も、まとめて書いておきます。
参考までに。
概要
- 以下の現象の原因と対応について書いていきます
タッチイベントがずれる
- 現象
- タッチした時、実際のタッチした箇所と反応している箇所にズレがあった
- 原因
- 対応
- 全体にかかっているズーム率を取得。その後、canvasに対して以下スタイルをあてる
- zoom: 1 / ズーム率
- transform-origin: top left
- transform: scale(ズーム率, ズーム率)
- 参考
staging環境で画像click時にエラーに
retinaでcanvasがぼやける
if (window.devicePixelRatio) { var height = canvas.getAttribute('height'); var width = canvas.getAttribute('width'); canvas.setAttribute('width', Math.round(width * window.devicePixelRatio)); canvas.setAttribute('height', Math.round( height * window.devicePixelRatio)); canvas.style.width = width+"px"; canvas.style.height = height+"px"; stage.scaleX = stage.scaleY = window.devicePixelRatio; }
(android)canvasが2つ出てきた
- 現象
- 原因
- 対応
- 親要素のoverflow(or overflow-x):hiddenをvisibleにして解決
- 不都合あれば、DOMを調整しよう。
(android)でcanvasに1clickすると2clickした事になってる
- 現象
- createjsのtouch enableつけて、androidの一部の機種に悪影響
- 原因
- どうやら、タッチした時に、touchstartと、mousedownもfireしてるっぽい。
- androidの一部端末に見られた。(galaxy系とか)
- 対策
(android)特定の条件で、eventに対して意図しないオブジェクトが反応してしまう
- 現象
- 原因
- 対象objの上に別のobjを重ねてtweenアニメしていたのが原因で、元の対象objまでevent callできなくなってる様子
- 普通にcreatejsのバグっぽい
- 対応
- 今回の場合、たまたまanimeしてるobjはtouchする必要がなかったので、animeしてるobjにmouseEnabled = falseすると、解決
(android) 古い端末でcanvasが重すぎる
(android)一部の端末でcanvasではじめに描画した画像の残像が残って画面が崩れる
- 現象
- 原因
- 描画についてこれていないっぽい
- 対応
// android4.1と4.2の時だけ、毎回のupdate()で、以下。 this.canvas.style.visibility = 'hidden'; this.canvas.offsetHeight; this.canvas.style.visibility = 'inherit';
(iOS)iphone4をios7にした端末で、なぜか一部タッチできない
- 現象
- 基本的に、iphoneでは、殆ど問題なく動く
- ところが、iphone4をios7にupdateした端末だけタッチが効かなくなった。
- 原因
- 対応
- 上記一個目のページの下部にあるcacheを追記したら、確かにうまくいった!
結論
- やっぱり、androidで苦労したなーという印象。
以上。
isucon4予選やってきた
isucon
isucon4予選やった。
言語は、せっかくの機会なので勉強して、Goで。
初めのscoreは1223点で、
最終的に、26631点まで伸ばして、2日目の17位で終わった。
つまり、予選通過ならず、敗退してしまった。
ここまでやった事でlog等から思い出せるだけを記録に残す。
事前準備
- 予選問題をやった
- ネットにころがってる、有り難い記事を読んでた(LINEの夏期講習完全版とか、関係者のまとめとか)
- isuconを良い機会に、golangの勉強した
- 参加メンバーの役割分担した。(皆がやる事分からないと混乱するので、大体何をするべきかエクセルにまとめた)
- gitbucket準備した
- 一日の流れを決めた
- 午前中に最低限のinstallと設定と各種指標の調査計測を行って、
- お昼にTODOを効果とリスク書いて整理して、
- 午後にTODOを効果順につぶしていく。
| TODO内容 | 効果 | リスク | 担当 |
みたいな感じ
予定していた構成
- 過去の問題から、こんなイメージをしていた
- front
- varnichかnginxでcache
- ※今時のサイトは画像とか絶対あるし、frontのcache周りが重要になるような気がしていた。
- backend
- nginx + Go(unix domain socket繋ぐ)
- ※今迄のように生Go(with gorilla)の想定で、なんとなく心の奥底でmartiniかgin出るよ〜と言われてる気がしていたが、封じ込めていた。
- DB
実際の構成
- 結局真っ裸でtableも少ないweb appliだった。
- KVS入ってなくて(これは独自で入れた方が良かったが、結局、私たちは入れなかった)
- goはmartiniだった。(今後、参考にさせてもらいます。)
- あと、front周りは静的fileが非常に少なかった。これが分かっていた時点で、早く、皆でbackendに注力するべきだったなー。
- 初めからnginxだった。apacheをnginxにするだけでscore稼ぎみたいな事は出来なかった。
当日の朝
- score算出プログラムを読もうとしたが、見当たらない。go binaryだけ?っぽく断念。
- supervisordでGoに切り替えるのだが、どうやら、うまくいかない。
- nginxの設定空っぽだったので、とりあえず最低限の設定した
- worker_procesとかworker_connectionとかgzipとかepolとかsendfileとかそういうヤツ
- /etc/my.cnfも基本的な設定を実施。slow queryとか仕込んで、innotopとpercona tool入れた。
- でも、結局、mysqldumpslow/show process listしか、まともに使ってないな、そういえば。
domain socket繋ぎ
- httpやtcp経由でnginx繋いだりmysql繋いだりしてると、3way hand shakeやフロー/輻輳制御する分コストかかるので、unix domain socketに変えていった
- ただ、localhost内での話なので、scoreへの貢献は少なかったかもしれない
- Goからnginx とのdomain socket
//http.ListenAndServe(":8080", m) l,err := net.Listen("unix", "/tmp/go.sock") if err != nil { fmt.Printf("%s\n", err) return } sigc := make(chan os.Signal, 1) signal.Notify(sigc, os.Interrupt, os.Kill, syscall.SIGTERM) go func(c chan os.Signal){ sig := <- c log.Printf("Caught signal %s: shutting down.", sig) l.Close() os.Exit(0) }(sigc) err = http.Serve(l, m) if err != nil { panic(err) }
- nginx側もsocketに対しての権限が必要で、Go側で権限を変えるコード書いてみたが動かなかったので、結局、supervisordからGoを実行するUserをnginxユーザーに変えた(権限でどこかのdir等ひっかかると思ったら、それで特に問題なかった)
- goから繋ぐmysqlもtcpをunix domain socketに変更
benchトラブル
- この辺りでbenchmarkプログラムからエラーが出るようになった
その1
type:fail reason:init script failed log:exit status 1 message:Do not run benchmark
- 何これ?
- benchmarkで使ってるinit.shでエラーになってて、中身を見ると、単に外部からtsvをimportしてるだけだった
- 結局、一度に大量のデータ送られて困っているようで、以下/etc/my.cnfに書いたら解決した
max_allowed_packet=300M
その2
- 次にこんな事言われた
02:47:40 type:fail reason:Get http://localhost/: dial tcp: lookup localhost: too many open files method:GET uri:/
- 確かこれは、いろんな所でfile descriptor上げると解決したと思う
その3
- その次に更にこんな事言われた
01:31:07 type:fail reason:Connection timeout method:GET uri:/
- (もしかしたら、違うログだったかもしれないが)確か、これは、nginxがhost書き換えていたとかで、アプリ側で許可してるIPから外れてしまってエラーになっていたヤツだったと思う。
nginxの設定を見直して解決
ここら辺でお昼くらいになってた。気付けば。
お昼
- 一旦、サーバーをimageにして皆にmaster AMIとして共有した
- gitbucketも準備していたが、結局、AMIの共有で連携していた
- Master AMI作成して皆に共有
- 各自はmaster AMIを元につくった自分のinstanceで作業。うまくいけば、本番にも同じ適用
- この適用の時は一部gitbucket使ってたんだけど、んーー。必要だったかな?
- front任せてた人からgzipかけない方が良いといわれ外してもらった
- 今回のケースではstatic file少なく、gzipかける前後のsize差がないのに、変換costかかるからscore下がってるっぽかった。
index
- めっちゃ、遅かったが、ようやくベンチも動いてGoやnginxの基本構成も出来ていたので、ここでmysqldumpslowで遅いquery特定した
- 明らかにindex不足だった
- 弊社代表する優秀なエンジニア!にfrontやcache周り任せていたのだが、今回のシチュエーションだと殆ど活躍する機会が皆無で勿体ないので(というか申し訳ないので)、このmysql index周りをお願いした
- 結局、このindexが一番効いて、一気に1万の台に上がった
- なんというか、逆にあまり決めないで臨機応変な体制にしても良かったかもしれない。。。(ただ、そうすると、色々ぶつかりそうだったり、漏れがあったり...どうだろう。何がいいんだろう)
n+1問題
- 所謂n + 1問題(ORMでよくあるLoopで毎回SQL発行するやつ)も見事にあったので、おっしゃ俺やるぜ!と思って頑張った
- まあ、sqlは一個にまとめてprogramに適用したが、scoreに反映されず、あれ、と思ったらそもそも、このsqlを使っているのは、ルール上scoreに換算されない所だった!!!
- 見事に1時間くらい無駄にしてしまった><うーーん。。
- これ、もし罠的な意図無ければ、product codeに入れずに、score算出プログラム側でやってほしかったなーと思ったり
- そもそも俺がルールよくみないのがいけないですよね。これ実際の現場でもよくありますよね。仕様よくみないとね。
- 反省。
計測
- 初め見たときはCPUもmemoryもがら空き状態だった。
- nginxのconnection数やらGOのruntime.GOMAXPROCS(runtime.NumCPU())やらやってもCPU食ってくれない
- 結局、IO待ちが多くて、上のindex追加対応とマージするとCPUそこそこ使ってくれるようになった
- とはいえ、それでも確か8割位でLoadAverageも一桁で、まだまだ使い切れそう
- process はnginxが複数たってくれなかった。(1台で玉に2,3台でてくる程度)
- これも、index追加対応でIO待ち解消すると、ちゃんと複数あがってくれた。
- worker_process autoの時の話だが。あれ、そもそも、ここ、皆固定値入れてるの?
- あと、memoryが、超がら空きだったのが勿体なかった
- swapも当然ほとんど発生してない。
- 余裕有ればKVS入れて、Count処理とかcacheしても良かったなー。
- KVSといえば、今回のtable構成では、loginのtrackingしてる所があり、単純にinsertしてselectしてるだけなので、これをKVS(redisでsort済みとかね)に突っ込むのやりたかった。ただ、queryが割と柔軟に書かれていたので、この対応いちいち書き換えて行く作業時間が、残り時間に入るか不安で没に。
夕方
- /etc/my.cnf見直しをエンジニアAに依頼。ここは何をやったかあまり見てない
- あと、locked usersというreportも気になって見てもらった
benchmarkのエラー
- index追加して、nginx+Goの多重化を整理すると、またbenchmarkのエラーが出てきた
type:fail reason:Get http://localhost/: dial tcp 127.0.0.1:80: cannot assign requested address method:GET uri:/
- これ、多分、多くの出場者がひっかかっていたのでは?(井戸端でも誰か書いてた)
- 調べると、goのnet/httpのkeepalive周りの問題っぽい。 ※参考1/2
- nginxでkeepalive接続をoffにしたら、このエラーでなくなった。
- こういうのも、現場でよくありますよね。
benchmarkの調整
- 最後にベンチマークのworkaroundを幾つか指定して適性値を探した。
- ここら辺で2万くらいのscoreになってた
最後
- ぎりぎりになって、table設計の怪しそうな所を変えて試したが、score貢献なかった(varchar をintに、tinyint(4)を1にとか)
- あと、mysqlの余計なlogとかoffにしたり。
- マージしてマージして、と言っていたが、結局マージ反映全然出来てなくて最後少しバタバタした(何故か終了前にssh繋がらないとか、、、)
- 17:50くらいに最終score送信して、それで終了
感想
- 振り返ると、なんか、benchmark周りのエラーを除くのばっかやっていたような印象。
- メモリーが全然がら空きでmemcache/redisとか突っ込めば良かったなーと
- あと、初めに担当決め過ぎると、責任感の意識が働いて柔軟に動けず逆に良くなかったなーと
- なんか、17:50くらいで終わったので、皆で反省会やったけど、なんか暗い雰囲気になってしまったのも良くなかった!
- 反省会はお酒飲みながら明るくやらないとね!
- その後、hikarieのおしゃれなお店で酒飲みながら反省会しました。
次回
- 次回も参加したいっす。
Server-Sent Eventsまとめ。ハイパフォーマンスブラウザネットワーキング16章
まだ、社内でO'Reillyのハイパフォーマンスブラウザネットワーキングの読書会をやっていて、
自分が、16章のserver sent eventsやるので、その下書き。(前の資料もいつかblogにupする)
※ちなみに、書いてる事を単にまとめてるわけではないので、ご注意を。
ハイパフォーマンス ブラウザネットワーキング ―ネットワークアプリケーションのためのパフォーマンス最適化
- 作者: Ilya Grigorik,和田祐一郎,株式会社プログラミングシステム社
- 出版社/メーカー: オライリージャパン
- 発売日: 2014/05/16
- メディア: 大型本
- この商品を含むブログ (2件) を見る
16章 Server Sent Events
- よく言われるのがSNSのTimelineの更新とかで使える仕組み
- server sent eventsってwebsocketと被っている事もあって、中々目立たないですよね
server sent eventsの対応状況
- caniuse
- websocket同様androidとIEが非対応で足ひっぱってきたが
- androidは4.4から使える
- IEは11でも未だに「使えない」
- ググってもie使う兆しや噂も無い
- IE11βのfeedback面白かった
有名サイト
- ちょっと気になったので、
- 有名サイトでpush通知っぽい事をどういう技術で実現してるか、ざっくり調べてみた。
- 2014年8月9日の状況
- ざっくり見た感じなので、間違ってたらごめんなさい。
- Timeline:ajax polling(数十秒)
gmail
- ajax polling
- 定期的にmailのpreloadしてて(多分cacheしてそう)、そのtimingでメールあれば、別xhr飛ばして取得してきてる
github
- server sent events!!
- 別host(live.github.com)とSSEで繋いでて、push来たら、本hostに通常のxhrでgetしてるっぽい
利用例
- websocketも、server sent eventも、まだまだ珍しい状況。
- 結局、いずれもIE/android対応遅かったので多くの機器でpolyfilする必要があり、複雑化を恐れたためか?
- 今回ピックアップしてみた例の中では、server sent events利用してる所はgithub位だった。
実際、動かしてみる
- nodeの例(英語)を動かしてみる
- consoleでstreamを見てみよう。
- 参考
- 他に、express+redisの例やherokuの例もあった
sse
- client側
source = new EventSource("stream"); source.addEventListener("message", function(e){ // メッセージ表示処理 }, false);
sse
- server側
// これはimageで色々省略してます。 var reqListener = function(req, res){ res.writeHead(200, {"Content-Type":"text/event-stream"}); res.write("id: 1234"); res.write("data: some message"); } http.createServer(reqListener).listen(8888);
要するに
- front
- EventSourceをnewすると、引数のパスにGETして通信開始
- 後はevent bindingして処理を追記していく
- back
- responseのContentTypeに
text/event-stream
- 決まった書式でresponse返す(data: ***)
- responseのContentTypeに
Server-Sent Eventsの主要な要素
- EventSourceインタフェース
- DOMイベントとして取得できる
- EventStream
- 低レイテンシで単一接続で済む(consoleで確認してみよう)
- sseはxhr上のstreamingでバッファ肥大化しない(通常のxhrと違って、メモリに溜め込まず消去されるらしい)
再接続
- エラー時、自動再接続する機能
- 試すと、確かにclientが勝手に再接続した。(復帰迄5,6sec位かかった)
- 接続再開後、失われたメッセージの再配信する機能
- これは、Last-Event-IDヘッダーをclientから渡す仕組みは確かにあるが、(p274)
- それを見て、再送信させる云々はserver sideで自力で書かなくては行けない
polyfilライブラリ
- 幾つかある様子
- これとか
- このpolyfilで決定版みたいなlibraryが無い点は注意(websocketといえば、socket.ioみたいな定番がsseは無い)
制限と課題
- 制限
- 課題
- NW中間装置がstreamをcacheするかも。そこからレイテンシ増加/接続破壊を引き起こす可能性あるらしい
まとめ
digital oceanにspdy付きのnginx構築する
経緯
- spdyをちょっと試してみたい。
- digital ocean使って、spdy付きのnginx構築してみた。
- これは、そのメモ。
前提
nginxインストール
yum install wget gcc pcre-devel gd-devel perl cd /usr/local/src/ wget http://www.openssl.org/source/openssl-1.0.1h.tar.gz tar zxvf openssl-1.0.1h.tar.gz wget http://nginx.org/download/nginx-1.7.3.tar.gz tar zxvf nginx-1.7.3.tar.gz cd nginx-1.7.3 ./configure --with-http_ssl_module --with-http_spdy_module --with-openssl=../openssl-1.0.1h make make install
ssl証明書の作成
$ cd $HOME $ openssl genrsa -des3 -out certificate.key 2048 $ openssl req -new -key certificate.key -out certificate.csr $ cp certificate.key certificate.key.org $ openssl rsa -in certificate.key.org -out certificate.key $ openssl x509 -req -days 3650 -in certificate.csr -signkey certificate.key -out certificate.crt $ sudo mv certificate.* /usr/local/nginx/conf
nginxでspdy有効にする
vi /usr/local/nginx/conf/nginx.conf
- sslの設定のコメントを外して、幾つか追加変更する
# HTTPS server # server { listen 443 default ssl spdy; //★ここを追加 server_name _; //★ここも一応変えておいた ssl_certificate /usr/local/nginx/conf/certificate.crt; ssl_certificate_key /usr/local/nginx/conf/certificate.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; location / { root html; index index.html index.htm; } }
spdy indicatorを入れる
- spdy indicatorというchrome extension入れる
nginx起動して確認してみる
- nginx起動
/usr/local/nginx/sbin/nginx
参考
- hatyuki氏のブログ
- 基本的にこれをベースにversion等新しくした
- 公式からリンクあるspdy記事
install中のエラー
エラーでまくって、困ってる人のためにも残しておく
configureでのエラー
- 初めに、pcre-develとgd-devel(zlib)入れないとこんなエラーでる
./configure: error: the HTTP rewrite module requires the PCRE library.
./configure: error: the HTTP gzip module requires the zlib library.
makeでのエラー
- install時にwith-http_ssl_moduleオプション入れないとこんなエラーがでる
make: *** `default' に必要なターゲット `build' を make するルールがありません. 中止.
- perl入れてないと、makeでこんなエラー出る
You need Perl 5. make[1]: *** [../openssl-1.0.1h/.openssl/include/openssl/ssl.h] エラー 1 make[1]: ディレクトリ `/usr/local/src/nginx-1.7.3' から出ます make: *** [build] エラー 2