Nginxのコードを読むために準備したこと

はじめに

僕には無理な話だった。

いろいろな事情があって、 nginxのモジュールの仕組みなどを知る必要が出てきた。 チョットデキル人になる必要はないが、完全に理解する必要があり、重い腰をあげてソースコードを読むことにした。

読み始めて3時間で後悔し、何週間かで完全理解するまでに自分が行ったことをメモとして残しておく。

読むにあたって準備したもの

今回、僕がNginxを読むためにいくつか準備したものがあるので記述しておく

今回Nginxのソースはgithubのものを用いることにし、リバースプロキシの部分を追いたかったので、 curl でリクエストしたら hello が返ってくるような ping 程度のAPIサーバとnginxサーバを Docker を用いて用意することにした。

またnginxのソースコードは非常に抽象化されており、僕のC言語のスキルでは太刀打ちできる気配もなかったため、gdb を用いてブレークポイントを貼ることで順次コードを追うアプローチをとることにした。僕にはvoidポインタが何者にも見えなかった。

gdbデバッグするにあたって公式のDebugging NGINX を参考に、 --with-debug を有効にするなど、あらかじめ nginxデバッグできるようなオプションをつけてビルドを行った。

余談だが、 上のような構成で gdb を起動する場合、 Docker 内で gdb -p ${pid} によってプロセスへアタッチする必要があるが、権限周りでオペレーションが拒否されたので注意が必要。

僕は docker--privileged オプションを使って gdb を実行することで回避した。

Nginxについて理解する

ソースコードを読む前に、そのソフトウェアがどういった背景や設計思想(アーキテクチャ)の元開発されたものかを知ることは非常に大事だと思う。

ソースコードの読解効率にも関わってくるし、書かれたコードの裏側にある意図をきちんと理解するためにもまずはソフトウェアの全体像を知っておいた方が良いはず。

というかむしろ全体像さえ知っておけばソースコード読まなくても困らないことの方が多いし、本当に必要にならない限りはコードを読むのはカロリーが高いし僕は身が持たない。 YAGNI の思考でいこう。

ここでは今回僕がソースコードを読む上で知っておいて良かったものに関して、ざっくり簡単に記載しておく。記載内容にあまり自信もなく精度もあまり良くないと感じているので、できればちゃんと自分で調べることをオススメする。

Nginx

エンジンエックスと読む。ンギックスではない。

一言で簡単にざっくり言えば、10K問題を解決したWebサーバーで、多重化されたノンブロッキングI/Oや非同期のイベント駆動アーキテクチャを採用したWebサーバ。

よく比較されていたApacheは、Apacheはマルチプロセスモデルを採用しておりアーキテクチャなどで差別化されている。

詳しい話はいくつかのLinkを貼るのでそちらを参照してもらえれば良いと思う。下からいくらでもキーワードは抽出できると思うので、あとは自分で調べて欲しい。

Nginxのモジュールについて

この仕組みを引数などにとにかく副作用的に入れ込んで実現しているので読むの辛かった

全体の設計概念よりもう少し内部の実装に近い設計の話になるが、ソースコードを読むにおいては理解しておくべき内容だと思う。

nginx はプラガブルに設計されており、 nginxが持つ様々な機能は module という単位で管理されている。

例えば、リバースプロキシも module の一つとして管理されているし、 mainmaster/worker プロセスが実行される前に呼び出されるコアな機能もCore Module として管理されている。

モジュールにもいくつかあって、コアとしてあるもの、標準モジュールとして提供されているもの、オプションとして提供されているもの、サードパーティ/自作のものがある。

当然プラガブルな実装ということで抽象化されており、各々が好き勝手に実装されているというわけではなくいくつかのインタフェースを実装することで実現されている。

http://mogile.web.fc2.com/nginx/dev/development_guide.html#Modules

もし、自作したい場合はインタフェースに則った実装をすることで作ることができる。

この辺りは、 Hello world のような最小単位の自作モジュールを作っている人もいるのでその辺りを参照すると良いかもしれない。

また、auto/moduleauto/modules を読んでみると、どうやら modulenginx をbuildする際に、オプションなどをもとに nginx_modules.c を自動生成することでバイナリに含むようなアプローチをとっているみたい。

