DjangoにHEADメソッドを投げてもGETの処理が走ってしまう

以前勤めていた会社で管理していたポータルサイトで、クローラーがHEADでページを要求しているのにDBの負荷が上がって不思議に思い調べたらこのような実装になっていた。

その時調べたときはこの記事をみただけで(バージョンが違うけどどうせ処理は同じでしょ)と思い終わりにしていたけど、今回はソースも確認する。

blog.hirokiky.org

Version:2.2.6

def view(request, *args, **kwargs):
    self = cls(**initkwargs)
    if hasattr(self, 'get') and not hasattr(self, 'head'):
        self.head = self.get
        # 省略
    return self.dispatch(request, *args, **kwargs)

https://github.com/django/django/blob/2.2.6/django/views/generic/base.py#L63

やっぱり変わっていないですね、とりあえずDjangoソースコードを追う機会ができて楽しかったです。

Shizuoka.phpに参加しました

Shizuoka.phpに参加してきました。

モダンなPHPを知りたかったのと、デザイナーがやってるWordPress案件をより効率よく行う何かが1つでも知れれば御の字と思って参加しました。

一番の目的はHaskellおじさんに会う事だったのは秘密です。

感想

polidogさんの求心力のおかげで、東京で働いている方達も来て非常に面白い内容を話してくれました。

PHPを書く機会は無いかもしれませんが、次回も是非参加したいです。

面白いと思った内容

聞いた内容をもとに書いたメモを置いておきます

モダンなPHPを学ぶ方法

The Right Wayから学ぼう

コーディング規約

PEPのような規約がある * PSR1 * コーディング規約 * PSR2 * スタイルガイド * PSR4 * オートローディングスタンダード

phpcsを利用すればエディタにPSRを適用できるよ。

php-cs-fixerを利用すればCIとかに適用できるから便利

依存関係管理

  • 時代はcomopser、PEARは古い
  • パッケージを探したいならpackagistを利用しよう
  • Security Advisories Checkerを利用するとライブラリの脆弱性確認をして新しいバージョンがあれば教えてくれる

DI

アンチパターンのサービスロケーターパターンも一緒に覚えておくべき

テスト

デプロイ

PHP専門のデプロイツールDeployerが良いらしい

最近VueとかのSPA流行ってるけど実際どうなの?

  • 最近はもっぱらSPAでやってるよ
  • ログイン関係は怖いからクッキー使ってやりたいからそこだけはバックエンドで書くとかはよくやる

今後のphpはもっと便利になるよ系

WordPressのadd_filterで追加した無名関数を消す方法

ここ数ヶ月WordPressの案件のヘルプに入っていた。

緯度経度を使って現在地から近い順で並び替えたい要望があり実装、アクセス数の都合上GoogleMapAPIは使えなかったのでDBに処理を書くことにした。

そこで、タイトルに書いた問題が発生した、ググると日本語の記事がまだ見つからなかったので社内で共有した殴り書きを流用。

WordPressが初めてでディープなところに踏み込めたのは意外と嬉しかった。

WordPressでクエリの投げる直前に、任意のクエリを埋め込む時に使用するフック関数

add_filter('posts_join', 'add_query_join_lat');

これだと任意の引数が渡せない、解決するには現状思いつくのが無名関数を渡しスコープ外の変数を渡す方法

add_filter('posts_fields', function ($fields) use ($lat, $lng) {
    $km = 6371;
    $mile = 3959;
    $latlng_distance = ",(
        $km * acos(
            cos(radians($lat))
            * cos(radians(META_KEY_LAT.meta_value))
            * cos(radians(META_KEY_LNG.meta_value) - radians($lng))
            + sin(radians($lat))
            * sin(radians(META_KEY_LAT.meta_value))
        )
    ) AS distance";
    $fields .= $latlng_distance;
    return $fields;
});

このフック関数の悪い所は、addしたら全てのクエリ発行の時にこのフックが走ってしまうところで、解除するにはこんな感じで解除したい関数名を書く必要がある。

remove_filter('posts_join', 'add_query_join_lat');

ここで問題が発生、無名関数は名前がないから削除できない。

一度無名関数を変数に格納してやればいけるんじゃ?と思いやってみたが、変数に無名関数を渡しただけで名前はついていないのでやっぱり消せない。

$hoge = function() {echo 1;}

add_filter('posts_join', $hoge);

remove_filter('posts_join', "hoge");

ググってたらやっぱり同じ問題にぶち当たっている外人が沢山いた、結局使ったのがこれ。

https://stackoverflow.com/a/48480358

これだとプラグインで使用している無名関数も消えてしまうので、フックした関数名、無名関数で利用した引数の名前をチェックして削除するように改善

global $wp_filter;

foreach ($wp_filter as $filter_name => $filter_properties) {
    if($filter_name === "posts_fields") {
        foreach ($filter_properties->callbacks as $priority) {
            foreach($priority as $function) {
                if(is_object($function["function"]) == true) {
                    $tmp_function = new ReflectionFunction($function["function"]);

                    $static_keys = array_keys($tmp_function->getStaticVariables()); // useで指定した$lat, $lngが格納されている
                    $parameter_keys = array_keys($tmp_function->getParameters()); // 関数で使用する引数が格納されている
                    
                    $is_distance_function = (in_array('lat', $static_keys) && in_array('lng', $static_keys)) && in_array('fields', $parameter_keys);
                    
                    if($is_distance_function) unset($wp_filter[$filter_name]);
                }
            }
        }
    }
}

