Web技術」カテゴリーアーカイブ

同時に複数の処理を実行するための最低限の知識 – メイドさんでも分かるプログラミングシリーズ vol.4

前回に引き続き、メイドさんにプログラミングを教えるためのシリーズです。

前回Webサーバーの仕組みについて、説明しました。早速アプリからWebサーバーに通信するプログラムを作ってみたくなりますが、その前に一つ知っておかなければならないことがあります。

外部と通信する時に大切なこと

Webサーバーは、アプリを実行する端末とは通信回線越しに離れたところにある別のコンピューターです。そのため、通信をして結果が帰ってくるまでの間には、どうしても待ち時間が発生します。

ところで、プログラムは通常、上から順に書いたとおりに実行されます。途中で遅い処理があると、その処理が終わるまであとの処理は行われないのが大原則です。

通信している間待つ

もし、Webサーバーとの通信のような遅い処理を待ってしまったらどうなってしまうでしょうか?ボタンを押してから、サーバーが結果を返すまでの間、固まってしまうことになります。その間は、他のボタンを押すこともできませんし、ホームボタンを押してホーム画面に戻ることも、別のアプリを起動することも、アプリを終了することさえもできなくなってしまいます。

通信中ボタンが押せない!--

こんなアプリを作ったらユーザーに怒られてしまいますね。(^^;
(実際はできないようになっています)

並列プログラミングとは

外部との通信など結果が得られるまでに時間がかかってしまう処理は、待つのではなく、別個独立してやって欲しいです。このような処理「並列処理」と言います。

並列処理をJavaで実現する、最も基本的な仕組みとして、「スレッド」というものがあります。Threadとは糸という意味です。一つの処理の流れを糸に例えて、複数の糸が同時に伸びて絡み合っている様子をイメージしてください。複数のスレッドを使うので、「マルチスレッド」ということもあります。

スレッドは糸

Javaでスレッドを作るためにはズバリ、Threadというクラスを使います。書き方は2通りあります。

Thread t = new Thread() {
    @Override
    public void run() {
        // 処理
    }
};
t.start();
Thread t = new Thread(new Runnable() {
    @Override
    public void run() {
        // 処理
    }    
});
t.start();

2つの書き方の結果に違いはありません。第2回の知識を使うと、前者はTemplate Methodで、後者はRunnableという関数オブジェクトを使っていますが、どちらを使うかは自由です。

最も手っ取り早くスレッドを作りたければこんな書き方ができます。

new Thread() {
    @Override
    public void run() {
        // 処理
    }    
}.start();

スレッドの使い方はこれだけです(笑)

しかし、実際はスレッドを扱うには注意しなければいけないことがたくさんあります。

スレッドは動き始めてしまったら止められない(汗;

Thread t = new Thread() {
    @Override
    public void run() {
        // 処理
    }
};
t.start();

このように初めてしまったスレッドtは、もう、run()メソッドが終了するまで外側から止めることはできません。

stop()susupend()というようなメソッドがあるように見えますが、これらは「安全ではない」と非推奨になっています。
スレッドは止められない

もし、プログラミングを失敗して、いつまでも終了しないスレッドがたくさん作られたら大変です!マシンが暴走してしまい、システムはカックカクで最終的に強制終了しなければならないでしょう。

毎回結果が異なる

複数のスレッドがあるとき、コンピュータはどのスレッドをどのくらい優先的に実行するのか、プログラマーには制御できません。そのため、全体の処理の順番が、その時時によってバラバラになります。そのため

「あれ?前回と結果が違う」

「トラブルの報告を受けて、言われたとおりに試したけど再現しない」

ということが格段に増えます。

データが壊れることがある

オブジェクトは複数のスレッドから同時に使われることを想定していない場合があります。

例えばプログラムをカフェの店員さんに例えてみましょう「お客さんのコップの中身が空なら水を注ぐ」という仕事があったとします。きっとこんなプログラムだと思います。

if (お客さんのコップは空ですか?()) {
    お客さんのコップに水を注ぐ();
}

とてもシンプルですね!店員さんが一人の時はこれで問題がありませんでしたが、大変ありがたいことに、お店に人気が出て、お客さんがたくさんいるので、店員さんを複数人雇いました。店員さん一人ひとりが一つの「スレッド」です。

class 店員スレッド extends Thread {
    @Override
    public void run() {
        while (就業時間中?()) {
            if (お客さんのコップは空ですか?()) {
                お客さんのコップに水を注ぐ();
            }
            // その他色々        
        }        
    }
}
Thread 店員1 = new 店員スレッド();
Thread 店員2 = new 店員スレッド();
Thread 店員3 = new 店員スレッド();
店員1.start();
店員2.start();
店員3.start();

さあ、みんなで仕事を始めたら大混乱!

  • まず、店員1さんが、お客さんのコップを確認します。
  • 「あ、コップが空だ!注がなきゃ!」といって水を準備します。
  • その間に店員2さんも、同じお客さんのコップを確認します。
  • 「あ、コップが空だ!注がなきゃ!」といって水を準備します。
  • 店員1さんが戻ってきてコップに水を注ぎます。
  • コップは水で満タンになります。
  • そこへ店員2さんが戻ってきました。
  • 店員2さんは、さっきコップが空だと確認したので、よく確認しないで、コップに水を注ぎます
  • コップは既に水で満タンなので、盛大にこぼれます!!

データの破壊

実際の人では、そんなことは起きませんが、複数人の人が無秩序に動いていたら大変な様子が想像できると思います。

並列プログラミングでは、「あるデータの状態を見る」それにもとづいて「次の処理をする」というプログラムを書くとき、「その間に別のスレッドが書き換えているかもしれない」という心配が常に発生するのです。

そこで、どうするかというと、店員1さんがお客さんの対応を始めたら、別の店員さんが同じお客さんを対応しないように、印を付けてしまいます。この行為を「ロック」と言ってJavaではsynchronizedと書きます。

synchronized (お客さん) {
    // お客さんに対する処理
}

このようにしておくと、別の店員さんはロックされている間、そこで処理を待ちます(別のお客さんのところには行かないです)。

固まってしまうことがある

そんな、データの破壊を防ぐためのロック機構ですが、ロックをすると別の怖い問題が発生します。「デッドロック」という現象です。

  • お客さん1をロックする
  • 何かする
  • お客さん2をロックする
  • 何かする

という店員Aさんと、

  • お客さん1をロックする
  • 何かする
  • お客さん2をロックする
  • 何かする

という店員Bさんが同時に動いていたとします。

運悪く、それぞれが「お客さん1」「お客さん2」をロックした後、それぞれ「お客さん2」「お客さん1」をロックしようとしたらどうなるでしょう。

答えは2人の店員さんは見つめ合って固まってしまいます。\(^o^)/

デッドロック

この現象を「デッドロック」と言います。デッドロックはとても怖い現象です。防ぐことが難しく、発生したらもう救うことができないからです。

デッドロックを防ぐ方法としては、

  • 逐次ロックせず一変に全部ロックする
  • ロックする順序を必ず同じにする

などの工夫があります。それでも、複雑なプログラムではうっかりどこかで考慮漏れは発生します。

今日もどこかでデッドロックでプログラムが固まっているでしょう。

まとめ

並列プログラミングは、カフェで店員さんがたくさんいるような状態だとイメージ出来ましたでしょうか?人がたくさん働くときは、秩序が必要であるのと同じように、コンピュータも、マルチスレッドの時は秩序の管理が大切になります。


Webサーバーの仕組み – メイドさんでも分かるプログラミングシリーズ vol.3

前回に引き続き、メイドさんにプログラミングを教えるためのシリーズです。

今回は前回までとうってかわって、Webサーバーの仕組みを説明します。Androidアプリを使っていると「この部分はサーバーが必要だ」「ウェブサーバーを立てよう!」という言葉をよく聞くと思います。

「ウェブ」って、「ホームページ」とか見るための仕組みではないでしょうか?なぜ、スマートフォンアプリにWebサーバーが必要なのか?Webサーバーを立てると何ができるのか、アプリ開発視点で見ていきたいと思います。

WWW(World Wide Web)は、世界中の論文をリンクする仕組みだった

昔々、と言っても1990年代なのですが、Timさん (Tim Berners-Lee)という人が、現在私達が「インターネット」だと思っている世界を考えました。

World Wide Webと名付けられたそれは、当時、できたてほやほやの「The Internet」を使って、論文を公開する仕組みとして設計されたものでした。

論文は他の論文を引用します。引用先はワンクリックでジャンプできたら便利です。そこで、引用先にリンクできる仕組みを「ハイパーリンク」を実現するテキスト文書「ハイパーテキスト」が誕生しました。「HTML」です。これは

<a href="リンク先">リンクテキスト</a>

のように書くと、他の文書にリンクできる画期的な書式でした!

Webとはくもの巣という意味です。文書と文書がリンクによってくもの巣のように世界中に張り巡らされている!それがワールドワイドなウェブの目指す世界だったのです。

この世界を実現するために、論文を読むためのソフト(Webブラウザー)と、論文を配信するホストコンピュータ(Webサーバー)が作られました。WebブラウザーとWebサーバーは互いに通信をします。通信をするための決まりごとを「プロトコル」と言います。Web専用のプロトコルとして、「HTTP (Hyper Text Transfer Protocol)」が作られました。

WWWの世界

用語のおさらい

用語 意味
World Wide Web Timさんが考えた「The Internet」上の論文配信ネットワーク
ハイパーリンク 論文から引用先論文にジャンプする画期的機能
ハイパーテキスト(HTML) ハイパーリンクを実現するための文書形式
Webサーバー 論文を配信するサーバー
Webブラウザ 論文を閲覧するためのソフト
プロトコル 通信をするための決まりごと
HTTP WebサーバーとWebブラウザの間で行われる通信のプロトコル

HTTPの仕組み

論文をサーバーから貰うには、次の情報が必要です。

  • 論文のファイル名

論文を取得する命令をGETと名付けられました。

GET /folder/hogehoge.html

この命令(「HTTPリクエスト」と言います)を受け取ったWebサーバーは、folderの中にhogehoge.htmlがあれば次の情報を返します。

  • 「あったよ!」という情報
  • hogehoge.html の内容

これらを合わせて「HTTPレスポンス」と言います。

そのうち、前者を「ステータスコード」と言います。これは数字3桁によって定められていて、例えば次のように決まっています。

  • 200: OK (あったよ!)
  • 400: BAD REQUEST(リクエストが間違ってるよ!)
  • 404: NOT FOUND(そんなファイル無いよ!)
  • 500: INTERNAL SERVER ERROR(ごめん、サーバーでエラーが起きちゃった(汗;)
  • 503: Service Unavailable(ごめん、今混んでるみたいだ!後でもう一度来て!)

とてもシンプルな仕組みですね!

HTTPの仕組み

WebサーバーがHTMLを自動生成しても良い

Webサーバーは、Webブラウザーから、リクエストを受け取ったら、ステータスコードと、HTMLページを返せば良いのです。HTMLページは、サーバーのディスク上に、HTMLファイルとして置いておくことが最もシンプルですが、別に、ファイルがなくても、その場でプログラムで作ってしまっても良いのです!

Webリクエストを受け取ったWebサーバーが、プログラムを動かす仕組みとして、CGI (Common Gateway Interface) という物が作られました。

Webプログラムの仕組み (2)

プログラムによって毎回違うページを作ることができるので便利です(例えば、現在時刻を出力!)このようなページのことを「動的ページ」と言います。反対に毎回変わらないページを「静的ページ」と言います。

Webリクエストにパラメータを渡したくなったら

CGIによって「動的ページ」が実現できると、プログラムにパラメータを与えたくなってきます。そこで、初め、ファイル名の後ろに?を付けてその後ろにパラメータをつけていく方法が考えられました。

GET xxx.html?id=1

この方法はとても便利です。現在でも、Googleの検索結果を

https://www.google.com/?q=Java

のように表すことができます。

しかし、問題がありました。

GETの仕組み

  • 大量のデータを送ろうとすると長くなりすぎる

そこで、POSTという別の方法が考えられました。これは、ファイル名を指定した後、一行空行を開けてパラメータを送るという方法です。

POST /hello.cgi

name=taro&age=20&country=Japan&.......

これによって、非常に大量の情報が遅れるようになったので、Webを使って「ご注文フォーム」が作れるようになりました。Amazonのようなネット通販の始まりです。

POSTの仕組み

時代の流れとともに、いろんな情報を送りたくなってきた

時代は流れ、WWWは論文の配信だけにとどまらず、通販やゲームのようなあらゆる用途で使用されるようになってきました。しかも、文書だけでなく、画像、音声、映像、様々な種類のデータを配信するようになります。

そうすると、HTTPもどんどん複雑になります。現在はHTTP 1.1というバージョンが主流で、次のようにいろんな情報を送ります。

GET http://www.susumuis.info/
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip, deflate, sdch
Accept-Language:ja,en-US;q=0.8,en;q=0.6
Cache-Control:no-cache
Connection:keep-alive
Cookie:
Host:www.susumuis.info
Pragma:no-cache
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36

レスポンスは

200 OK
Cache-Control:no-cache, must-revalidate, max-age=0
Connection:keep-alive
Content-Encoding:gzip
Content-Type:text/html; charset=UTF-8
Date:Mon, 04 Jan 2016 02:57:30 GMT
Expires:Wed, 11 Jan 1984 05:00:00 GMT
Pragma:no-cache
Server:nginx
Transfer-Encoding:chunked
Vary:Accept-Encoding

<!DOCTYPE html>
<html>
〜
(省略)
</html>

こんな風に、色々な情報が付与されてきます。Accept:のようにHTTPリクエストに付与される付加情報を「リクエストヘッダ」と呼びます。Cache-Control:のようにHTTPレスポンスに付与される付加情報を「レスポンスヘッダ」と呼びます。

Content-Typeヘッダについて

レスポンスヘッダに次の部分がありました。これは「コンテンツタイプ」といって、とても重要な情報です。

Content-Type:text/html; charset=UTF-8

text/htmlは、「MIME Type」と呼ばれる情報です。これは、レスポンスするデータの種類を表しています。MIME Typeには次のようなものがあります。

MIME Type 意味
text/plain テキスト文書
text/html HTMLページ
image/jpeg JPEG画像
text/javascript JavaScript
application/xml XMLデータ
application/json JSONデータ

アプリとWebサーバー

本来、Webサーバーは、WebブラウザーにWebページを配信することを目的としたサーバーでした。しかし、時代は流れ、Webブラウザだけでなく、HTTPプロトコルさえ使えれば、Webサーバーと通信ができる特性を利用して、スマートフォンアプリなどのプログラムがサーバーと通信をするために大変広く使われるようになりました。

HTTPがシンプル・高機能・有名で便利だったからです。

プログラム同士の通信では、もう、HTMLを使用する必要はありません。HTMLは人間に見た目を提供するためのフォーマットだからです。

プログラムで使う場合は、XMLまたはJSONというデータ形式が使われます。

XMLの例

<items>
  <item>
    <name>アイテム1</name>
    <price>1000</price>
    <image>xxxxxx.jpg</image>
  </item>
  <item>
    <name>アイテム2</name>
    <price>1240</price>
    <image>yyyyyy.jpg</image>
  </item>
</items>

JSONの例

{
    {
        "name": "アイテム1",
        "price": 1000,
        "image": "xxxxxx.jpg"
    },
    {
        "name": "アイテム2",
        "price": 1250,
        "image": "yyyyyy.jpg"
    }
}

アプリからの利用イメージ

サーバーはどうなっているの?

アプリ側から、サーバーの内部を意識する必要はありません。しかし、サーバーは通常次のように作られています。

Webサーバー

Apacheや、IIS、Nginxというようなサーバーソフトが使われます。

サーバープログラム

PHPや、Javaや、Rubyで書かれています。その間にアプリケーション・サーバーというソフトウェアが動いている場合もあります。

DBサーバー

Webサーバーは非常に大量のデータを扱うため、DBサーバーという専用のソフトウェアが使われることが大変多いです、MySQL、PostgreSQL、Oracleなどが有名です。

キャッシュサーバー

DBサーバーは非常に便利ですが、遅いという問題があります。そこで、高速化の目的で、別途キャッシュ用のサーバーが用意されていることがあります。Redis、Memcachedなどが有名です。

サーバーの構成例

まとめ

このように、もともと論文を配信するためであったWebサーバーはとても便利なので、アプリのデータをやり取りするために使われるようになりました。

Webサーバーは今やとても複雑な仕組みですが、呼び出す側としては、HTTPプロトコルさえ分かればやり取りができるので、内部まで意識しなくても大丈夫です!

それでは、次回は実際にアプリから呼び出す方法を説明していきます。


テンプレートエンジンMayaaについて知りたいすべての人へ

これは Mayaa Advent Calendar 2015 の25日目です。昨日は「Mayaaソースコードの読み方」でした。

マヤー(メリー)・クリスマス!

今日はクリスマスです!Mayaaアドベントカレンダーは本日が最終日です。

結局最後まで一人で書きました。はじめは心細く、4,5日目あたりが一番つらかったです。今日まで続けてこれたのは、TwitterやFecebookで「いいね」をしてくれたり、リアルで応援をしてくれた皆さんのお陰です。

ここまでを振り返って

Mayaaアドベントカレンダーを通じて、自分の持っているMayaaのノウハウを放出することで、世界で一番詳しいMayaaのノウハウ集をアウトプットしようと考えていました。

振り返ってみると、コーディングルールだったり、フレームワークとの連携だったり、拡張方法だったり、教育や、ソースコードの読み方など、本当にあらゆることを書けました。

そこで、今日はここまで書いたこと、及び、公式ドキュメントや、このブログの過去の記事、別の方の記事などをインデックス化することで、Mayaaについて調べる時のポータルページを作りたいと思います。

この、世界一詳しいMayaaのノウハウ集を、皆さんへの本当のクリスマスプレゼントとして捧げたいと思います。

Mayaaとは何か知りたい

プログラマー向け

Mayaaの使い方を覚えたい

アーキテクト・上級プログラマー向け

ここから先は、Mayaaをどのように活用するかという話になります。

Mayaaを拡張・チューニングしたい、トラブルシューティングしたい

プロジェクトマネージャ、リーダー向け

Mayaaを使ったプロジェクト運営論

豆知識系

まとめ

25日間お疲れ様でした。
いかがでしたでしょうか?

ブログを毎日書くのは初めての体験で雑なところなどもあったと思います。半ば書ければいいやなどの投げやりな気持ちも1mmくらいはあったと思います。

しかし、今時派手ではない、テンプレートエンジンのノウハウはこうでもしないとアウトプットされないでしょうから、この機会があって良かったと思います。

今後僕は、あらゆる場面でこのアドベントカレンダーの一覧の記事を活用していこうと思います。その際にあらに気づいたら自ら直して行くことでしょう。

つまり、世界一詳しいMayaaノウハウ集づくりは、ここが起点なのです。Mayaaが続く限り、将来にわたってこれらの記事をメンテし続けることを約束します。

それではみなさん、メリークリスマス、そして良いお年を!