ソースコードを読む

ざっくり nginx について理解できたのであとは読むだけ。

nginx が起動しているコンテナ内で worker プロセスに対して gdb を起動し、nginx.conf で指定した port に対して curl でリクエストを投げる。

その後、br などを用いてブレークポイントを仕込んだりして、一歩一歩コードを読み進めていけば良いはず。

docker$ ps aux | grep nginx
docker$ gdb -p ${worker_process_id}
bash$curl http://localhost:${port}/${request_uri}

おわりに

Dockergdb を用いながら nginx を読もうとして結構色々ハマったので念のため残しておくことにした。

ここではあくまで準備した事しか書いていないが実際に読んで、カーネル弱弱すぎて、epoll の使い方の基本を知ったり色々と勉強になる部分も多かった。

また、nginx の内部をざっくりと理解するという点では、読んで良かったかなとも感じる。

とはいえ学習カロリーが半端ないし、このカロリー消費してやらないといけない事も結構あったりするので、本当に必要になるまでもうこれ以上を読むことはきっとないだろう。優先順位の問題ともいう。モチベーションがもたない

Atcoderは難しい!?彼女はいる?緑色になる方法について調べてみた!!

はじめに

アフェリエイトとオンラインサロンで稼ぎたい。あとは水素水で儲けたい。

コロナで引きこもりすぎてやることが尽きてきたので数年ぶりにブログを書くことにした。

f:id:kanataxa:20200509231831p:plain
緑色コーダーになった僕のグラフ
kanataxa - AtCoder

無事緑色になったので、始めた動機ややってきたことなどをとりとめもなく適当に書いていこうと思う。

有名企業に勤めているわけでもなければ、東大京大を出ているようなそういう頭を持っているわけでもない、どこにでもいる一兵卒エンジニアなので安心してほしい(?)

同じようなモチベーションで始めた人の参考になれば少し嬉しいかもしれない。

はじめたきっかけ

ただの隙自語で読んでも得はないので暇人以外は飛ばしてほしい。

きっかけは二つある。

一つは、アルゴリズムに関する知識不足をここ最近少し感じるようになったことだ。

これから30歳に向けてソフトウェアエンジニアとしてどう歳をとっていくかを考え、より横にスキルセットを伸ばそうと考えたときに圧倒的にアルゴリズムやCS知識が足りていないと感じたのだ。

基本的なデータ構造やソートアルゴリズムに関する最低限の知識は持っていたが、少し複雑なものに関してはほとんど知識を持ち合わせていなかった。

アルゴリズムの基礎知識がないとつらいことはたまにあって、例えばある技術基盤の学習や、OSSソースコードレベルで理解しようとしたときに、意図が理解できないことがあったりする。 例えとして適切かは自信がないが、例えば暗号の基本を理解するには mod の知識が必要だったりする。よりモダンな楕円曲線によるアプローチを理解するには離散数学の知識が必要だろう。

もちろん、特定の分野に対して興味がある人はそこを入り口にして基礎的な部分へ深掘りしていく方が良いと思うし、僕もそういう状況であればそういうアプローチをしたと思う。 ただ僕にはそういう分野が思いつかなかったから競技プログラミングをすることにした。また勝つことが好きで負けることが嫌いな自分にはちょうど良かった。

これは完全に余談だが、最近はネットワークや分散トランザクションに関するちょっとした知識を得る必要性があってできる範囲で無理せず気が向いたときにゆっくり勉強していたりするが、競技プログラミングが役立ったという実感はあんまりなかったりする。

もう一つは俗物的な話になるが、外部から見たときの普遍的な肩書きが少しでも欲しかったというところにある。

これについては色々な事情があるので割愛する。

Atcoderを始めた頃のレベル感

緑色になるまでに自分がやったことについて話す前に、最初期の自分のレベル感を書いておく。

  • C問題までは時間をかければ解けた
  • BFSやDFSくらいの簡単なものについてはあらかじめ知識があった

つまりAやBで詰まっている人がこれを読んでもあんまり参考にならないだろう。

緑色になるための戦略

