jsだけレスポンスヘッダで文字コードを設定する @Apache
Apacheでjsが文字化けした。
ファイルの文字コードも無茶苦茶だしApacheよくわかんないしあーあーしてたら先輩が解決してくれた、自力で見つけられなくて悔しかったから書いとく。
直接の原因はjsファイルはUTF-8だったのにレスポンスヘッダを見るとEUC-JPが指定されていたこと(PHPのファイルがEUC-JPだったから?
というわけでjsはUTF-8で開いてほしい → .htaccess
があったからそれにこう書いて終わり。
AddCharset utf-8 .js
今回言われるがままに .htaccess
に追記したけど積極的に使うべきものではないのかな↓↓
Apache チュートリアル: .htaccess ファイル - Apache HTTP サーバ バージョン 2.4
一般的に、サーバの主設定ファイルにアクセスできない場合を除いて、 .htaccess ファイルの使用は極力避けてください。
複数のユーザーがどうしても自分の好きに設定したいときに各人作るものらしい。
リクエストのたびに .htaccess
のファイル探すコストがかかるのと、ユーザーがwebサーバーの設定をいじくれる状態はよくないのと、というところだそう。
ネットワーク調査あれこれメモ①
会社でなんか変だぞーって調べてたときに打ったやつとか参考にした記事とか、何度か同じこと調べてるので残しておく。
誰の利にも別にならないことを書いておけるのは個人ブログの良いとこだと思う。
予定は無いけど②とか③とか生まれる気がするから①(YAGNI!!)
状態ごとの接続数
[hirapi@server ~]$ netstat -tan | awk '{print $6}' | sort | uniq -c 4 CLOSE_WAIT 88 ESTABLISHED 1 FIN_WAIT2 1 Foreign 12 LISTEN 2598 TIME_WAIT 1 established)
規定時間以上残っているTIME_WAIT
[hirapi@server ~]$ netstat -nato|egrep -c 'timewait. *\(0.00' 2001
半分以上わからなかったけどこちらのスライドありがたかった、kernel 3.Xだとうまく回収してくれないのね。。。
ついでにカーネルのバージョン確認は
[hirapi@server ~]$ cat /proc/version Linux version 2.6.32-358.el6.x86_64 (mockbuild@c6b8.bsys.dev.centos.org) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-3) (GCC) ) #1 SMP Fri Feb 22 00:31:26 UTC 2013 [hirapi@server ~]$ yum list installed | grep kernel dracut-kernel.noarch 004-409.el6_8.2 @updates kernel.x86_64 2.6.32-358.el6 @anaconda-CentOS-201303020151.x86_64/6.4 kernel.x86_64 2.6.32-696.18.7.el6 @updates kernel-devel.x86_64 2.6.32-642.4.2.el6 @updates kernel-devel.x86_64 2.6.32-696.18.7.el6 @updates kernel-firmware.noarch 2.6.32-696.18.7.el6 @updates kernel-headers.x86_64 2.6.32-696.18.7.el6 @updates
(開発環境だから……)
recycleとreuse
net.ipv4.tcp_tw_recycle は廃止されました ― その危険性を理解する - Qiita
ロードバランサの配下にある通信ではパケットに振られるタイムスタンプ(の前後関係)が実時間と一致しているかわからないため、タイムスタンプで新旧を判断するrecycleを有効にすると意図しない切断が起こる可能性がある、とのこと?
TCP関連のカーネルの設定ファイル
/etc/sysctl.conf
変更はこれ書き換えてから # sysctl -p
ローカルポートを広げる
接続数多すぎてなんか止まっちゃった、という時はローカルポートを使い切っている可能性を疑う。変更は↑↑の設定ファイルのここ
net.ipv4.ip_local_port_range = 20000 65500
ローカルポートを食いつぶしていた話 - ダウンロードたけし(寅年)の日記
サーバーとかネットワークとかぜんぜんわからずにアプリケーション書くと最後はこういうとこで詰まってお手上げになる。
平気で6万回もMySQLサーバーに繋ぐ画面なんて作らないでよ過去の人……。
とはいえちょっとだけ低レイヤー(?)に興味を持てた、Linuxとかネットワークとかちょこちょこ読書中。
redashの入力フォームで「特定の値 -> 無指定」として扱いたいときのSQL
こんなテーブルがあったとして、
mysql> SELECT * FROM users; +----+-----------+------+----------+ | id | name | age | group_id | +----+-----------+------+----------+ | 1 | hirapi | 25 | 1 | | 2 | someone | 100 | 1 | | 3 | young man | 6 | 2 | +----+-----------+------+----------+
redashの入力フォームに「対象グループID」を入力して、そのグループの人の名前を取ってきたいとする。
redashは {{フォーム名}}
で入力値を取れるので、普通に書くと
SELECT name FROM users WHERE group_id = {{対象グループID}}
となる。
ここで、例えば「グループ関係無くみんなの名前も取れるようにしたい、クエリは分けたくない」みたいなこと言われたら、
「入力フォームに 0
を入れたらグループ無指定ということで全員の名前を取ってくる」というのはどうだろうということになる。
pythonでif文はさんでクエリ作るのもアリといえばアリだけど面倒くさいなあと思った結果↓↓
SELECT name FROM users WHERE {{対象グループID}} = 0 OR group_id = {{対象グループID}}
対象グループID
が0だったら
mysql> SELECT name FROM users WHERE 0 = 0 OR group_id = 0; +-----------+ | name | +-----------+ | hirapi | | someone | | young man | +-----------+
対象グループID
が1だったら
mysql> SELECT name FROM users WHERE 1 = 0 OR group_id = 1; +---------+ | name | +---------+ | hirapi | | someone | +---------+
クエリチューニングの面から見たら良くないかもしれないけどさくっと作れたし今回はおっけー。
別にredashに限った話ではないけど入力値をそのままクエリに突っ込むのがredashくらいしかなかった。
Prestoで配列の要素数を取得する
6.15. Array Functions and Operators — Presto 0.195 Documentation
cardinality(x) → bigint
Returns the cardinality (size) of the array x.
countとかsizeとかかなあと思ってたら違った、カーディナリティか……
PHPでTreasure Dataにpost2()
会社でTreasure Dataを使ってログの蓄積・集計をしていて、PHPからTreasure Dataにレコードを送ることがある。
そういうときはこのライブラリを使う↓↓
今まではこのREADMEにあるUsageのとおりこんな感じで送ってた↓↓
<?php require_once __DIR__.'/vendor/autoload.php'; use Fluent\Logger\FluentLogger; $logger = new FluentLogger("localhost","24224"); $logger->post("debug.test",array("hello"=>"world"));
ただこの間ちょっとレコード多くなるかもだから集計時間短くなるようにしたいなということがあって、こちらのブログを参考にtimeカラムに ID × 3600
みたいな任意の値を入れたくなった。
やってみて気づいたんだけど、こういう配列を前述の例のように post()
に渡してもtimeカラムにはunixtimeが入ってしまう。
<?php require_once __DIR__.'/vendor/autoload.php'; use Fluent\Logger\FluentLogger; $logger = new FluentLogger("localhost","24224"); $logger->post("debug.test",array("time"=>7200)); // => timeカラムには普通に呼び出し時のunixtimeが入る
GitHubで post() のところを追ってみたところ、timeカラムの値は別途自動で入れられるらしい。
じゃあこのライブラリではtimeカラムに好きな値を入れられないかというと、そういうわけではない。
ここで post2()の出番。
冗談みたいな名前してるけどpublicなメソッド。
post()
にはタグと配列を渡すけど、 post2()
にはEntityクラスのインスタンスを渡す。
post()
も中身を見たら同じことをやっている。
Entityクラスのコンストラクタを見ると、第三引数にtimeっぽい値を渡せるとのこと。
post()
の中身ではここに何も渡してないからデフォルトでnullになって、結果Entityオブジェクトのtimeプロパティにそのときの時刻が入る、というだけらしい。
というわけで自分でEntityクラスのインスタンスを作って post2()
に渡してあげるとtimeカラムにちゃんとその値が入る。
<?php require_once __DIR__.'/vendor/autoload.php'; use Fluent\Logger\FluentLogger; use Fluent\Logger\Entity; $logger = new FluentLogger("localhost","24224"); $entity = new Entity("debug.test",array("hello"=>"world"), 7200); // 第三引数にtimeカラムの値 $logger->post2($entity); // => timeカラムに7200が入る
レビューで先輩に教えてもらったとき何だその名前、と思ったけど合ってる。
どういう名前をつけるのがいいのかなあとちょっとだけ考えてみたけど、そもそもなんで送信用のメソッドを2つ作ったのかにもよるのかもしれない?
名前にちょっとだけウケたから投稿してみた。
Hanami公式入門ガイド日本語訳【5】Getting Started(4)
http://hanamirb.org/guides/1.1/getting-started/#writing-our-first-test
初めてのテストを書く
ブラウザでアプリケーションを開いたときに最初に目にする画面は、ルーティングが何も定義されていないときに表示されるデフォルトページです。
HanamiはWebアプリケーション開発手法としてビヘイビア駆動開発(BDD)を推奨しています。
最初の自作の画面を表示させるために、高次元の機能テストを書きましょう:
# spec/web/features/visit_home_spec.rb require 'features_helper' describe 'Visit home' do it 'is successful' do visit '/' page.body.must_include('Bookshelf') end end
注意してほしいのは、Hanamiは最初からBDDの開発フローをサポートしていますが、特定のテスト用フレームワークに縛られているわけでもなければ、特別な統合システムやライブラリを備えているわけでもありません。
ここではMinitest(デフォルト)を使っていきますが、プロジェクトを作る際に --test=rspec
オプションをつけることでRSpecを使うこともできます。
そうすればHanamiはRSpecのためのヘルパーやスタブのファイルを生成します。
(※ データベースのURLを微調整する必要があるときは .env.test
を確認してください)
このコマンドを実行して、テスト用のデータベースにスキーマをマイグレーションしなければなりません:
% HANAMI_ENV=test bundle exec hanami db prepare
見ての通り、コマンドを実行する環境を指定するには環境変数 HANAMI_ENV
をセットします。
リクエストを受ける
今テストを実行すると、失敗することがわかります:
% bundle exec rake test Run options: --seed 44759 # Running: F Finished in 0.018611s, 53.7305 runs/s, 53.7305 assertions/s. 1) Failure: Homepage#test_0001_is successful [/Users/hanami/bookshelf/spec/web/features/visit_home_spec.rb:6]: Expected "<!DOCTYPE html>\n<html>\n <head>\n <title>Not Found</title>\n </head>\n <body>\n <h1>Not Found</h1>\n </body>\n</html>\n" to include "Bookshelf". 1 runs, 1 assertions, 1 failures, 0 errors, 0 skips
それではこのテストを通しましょう。
そのために必要な必要なコードをひとつずつ書き足していきましょう。
初めに足すのはルーティングです:
# apps/web/config/routes.rb root to: 'home#index'
アプリケーションのルートを home
コントローラの index
アクションに指定しました(詳しくはルーティングの解説を見てください)。
次にindexアクションを作ります。
# apps/web/controllers/home/index.rb module Web::Controllers::Home class Index include Web::Action def call(params) end end end
これは何のビジネスロジックも実行しない空のアクションです。
それぞれのアクションには対応するビューがあり、ビューはRubyのオブジェクトであり、リクエストを満たすために追加する必要があります。
# apps/web/views/home/index.rb module Web::View::Home class Index include Web::View end end
アクションと同様にこのビューも空であり、テンプレートをレンダリングするだけです。
これが、テストを通すために編集する必要のあるファイルです。
先頭に "bookshelf" と追加するだけです。
# apps/web/templates/home/index.html.erb <h1>Bookshelf</h1>
変更を保存し、テストをまた走らせてください。そうすると今度は通ります。
やったね!
Run options: --seed 19286 # Running: . Finished in 0.011854s, 84.3600 runs/s, 168.7200 assertions/s. 1 runs, 2 assertions, 0 failures, 0 errors, 0 skips
Hanami公式入門ガイド日本語訳【4】Getting Started(3)
http://hanamirb.org/guides/1.1/getting-started/#hanami-architecture
Hanamiのアーキテクチャ
Hanamiのアーキテクチャでは、同じRubyのプロセスで別々のHanamiアプリケーション(とRackアプリケーション)をホストすることができます。
これらのアプリケーションは /apps
以下にあります。
各アプリケーションが、ユーザー向けのWebページや管理画面、メトリクス、HTTP APIなどととしてプロダクトを構成することができます。
これらのパーツは、lib
以下にあるビジネスロジックに対する 分娩機構 (訳註:原文では" delivery mechanism ")です。
ここは、Modelが定義され、相互作用してプロダクトが提供する機能を構成するディレクトリです。
Hanamiのアーキテクチャはクリーンアーキテクチャに強く影響を受けています。