webアプリケーションに触れてみる(1)【webアプリケーションを設計する】

先週はangular2のチュートリアルやってたのでお休みしてましたが今週からは実際にアプリケーションを作っていこうと思います.

作るのはunityのWebGLを閲覧したり投稿したりするプラットフォームみたいなものにしようかなぁと思っています.

いつだかに今月中に何か完成させるみたいなこと言ってましたが多分無理です.今はプロトタイプみたいなものでも来月いっぱいまでかかるかなぁって見積りです.

余談ですが,やっぱりangular2とかよりreactのほうが流行りなんでしょうか…?angular2しか使ってないので何とも言えませんが,angular2は書きやすいけどちょっと管理しにくいかなって印象です.

ではとりあえずどんな構成にするか説明してみます.

サーバ構成

f:id:ymzkmtfm:20170923222411p:plain

今回の構成は先々週までのものに近いです.

いくらか変わったこと(まで予定ですが)としてはwebサーバ(Nginxから変更なし)から配布するファイルをangular2で作ってることとDjangoREST APIを提供するサーバとして使用するという点です.

ページ構成

f:id:ymzkmtfm:20170923225407p:plain

angular2で作るページは概ねこんな感じになります.トップページはランキングページ(といっても作品はおそらく全部ダミー)でいいかなと思ってます.

データ構成

現在考えているデータ(テーブル)としては

・user: ユーザー

- name: string

- image: string(url)

・content: 作品

- titile: string

- url: string(url)

- description: string(url?)

- image: string(url)

- published_at: Date

- author: user

・タグ

- tag: string

・タグ-作品

- tag: tag

- content: content

・コメント

- user: user

- comment: string

- content: content

・評価

- user: user

- evalution: number

- content: content

デイリーランキング

- date: Date

- content: content

- rank: number

- evalution: number

・ウィークリーランキング(デイリーと同じ)

・マンスリーランキング(デイリーと同じ)

って感じにしたいと思います.

現状

youtu.be

現在はランキングページと検索ページの骨組みが少しできたかな,という感じです.

ただ,後述しますがルーティングの処理がいまいち理解不足で検索窓の反応が少し意図しないものになっています(ブログ書いている間に改善できました).

github.com

コードはこちらになります.

travisCIも導入してるのでjsのテストをしたい方は参考にしてください.現在はビルドしてアプリケーションが生成されるかどうかだけチェックしてます.ちなみに現在開発中のdevelopブランチではビルドに失敗してます.泣きそう.

いまいち分かりにくいところ

Angular2は大体コンポーネントという単位で開発するのかなぁという風に感じているのですが,開発したコンポーネントの連携方法がいまいちわかりにくかったので少し書いておきます

app

-app-routing.module.ts

-app.module.ts

-app.component.ts

-search/

--search-routing.module.ts

--search.module.ts

--search.component.ts

大体こういう感じで分けたとき,「/search/:term」という感じで検索を使用としたとき,まずはsearch-routing.module.tsを大体こんな感じにします.

大切なのはforChildの部分です.次にこれをsearch.module.tsに取り込みます.

最後にこれを上位のモジュール(今回はapp.module)に組み込みます.

まとめると

上位モジュール - 下位モジュール - 下位ルーティング

みたいな感じです.

最初はルーティングの上下とモジュールの上下関係がよくわからなくて結構悩みました.結局英語の長い公式ドキュメントを見る羽目になりました.

ただし,トップページに関してはapp-routing.module.tsに直接書いたほうがよさそうです.

あと検索窓に

<input $hoge/>

<button [routerLink]="['' '/search',$hoge.value]">fuga</button>

みたいな感じにしたら反応が悪かったんですが

<input [(ngModel)]="hoge">

<button [routerLink]="['' '/search',$this.hoge]">fuga</button>

みたいな感じでデータバインディングをはさむとうまくいきました.

理由はよくわかりませんが一時変数をそのまま使うのは控えたほうがいいのかもしれません

来週の予定

来週は画像の読み込みと認証の一部ができればいいかなと思っています

サーバに触れてみる(3)【NginxとDjangoとMariaDBを接続する】

先週はざっくり環境を整えました

今週は整えた環境をつないでみたいと思います

Djangoチュートリアルとかもやってたんですが,チュートリアルまんましかやってないので書くことはないです