当然始めたての頃はパフォーマンスなんて全然出なかったし、どうすればパフォーマンスが出るのかも知らなかった。

なのでまずどうすれば緑色になることができるのかについて調べることにした。 先人の知恵がWebにたくさんあったので、それらを読んだところ以下のどちらかをすればなれそうだということがわかった。

  • C問題までを早く解く
  • D問題までを解く

僕はAtcoderのレートを伸ばすことが目的ではなかったし、早く解くのもあまり得意ではなかったので、D問題までを解くことにしようと思った。

ある程度の速さで4完を目指すという感じの戦略で行くことにした。

4完を目指してやったこと

過去の問題を解く

習うより慣れろ ということでまずはとにかく問題を解くことにした。

土日は気が乗らないことが多いので、週に3~4くらいのペースで解いていないABCのD問題までを解くことを日課とした。今でもやっていて今は水色を目指してEまで解いている。

最初のうちはCまででも結構時間がかかってしまったが、慣れるうちにCまでで10~15分くらいで済むようになったしD問題を含めても30~60分程度で終わるので、無理なく続けられている。

知っていなければ解けないみたいな問題も多々あるので、わからないなら大人しく解説を見ることも必要なことだと思う。

そもそも引き出しにないものが解けないのは当たり前で、身に付けた知識を適切な時に適切に扱えるようになることが大事なことである。

できないにもいくつかレベルがあって、

  1. 知らない
  2. 引き出しから出てこない
  3. 実装できない

このうち 2 まではもう仕方ないと割り切って、3 だけはないように精進する必要がある。

公式の解説(pdf,youtube) はもちろん、ネットに解説ブログもたくさんあるので ABC123 D のように検索すればわかりやすい解説がたくさん出てくる。とても感謝。

ライブラリをもっておく

ライブラリと書いたがそんなに仰々しいものではない。

問題を解いていくといくつかのデータ構造などある程度一般化できるものがあることに気づいた。

僕は Go で問題を解いているが、 GoPythonC++ に比べて汎用ライブラリが少なく実装が多くなるものもあったりするので、都度都度実装しているのも面倒になってきたのでライブラリ化することにした。

スニペットとして持つという選択肢もあったが、とりあえず github で管理することにした。

一人のWebエンジニアとして

完全な余談。

Webアプリケーションを普段開発しているエンジニアから見たときのAtcoderの問題はどこまで解けると良いのか、みたいなある程度の指針を書いてみる。 また、新卒などのできない前提の採用枠に関しては完全に対象外である。

結論から先に言うと、ある程度信頼を得るにはC問題までは解ける必要があると感じた。早く解ける必要はない。

もちろんリードやシニアレベルではなく、機能(API)開発をするようなエンジニアにおいての話だ。

また、社会に出ているエンジニア全員が全員解けるわけではないのでもし解けていなくても安心してほしい。

要は特別なアルゴリズムを使うことなく基本的なデータ構造や再帰を用いて物事を筋道立てて考えることができる、と言うことを示せるラインがC問題だと思っていて、これができればアプリケーションのレイヤーを作ることはそう難しくない。

このレイヤーで働くエンジニアは仕様を一般化してプログラムに落とし込むことが一番に求められることだからだ。

ただしあくまで論理的思考やコーディング能力が示せるだけなので、これだけできれば良いというわけではないし、逆にこれができていないから悪というわけでもないから、この観点のみで悲観も楽観もする必要はない。

ただしA問題が解けない人は危機感持った方が良いと思う

おわりに

いかがでしたでしょうか

とりあえず勢いで始めて無事緑になったので書いてみた。

僕がAtcoder始めて一番衝撃だったのは、学生ほんまにすごいなということ。 唯一僕が勝っているのが年齢だけってことに気付いちゃったよね。ぴえん。

最近の高校生は授業中に Bluetooth でイヤホン接続して映画見るらしいし、だんだんジェネレーションギャップみたいなのも感じ始めたりしていて、おじさんになってきたなあというなんともいえない気持ちもある。

老害にならないように良い感じに歳取って、将来彼彼女らが社会人になって一緒に働くことになった時に幻滅されないようにガンバリタイトオモイマシタ。