Yahoo! JAPN Tech Conference 2019 を見に行った

感想

全部Bを聞いた

はじめに感想を述べると AWS, GCP, Azure等のフルマネージドなサービスを自前で作ってるぞ! を感じた。

どのサービスもデータレイク的な考え方をしているように感じた(ていうか多分言ってた)。

CassandraとRedisを使い分けているように感じた。詳しく調べてみたい。

ライブ動画配信サービス「ワイキュー」の作り方 〜優れた社内技術で実現する、少人数のサービス開発〜

フロントエンドの人の話

フロントの人はフロントの事だけやっている、きちんと分業している。

それはなぜかというと、パブリッククラウドを使うような感覚でバックエンド側が利用できるから。

ここでRedisがマネージドサービスとして利用できると知った。

基本ステートレスだから、弊社でも運用できたりするかもしれない。と思った。

豊かなスポーツライフの実現を目指す、スポーツナビのシステムアーキテクチャ

各競技用DBを利用しているが、今後は汎用競技用DBを利用していくらしい。

そうすると、新しいく人気が出てきた競技のためにDBを設計して...がなくなり、表示側で頑張って出せば早くユーザーに情報を届けることができる。

負荷に応じてChefを利用してスケールしている。

失礼だけど、全部コンテナベースになっていないと分かり、少し安心した。

ただこれからコンテナベースにしていくと話していた。

Kubernetesで実現したYahoo! JAPANの次世代開発環境 ~ 100以上のクラスタを少人数で運用する秘訣 ~

Kubernetes-as-a-Service作りましたの話。

k8s聞いたことあるって人向け

Open stackを利用している。

クラスタの作成部分を1コマンド、GUIで1クリックでできるようにした。

クラスタの復旧は自動で行うようにした。

無停止クラスタアップデートも1コマンドでやる。

コンテナ監視用コンテナ、ログ収集用コンテナ等の汎用的に使用できるコンテナは、共有化できるようにした。

アドオンとして使えるようにした。

これをきいて、やっぱりRamcherとかが必要だと感じた。

他に良いのがあればそっちを使うようにする。調べる必要あり。

Yahoo! JAPANの巨大インフラの運用と展望

これはレイアが低すぎて難しすぎたので、気になった単語だけ。

ほぼ全てをOpenstackを利用している。

Openstack on Kubernetes

複数のOpen stackを管理することを考えならがCI/CDするのむずい

IIJ mio から UQモバイルへmnpした

日経ネットワークにmvnoの下り速度の比較表があり、Y!mobileUQモバイルが群を抜いて早かったのでmnpしました。 結果、かなり早くなりました。

パケットが勿体無いので少ししか検証してませんが。

朝の通勤時間帯や比較的快適な時間で

IIJ: 10Mbps前後 UQ: 40~50Mbps

18時~19時が

IIJ: 1Mbps前後

UQ: 10~20Mbps

4倍から10倍程速度に差が出る結果になりました。 なんと言っても1Mbpsしか出ない時間帯は何をするにもストレスが溜まり、テザリングでパッケージ等のダウンロードなんてやった日には、いつ返ってくるか分からない状況だったので幸せです☺️

それと、UQはフルmvnoなので(あってるよね?)、mnp申請した後もIIJで通信でき、UQから実際にsimが届いた後、webで回線切り替えボタンを押せば良い形だったので、今の生活スタイルでも無理なく回線切り替え出来たのが非常に助かりました。

Google Colaboratoryが凄い

スタンドアロンなjupyter notebook, jupyter labを探していたら見つけてしまいました。

普通にjupyter notebookとして使用できるだけでなく、後ろで動いているインスタンスにはNVIDIAGPU Tesla K80が付いています。

若干癖があるみたいですが、Google Driveないのファイルと連携もできる。

GCPのGCSも連携可能。

初めて機械学習やりたい場合Google Colaboratoryを使えば、初期投資0円で強いGPUで始められる。凄い...

こんな感じで環境も安くスケールを大きくできる

  • とりあえず機械学習を触る👊🏼
  • Google Driveに課金し、よりでかいデータを触る👍🏼
  • データが100GB以上になるのなら、GCSへ移行しスケールしやすくする✌🏼
  • 火力が欲しくなったら、無料インスタンスを捨てGCEへ移行しより高みへ🙏🏼

cronでtimezoneごとに実行

日本語以外の言語をサポートしてるシステムで、cronを使って通知を送りたいけど、JSTで送ってしまうと深夜の時間帯に送ってしまうことになりかねないよね。

ってことで、cronをタイムゾーンごとに実行できないか調べていたら見つけたので簡単に書いてみた。

これを使います。 github.com

コード

var CronJob = require('cron').CronJob;

new CronJob('0 19 * * *', function() {
    console.log("東京は夜の七時");
}, null, true, "Asia/Tokyo");

new CronJob('0 7 * * *', function() {
    console.log("リオは朝の七時");
}, null, true, "America/Sao_Paulo");

時間を弄ってすぐ実行されるようにする

# date -s "07/2 18:59:55 2018"
2018年  7月  2日 月曜日 18:59:55 JST

起動

# nodejs cron.js
東京は夜の七時
リオは朝の七時

良い感じ、本当はpythonで似たようなのが欲しいけどもすぐ見つからなかった。ググり方が悪い説。

業務がpython, DjangoなのでAPI叩く感じになりそう。