Nginx + Django

まずはNginxとDjangoをつなぎます

ただ,NginxとDjangoは直接つなぐことはできません(多分)

もしかしたらできるのかもしれませんが,普通はuWSGIというものを使うらしいです

f:id:ymzkmtfm:20170910100608p:plain

uWSGIはDjango(というかpython)とNginxとの通信を実現してくれるソフトウェアです.Apachとかだとmod_wsgiを使うらしいです

もうちょっというとWSGIというpythonとwebサーバとの通信の仕様書みたいなものがあってuWSGIはそれを実装したものみたいな感じらしいです.形態としてはサーバ・クライアントみたいに通信をしているらしいので,Django側にだけインストールすればなんとかなるらしいです.uWSGIはc言語での実装ですがpythonで実装したgunicornとかもあるらしいです.

NginxはuWSGIをサポートしているらしいので特に面倒なことをする必要ありません.ただしNginxの設定ファイルにuWSGIでアプリケーションサーバに通信することを教えてやる必要があるので少し設定をいじります

Nginxの設定は/etc/nginx/conf.dの中に*.confという名前でファイルを置いてやればできます

実際に置いてあるものがこちらです.これで192.168.33.10の80ポートに対するアクセスはNginxに対するアクセスになります.location / はとりあえず全部uWSGIをつかってDjangoにつながります.ポートはuWSGIの方で設定します

ここで注意しなければいけないのは/static/とaliasです.Djangoの静的ファイル(cssとか画像とか)はwebサーバを介して使うときにいくつか注意が必要で,きちんとやらないとそこらへんがうまく動きません.大まかな流れとしては

1.Django側で静的ファイルをまとめる

2.まとめたファイルをWEBサーバに移す

3.Nginxに場所を設定する

という感じです.

まずはDjangoで静的ファイルをまとめるのですが,これはsetting.pyを開いて

STATIC_ROOT = "ファイルをまとめたい場所"

としたあとに

python manage.py collectstatic

をすれば大丈夫です.

次にWEBサーバにまとめたファイルを移してやるのですが,これはrsyncでもgitでもいいと思います.どうやらデプロイツールとかを使うといいらしいんですがよくわかりませんでした.

最後にNginxのなかにlocation /static/ { alias webサーバに移したファイルのローカルなパス }とすれば静的ファイルが使えるようになります.

ただ,なんかインフラの設計としてこれでいいのかよくわからないのでこれがいいのかどうかはわかりません…

Nginx側の設定が概ね終わったら次はuWSGIの準備をします

uWSGIはcで書かれているのでインストールにはコンパイラが必要です

sudo yum groupinstall "Development Tools"

とかやると大体入ります.あとpython-develが必要なので

yum install python-devel

とかやって入れておきます.正直面倒です.終わったら

pip install uwsgi

でおそらくインストールされます.この手のサーバソフトとかには設定ファイルがつきものなので好きな場所に設定ファイルを作ります

 chdirにはアプリケーションの場所を設定します

moduleにはwsgi用の特別なファイルを設定したりする必要があるらしいのですがDjangoが勝手に作ってくれるのでsettings.pyのある辺りとかを探して書いてあるような感じでパスを通します

masterとvacuumは知りません

pidfileはプロセスの情報とか諸々を置いておく場所です.ディレクトリだけ用意してれば大丈夫です

socketはみたまんまです

die-on-termもみたまんまです

あとはuWSGIとNginxを起動します

uwsgi uwsgi.ini

systemctl start nginx

多分これでつながります

Django + MariaDB

今度はDjangoMariaDBを接続します.こっちの接続は結構簡単です

大まかな流れとしては

1.DBサーバでDjango用のデータベースを作る

2.作ったデータベースにDjangoからの接続を許可する

3.DjangoにDBの情報を教える

大体これで動きます

まずはDjango用のデータベースの作り方ですが,これは普通に作るだけです

作ったら

grant all なんちゃらかんちゃら 名前@IP なんか

みたいな感じで接続を許可します.詳しくは忘れました

作ったらsetting.pyにデータベースの情報を教えます.

これでつながります.3306ポートはMatiaDBのデフォルトです

来週の予定

来週は少しフロントエンドっぽいことをやろうと思っています