目的はないもののとりあえず何かコードを書きたいのであれば、Atcoder結構おすすめ。

好きになるその瞬間を。

見てきました。クリスマスイブ、オタクと二人で。

 

川崎の舞台挨拶、多分4回目くらいのアレ。(客が入らなかったのか)シアターが変更されてるとか、第一週からの特典全部貰えるとか、あまり売れ行きよくないのかな的な雰囲気を感じつつ。

 

以下は、ネタバレのような、ただのメモ書きのようなもの。語彙力0のオタク感想文。

 

108の設定の1つ、僕ラブコメが好きって満面スマイルではしゃいでた隣のオタクが一番印象に残った。

 

内容としては、歌の内容を映画一本分に強引に引き伸ばした感が否めない。前作に比べると少し構成とかが雑な印象を受けた。雛の一人語りで序盤の場面の切り替わりをしていたのと、中学の時の話を随分引っ張ったなーと。

後、(多分)乃木坂の演技がめちゃくちゃ下手だった。歌だけでええやんけ。

個人的には、高校入ってからの(歌の部分以外の)部分を濃くしてほしかったなとか。

ずっすきの方が良かったなとか思っちゃったので、もっと頭空っぽに純粋に楽しめばよかったなー。

 

とはいえ、作画もよく、最後のシーンで雛がぬるぬる動いていたのはすごかった(KONAMI)

瀬戸口雛好き、可愛いので。神谷くん演じる優もかっこいいしストレスレスだし、瀬戸口家好きすぎて好きになった。

ついでに松岡君が出演してて、好き、好きーてなってしまった。松岡君、好き。

 

終盤の虎太郎が校門で泣いてる雛にかけた台詞が、二次元の幼馴染にだけ許された台詞感があってよかったです。

後、EDの静止画かなり好きだったし、アレ映像化してほしい。頼む、予算降りて。

 

 

舞台挨拶は割愛。

 

書いてて思った、この映画について語れることのNASA

 

とりあえず、AWよりは面白かったです。

君の名は>ユーフォ==聲の形>>好き瞬>>>>>>>>>>>>>>>>>>>>>>AW

 

 

【忘備録】DjangoとJSONとAjax

Djangoで、AjaxでDBからデータを取得、JSON形式で返すためのメモ。

 

 

まず、AjaxDjangoでするには、postだと下記ページのような処理が必要。

Django公式:https://docs.djangoproject.com/ja/1.10/ref/csrf/

 

DjangoにはデフォルトでJSONresponseやserializeのようなJSON変換用のライブラリが存在するが、Modelのデータを直接取ってJSON化するため、pk等の不要なデータまで送られてしまい微妙である。気になったら公式に例があるので動かしてください。

 

そこで今回は、Pythonのライブラリを使って、Ajaxのために別でJson変換用の関数を定義し、そこへurls.pyで飛ばすように制御することを考えた。

 

sample/models.py

class Sample(models.Model):
    name = models.CharField(max_length=30)
first = models.CharField(max_length=30)

sample/ajax.py(views.pyの代わり)

 

def SampleListAjax(request): 
objs = Sample.objects.all()
data = [dict(name = obj.name, first = obj.first) for obj in objs]
json = json.dumps(data)
return HttpResponse(json, content_type="application/json")

 

 

sample/urls.py

 

class urlpatterns=[
url(r'^sample/',ajax.SampleListAjax)
]

 

後は普段通り、JavaScript系の何かでAjaxして設定したurlにリクエストしてJSONデータを取得するだけ。

 

 

【django】クラス汎用ビューについて

タイトル通りクラス汎用ビューの覚書きです。

 

Djangoの公式チュートリアルでは関数ベースのビューを使っているため非常につかみ辛かったのですが、何とか消化できたので記載。

 

クラス汎用ビューとは

雑に言うとあらかじめDjangoが用意してくれている、汎用的なビューのことです。

基本的にFormviewやListviewなどのクラス汎用ビューを継承して、テンプレート用のHTMLに指定された変数名を記載しておくだけで画面が作れてしまうという非常に便利なものです。

 

例:ListView