サーバに触れてみる(2)【Vagrant+Ansibleで3層Webアプリケーションの開発環境を構築する】

前回更新より約三ヶ月ぶりの更新です

その間何をやっていたかというと,二ヶ月間くらいは学校で好きなもの作れよみたいなチーム課題でゲーム作ってました

残りの一か月は遊んでました

というわけで今回の更新分は今週一週間の作業報告みたいなものになります.

ちなみに三か月前に作った仮想環境ですが,ぶっ壊れてました

泣きました

VMwareを更新したらネットワーク周りの動作がおかしくなったので更新が原因だと思うんですが結局直ることはありませんでした

そこらへんも含めて今回はやっていこうと思います

今回の目的

今回はいわゆる3層webアプリケーションの開発環境(今回はnginx+Django+MariaDB)を構築したいと思います

もちろん開発環境を構築したので何かしら作ろうと思っています

…というか,本当は概ね考えているんですけどそれぞれの機能をちゃんと把握していないのできちんと設計ができないという感じですね.

f:id:ymzkmtfm:20170901181019p:plain

それはさておき今回作成する環境は図にするとこんな感じです

3台のマシンの上にそれぞれ必要なプログラムを入れて通信させてwebアプリケーションを実現する形ですね

多分定番な形になっているはずです

あと,今回はいわゆるフロントエンドといわれるような技術(今だとReact.jsとかでしょうか)はあまり触れていません

ですからバックエンド,あるいはインフラ周りの話になるかと思いますのであらかじめご了承ください

なんで三台なのか

こんなことを書く必要があるかは不明ですが,一応この形にする理由をまとめておきたいと思います

f:id:ymzkmtfm:20170901191746p:plain

まずは一番素朴な構成だとこうなると思います.ブラウザがサーバにリクエストを渡してHTMLを返してもらう構成ですね.

これはとてもシンプルな構成ですが,これでは1+1の結果を返すこともできませんし(多分頑張ればできる),アカウントの管理も認証もできません

f:id:ymzkmtfm:20170901194930p:plain

そこで先ほどの構成になります.webサーバにはHTMLとかそこらへんだけを任せてデータベースにデータをためてその中間でこねこねする構成です.こうすると役割が分担できて便利です.

たとえばクックパッドを見てみましょう

 

cookpad.com

検索欄に「素麺」とか適当な単語を入れるとレシピの検索結果が返ってくると思います

内部構成がどうなっているのか定かではないので何とも言えませんがデータベースにレシピを保存して,アプリケーションサーバで検索/並び替えをしてwebサーバが返しているって感じじゃないかなと思います.本当のところどうなっているかは多分調べれば出てくると思うんで気になる人は調べてみるといいと思います

とにかく三層にするとそれぞれ役割与えてそれに特化させて色々カスタマイズがきいて便利だから今回はそうします

余談ですがwebサービスってデータを作る人と消費する人が同じなもの(ツイッターとかニコニコ動画とか)とwebサービスを提供する人が作ってるもの(ニュース系とか)と他人の作ったものを提供しているもの(amazonとかnetflixとか)とか色々あってなんだかちょっと面白いですね

どうやって三台のマシンを用意するのか

今回の構成ですが三台のマシンを用意します(本当は一台のマシンの中に入れてもいいんですけどね)

さすがに本物のパソコン三台用意できるわけじゃないので仮想マシン(今回はVirtualBox+Vagrant)にCentOS7を入れて使っていきたいと思います.

また,CentOSの中の設定を自動化するためにAnsibleを使いたいと思います

f:id:ymzkmtfm:20170901205825p:plain

図にするとこんな感じです.いきなり色々出てきたので一旦整理します.

VirtualBoxは簡単に言うとパソコンをソフトで実現したものです.似たようなソフトにVMwareとかがあります.こいつを使ってやれば一台のマシンの中にソフトウェアとして何台でも(リソースが許す限り)マシンを起動させることができます.ここにOSを入れてやればしっかりその数だけOSが起動します.今回は後述のVagrantと親和性が高いらしいのでこいつを使うことにしました.

VagrantVirtualBoxをはじめとした仮想化ソフトウェアを使いやすくしてくれるツールです.Vagrantfileと呼ばれるファイルに色々書いてやるとその設定で仮想マシンを作ってくれます.しかもかなり早く作ってくれるので仮想マシンを起動したり全部消してやり直したりのサイクルがかなり早くなります.これがないとVirtualBoxの設定とかOSのインストールとかにかなり時間を取られます.代わりになるソフトがあるかはよくわかりません

f:id:ymzkmtfm:20170901215254p:plain

Ansibleは新しいサーバに必要なものをインストールしたり,起動時にやる処理を自動化したりするソフトです.こういった初期設定をやってくれるソフトをプロビジョナーっていいうとか言わないとか.似たものにChefとかPuppetとかがあるらしいです.AnsibleはChefやPuppetに比べて簡単らしいので今回はこれにしました.その代わりAnsibleはChefとかに比べて複雑な管理が面倒らしいので数千台以上のサーバを管理するときはChefとかの方がいいらしいです.実際はよくわかりません.

f:id:ymzkmtfm:20170901223133p:plain

もちろん新しいサーバにはansibleが入っていないのでansible用のサーバが必要です.しかし今回はAnsibleのインストールと実行をそれぞれのマシンでやってもらいます.手動でやってはAnsibleとVagrantのありがたみがないのですが,Vagrantに設定すれば全部自動でやってくれます.つまり,VagrantとAnsibleの設定をしっかりしてやれば「色々設定してあるマシン×3を壊してもう一回同じ状態に戻す」というサイクルを「vagrant up」という1コマンドで全部自動化できます.ついでに設定がファイルで管理されているのでバージョン管理とかリファクタリングとかできますし,なんならテストもできます.使ってみると結構便利です.

それでは題名にも書いてあるとおりVagrantとAnsibleで環境を作りましょう

Vagrantの設定

Vagrantを使うには仮想化ソフトがないと始まりません

というわけでVirtualBoxをインストールします

https://www.virtualbox.org/

終わったらVagrantをインストールします

https://www.vagrantup.com/

あとはインストールするOSなんですが,生のisoではなくboxというファイルを使うので

https://app.vagrantup.com/boxes/search

ここから見つけます,ダウンロードする必要はないです

ここからの作業はコマンドプロンプトPowerShellかを使って進めていきます

まずは

mkdir vagrant

cd vagrant

などで適当に作業フォルダを作って移動します.そしたら見つけたboxのページに書いてある指示に従ってvagrantを初期化します.

CentOS7だと

vagrant init centos/7

ですね.Vagrantfileというファイルができたと思います.Vagrantに必要なのはそのファイルだけです.このファイルに従って仮想マシンが構成されます.

例えば一台のマシンを起動する場合はVagrantfileをこのようにします.起動の際は

vagrant up

とすると起動できます.確認してみてください.起動できた場合は

vargrant ssh

仮想マシンにログインできます.

作成した仮想マシンを削除するときは

vagrant destroy

です.

今回は三台のマシンを使うのでVagrantfileをこのようにします.細かいことは感じ取ってください.intentとかなんとか書いてあるのはマシン同士を通信させるのに必要らしいです.APサーバがappサーバなのは趣味です.できたらvagrant upしてみてください.

ちなみにそれぞれ名前がついてるのですが,この名前を使って個別に操作できます.例えば

vagrant ssh web

とすればwebサーバに入れます.

vagrant destroy db

とすればdbサーバだけ破壊できます.作成のし直しも同じ感じでできます.

あとは何をインストールするのかとかそういったことですが,そこはほとんどAnsibleの役目なのでAnsibleの話に移ります

Ansibleの設定

ansibleはインストールする必要ありません.そもそもwindowsだと動かないとかなんとか.

なのでいきなり設定ファイルの編集です.Ansibleに必要なファイルは指示と対象を結びつけるhostsファイルと具体的な指示を書く.ymlファイルです.

まずはhostsファイルです.ここにはansibleが対象とするhostたちのIPアドレスとかもろもろ必要な情報を書きます.先ほども言ったようにもともとサーバーにインストールするものなのでこんな構成になっていますが,今回はそれぞれ自分にインストールして自分で実行していただくのでかなり簡素な作りになります.というか全部localhostになります.

実際に三台のマシンに使うhostsファイルがこちらになります.[ ]で囲まれている部分はホストの役割みたいなものです.これのおかげでwebサーバー用の構成をすればいいのかDBサーバ用の構成をすればいいのかがわかるようになります.