mysite/sample/urls.py

from django.conf.urls import url
from django.views.generic import ListView

urlpatterns = [
url(r'^sample/',SampleListView.as_view(),name='sample'),
]

 

mysite/sample/views.py

template _nameを指定しないと、sample/model_list.html を参照するっぽいです。

from django.http import HttpResponse
from django.views.generic import ListView
from sample.models import Sample
@method_decorator(login_required, name = 'dispatch') class Sample
ListView(ListView): model = Sample template_name = 'sample_list.html'

mysite/sample/models.py

from django.db import models

class Sample(models.Model):
    name = models.CharField(max_length=30)

mysite/template/sample_list.html

上のviews.pyでget_context_dataをオーバーライドして取得データをprint してみると何取得してるかわかります。

<table>
<thead><tr>
<th>id</th>
<th>name</th>
</tr></thead>
<tbody>
{% for sample in object_list %}
<tr>
<td> {{sample.id}}</td>
<td> {{sample.name}}</td>
{% empty %}
<a> empty </a>
{% endfor %}
</table>




(importしてるものちょくちょく抜けてたりしますが、)こんな感じに適当にコーディングしてあげるとDjangoが勝手に解釈して作ってくれます。

もちろんクラス汎用ビューはget_context_data()等を持っているのでこれらをオーバーライドして処理を加えたりすることもできます。

CreateViewやFormViewなど色々な汎用ビューがあるので詳しくは公式Docmentを読んでみてください

Django公式

https://docs.djangoproject.com/ja/1.10/topics/class-based-views/

 

(何か間違いなどありましたらご指摘お願いします。)

 

 

【忘備録】Django1.10の基本的なこと【Django環境構築】

Django、初めて触ったので覚書き。Flask使いたい

ついでにDjangoの比較的新しいバージョンの日本語の記事あまり見ないので記載。

続きを読む

【雑記】ここ2カ月でやったこと

忘備録、ここ2カ月でやったことのメモ。

 

Jqueryの基礎学習

on()でDOM生成詰まった、読み辛いなって感じ。とはいえ、やろうと思えば一通り何でも出来ちゃうので助かる。

 

ブロックチェーンの概況

BitCoinが生み出したイノベーションのお話。マイナーとかPoWとかあるいはスマートコンストラクトとか。

 

読みやすいコードのお話

単純にリーダブルコードを読んだとか、あるいはUNIXの思想やDRY、KISSとかそんな話を学んだだけ。

新卒研修で、散々同期のWETなコードや外にはみでてるコードを読まされて非常にストレスだったので真っ先に勉強した。あの研修で教えていたことをすべて否定するような内容だったので余計悲しくなったりしたが、綺麗なコードをより意識するようになった(できるとは言っていない)。

 

SQLアンチパターン

論理設計のお話。僕自身これは大学でちょろっとやっていたのでその延長線上で。

小さいシステムのDBを設計することになり、自分が保守するので、過去SE達が踏んできた地雷を踏みたくないが故に勉強。設計しててここ臭いなって部分、だいたいアンチパターンにあったので先人は偉大なり。

 

並行処理(マルチスレッド)

これはJavaの並行処理。どうやってアトミック性を維持するのとか、これがって思う奴もあったし、これ当たり前だけど実装できるか怪しいとかそんなこと思いながら勉強。

実装は誰でもできるけど、安全に公開しながらの実装は非常に難しそう。

僕はConcurrentを信じようと思いました。

 

暗号のお話。

話し飛び飛びだけど、ブロックチェーンのために勉強。鍵のお話からハッシュ、認証、署名等々一通り学習。今やって意味あるのかって言われると、まぁなさそう。

途中で互徐法書いたり色々やってたらちょっと時間かかった。

 

NetWork

DNSとかHTTPとか表面上はだいたい知っていたけど、それだけじゃヤバいよねって話で勉強。基礎の基礎くらいは身についた(と感じる)。RESTとか色々あるのでもうちょっと学習が必要だと思った。

 

 

色々寄り道をしてふらふらしながらやっていたとはいえ、2か月でこんだけしかやってないんだなーと思ったり。精進します。

 

 

今後学びそうなこと