あとは実際の指示を書くymlファイルです.これはちょっと面倒で,公式のBestPracticesに書いてあるフォルダ構成が推奨されています.

http://docs.ansible.com/ansible/latest/playbooks_best_practices.html

この構成に従わないならなんかべたべた一枚のファイルに書いちゃえばいいと思います.とりあえず大切なのはconnection: localって書いておくことです.詳細は面倒なので省きます.githubに全部上げたので感じ取ってください.実際僕にもよくわかりません

github.com

さて,出来上がったらVagrantに組み込みます.といってもVagrantfileに追加するだけです

大切なのはlimitで自分が何者か教えてあげることです.これをやらないと自分が何者かわからなくなったマシンたちが全部インストールし始めます(それでもいいんですけどね)

全部できたら

vagrant up

してください.vagrant sshで中に指定したものが入っていると思います.

 

これでマシンの構成は概ね終わりました.

今はdjangoチュートリアルをやってます.これが終わったら設計に入って一個くらいは今月中に完成させたいと思います

 

Androidに触れてみる(5)【ブラウザ経由で認証してもらうマストドンクライアントをとりあえず形にしてみた】

www.youtube.com

github.com

サーバに触れてみる(1)【仮想環境にサーバ建ててssh接続】

サーバで遊び始めることにしました

前回までのandroidアプリはmstdnクライアントとして作ろうと思ったんですけどレイアウトを整えてたらモチベーションが死んだので開発も一緒に死にました

サーバに自力でマストドンを建てて遊ぶまでやってみたいと思ってます

今回は題名のところまでです

仮想環境を整える

今回はVMwarePlayer+CentOS7にしました

それぞれダウンロードして起動するまでは流れで何とかなります

今回は簡易インストールを止めにしましたがかなり簡単でした

lino.hatenablog.jp

ただ起動するとネットにつながりません

これはどうやらブート時にネットを設定するあれこれがデフォルトで起動しないかららしいです

webird-programming.tech

ここに書いてあるようにONBOOTをyesにするだけで解決しました

SSHで接続してみる

起動はうまくいったのでsshで接続してみたいと思います

VMwareだし直接いじればいいかもしれませんが、まぁ気分です

今回はsshクライアントにTeraTermを使いました

セットアップが簡単でいいですね

webkaru.net

ただ、パーミッションには気を付けたほうがよさそうです

takuya-1st.hatenablog.jp

なんとかできました

f:id:ymzkmtfm:20170525194002p:plain

実はいろんなところにハマってたんですけどね…

Androidに触れてみる(4)【ブラウザ経由で認証してもらうマストドンクライアントを作ってみた】

マストドンへのブラウザ経由の認証及びtootが成功しました。

せっかくですので少しづつ解説してみようと思います。

このアプリはネットにつなぐので当然必要になってきます

intent-filterに関してはよくわかりませんがとりあえずあとから開くものにはactionにVIEWを、categoryにDEFAULTを、ブラウザから開くものにはBROWSABLEをつけておけばよさそうです。

andante.in

またdataはブラウザからデータが送られる場所を設定するタグで、scheme://hostという場所に送らるそうです。利用するときにはそこを参照するようですが、なんでブラウザがそこにデータを送るのかとかなんでそこからデータが取れるのかとかはよくわかりませんでした。知っている人がいたら教えてください。

これは前回も使ったRetrofit2ですね。非同期処理を裏に回したいのでsubscribeOn(~)を使ってます。subscribe()の中身はメインで処理したいのでobserveOnで指定してます。

アプリの名前、リダイレクトURI(AndroidManifest.xmlで設定したshemeとhostをsheme://hostと並べる)、スコープ(read write followをスペース区切りで並べる)をパラメータとして渡してあげるとクライアントを登録できます。ただ、起動するたびに新しいクライアントとして登録するのはかなりまずいのでいつか直さないといけません。成功すると

github.com

 ここに書いてあるものがJSONで送られてきます。今回はGSONを使っている(addConverterFactory(~)の部分)のでクラスのようにデータを扱えます。

この部分でブラウザを起動してます。ブラウザを呼び出すときもパラメーターを渡さないといけませんマストドンOAuth認証にDoorkeeper gem for OAuthなるものを使っているようです。そのため、接続する場所はhost/oauth/authorizeまたはhost/auth/sign_inになるはずです。

github.com

 ブラウザから帰ってくると

こいつが呼ばれます。ここでsetIntentしてあげないとブラウザから送られてきたデータが使えません。ちなみにもらえるデータはcodeと呼ばれるよく理解できていない文字列でsheme://host?code=hogeという形式で送られてきます。onNewIntentの次はそのまま

こいつが呼ばれてきます。ブラウザからもらったcodeを抽出してAccessTokenを入手します。scopeも渡してますが、もしかしたらいらないかもしれません。必要なパラメータと帰ってくるデータについてはここをご参照ください。

github.com

subscribeではもろもろの必要なデータを渡しながら投稿用のアクテビティを起動しています。

tootにはヘッダが必要なのでRetrofitさんに作ってもらうようお願いしています。"toot"の部分につぶやきたい内容を入れればつぶやけるはずです。

Androidに触れてみる(3)【Retrofit2+RxAndroid(RxJava)で初めてのWebAPI】

色々あってWebAPIをandroidから叩いてみることにしました。

出来上がったものはこちらです

たったこれだけですがここに至るまでに結構時間がかかってしまったので同じような初心者に向けてここに至るまでの経緯を残しておこうかと思います

第一章 OAuth2がわからない

マストドンクライアントを作ろうとしているわけですがそもそもなにをどうすればいいのかわかりません

そんな時に出会ったのがこのページです

thr3a.hatenablog.com

こちらのページに書いてある通りOAuthなるものをまず最初にやればいいらしいのですがこれが全然理解できません。

murashun.jp

こんな記事とか

qiita.com

こんな記事を見ても全然ピンときません。

OAuthライブラリとかも探してはみましたがなんだかよくわかりません

結局OAuth認証をライブラリとかでパパッとやったり、そもそも仕組みを理解したりすることはあきらめました

ただ、いろいろ調べてわかったことはOAuthはWebAPIだということです

第二章 WebAPIがわからない

正直私はまともにプログラムを作ったことがないのでWebAPIなるものがなんなのか全然わかっていませんでした

qiita.com

この記事は個人的にはわかりやすいものだと思っています。

最終的にほんの少しだけWebAPIを叩いた経験と少しの調べた知識から推察するに、WebAPIとはちょっとリッチなhttp通信のことであり、少なくとも使う分には何ができるのかがわかっていればなぜできるのかを考えなくていいシステムなんだと思います。APIって名前がつくくらいだから当然なんでしょうけど。

ではこれを使うためにhttp通信をandroidで実装してやりましょう

第三章 AndroidでHTTPがわからない

アンドロイドではApachHTTPClientとHttpUrlConnectionなるものが標準で搭載されているらしいのですが、どちらを使えばいいのかよくわかりませんでした。

調べているうちに流れ着いたページをみると、どうやらApachHTTPClientは削除されたらしくHttpUrlConnectionなるものを使ってみることにしました

blog.riskfinder.co.jp

qiita.com

techbooster.jpn.org

しかし書いてみるとどうもしっくりきません

というか私はエラーハンドリングがあんまり好きではありません

AsyncTaskを継承したクラスを作成する必要があるのもなんだか嫌で、どこか胸がときめかないようなコードになってしまいました。

そんなときにいろいろ探し回った結果見つかったのがRetrofit2+RxAndroid(RxJava)でした

第四章 初めてのWebAPI

 最初に挙げたプログラムですが、大体ここら辺を見て作りました

dev.classmethod.jp

qiita.com

コードを見れば何しているのかわかりやすく、なによりエラーハンドリングとかAsyncTaskとかが現れなくて気持ちがいいですね。

 ただし導入紹介されているものはバージョンの関係で競合みたいなものが発生します。

stackoverflow.com

2をつけると解決するのですがいまいちわかりにくく結構ハマりました。

あと、どうやらマストドンjava用ライブラリが現在開発中っぽいですね

github.com

まだ安定していなさそう&エラーハンドリングがめんどくさそうなので今回は避けました

余談ですがこの方のスライドがRxをわかりやすく説明しているように感じたので載せておきます。

speakerdeck.com