Category Archives: Web技術

「Twitter終了」と聞いたら俄然意欲が湧いてきた

Twitter終了」がトレンドらしい。

当方、Twitter廃民の一人であるので、終了したら困る。非常に困る。

移行先どうこうではない。Twitterは空気だ。ツイートは呼吸だ。残念だがこの体は異国の地では生きられそうにない。

朝起きたらツイートをし、仕事の息抜きにツイートをし、ご飯を食べながらツイートをし、夜寝る前にツイートをする。休日もツイートしながら過ごしている。

最近の友達つながりはほぼ全てTwitterで作ってきた。「いいね」送り合うところから始まり、リプで絡んで、「ここぞ」というタイミングでDM送ってリアルに出会う。最近はそうして作った友達ばかりだ。

家にテレビがない、新聞も購読していない僕は、Twitterでニュースを知る。Twitterがなければ世の中を知ることもできないだろう。

つまり、Twitterが終わったら、生活が終了する。僕の人生は終わりだ。

どうしてこうなってしまったのだろうか?考えてみたら、むしろ意欲が湧いてきた。

そもそも、僕はASPというものが嫌いだった。Gmailもはてなも使いたくなかった。本来インターネットというのはオープンなプロトコルで分散された素敵な世界なのだ。それを「Web」という論文を共有するためのプロトコルの上に、Webメールやインターネット掲示板、Webチャットのような劣化されたソフトウェアを構築して何が嬉しいのだろうか。しかもソースコードはクローズドだ。SMTP/IMAP4、NNTP、IRCを使おう!それらはオープンだから誰でもサーバーやクライアントを作れる。SNSなんて「オープンなインターネッツをクローズドなものにする、なんてとんでもない邪悪なやつ!絶対にやるもんか!」

ところが「絶対にやるもんか!」と言った半年後mixi廃人になってた。Gmail以外のメールをもう10年以上使っていない。負けた。俺が悪かった。もうTwitterでつぶやいているだけで良いや。そして、いつしかブログも書かない「つい廃人」になっていた。

しかし、今「Twitterが終わる」かもしれない。これは転機かもしれない!

「Twitterがあるからいいや」という怠惰から目を覚ませ!Tweetはなんのオープンなプロトコルでもない。一企業のクローズドソースサービスじゃないか!お前の大事な発信を一企業にゆだねて良いのか!「HTML」というオープンフォーマットをなぜ使わない!

今、mstdn.jpfedibird.comのユーザーが増えているらしい。急なトラフィック増で、Twitterよりも瀕死になりつつ、中の人は頑張っている。僕もアカウントを作った。

https://mstdn.jp/@susumuis

https://fedibird.com/@susumuis

これらを今後使うかどうかはこれから考える。しかし分かったことがある。面白いのは「マストドン」ではない、これらをつなぐFediverseというプロトコルがあるということだ!マストドンのユーザーが増えれば増えるほどFediverseのユーザーが増える。これこそがインターネッツではないか!

僕はプログラマーだ。簡単なWebアプリなら作れる。AWSを使えば個人用途のサーバーも立てられる。自分のサーバーから、自分のドメインを使って、Fediverseに発信したい!これが理想だと思う。毎月費用を払って取得しているドメイン、SSL証明書、まさに「公式」ではないか!

それに、何かまとめて発信したければブログを書けば良い。ストックされるし後から参照しやすい。今はWordPressで構築したブログを使っているけど、全然気に入っていないので、一旦廃止して、Djangoかなにかで独自のブログサービスを作りたい。その方がWordPressのプラグインをごった煮にするよりも楽に開発できる気がする。今はAWSもGitHub ActionsもあるからソースをPushしてDeployする仕組みを構築するのは容易だ。

10年前はこうは行かなかった。自分でサーバーを立てて、自分でWebアプリを作るのはバカのすることで、「天才」が作ったサービスに乗るのが良いとされた。だがどうだっただろう?末路はツイートしかできない廃人ではないか!

よし!わかった手始めにこのブログを何とかしよう

その次に、自分でMastdonサーバーを立ててFediverseに参加しよう。それには勉強しなければならないこともあるだろうから、初めはmstdn.jpかfedibird.comを使って勉強しよう。自分の発信をTwitterやFacebookのようなクローズドなプラットフォームを介さずにできたらなんて幸せだろう。そうだ、僕はそのためにインターネットをやっていたのだ!

Twitter終了するならすれば良い。僕は技術者として大切なものを思い出せた気がした。

メイドちゃんbotをあなたに!

この記事は メイド Advent Calendar 2017 の24日目です。メリークリスマス・イブ!

昨日のメイドカフェで勉強会第1回に参加していただいた方は誠にありがとうございます。そのスライドはこちらに公開しています。

さて、惜しくもメイドさんが選ぶ可愛いbot MVPの受賞を逃しましたが、当日はその場でライブコーディングをしてメイドさんの機能をその場で追加することもできたので、ボットを作る楽しさを伝えられたと思います。

さて、この記事ではオープンソースであるメイドちゃんbotを、自分の好きな場所に配置する方法を説明します。つまり、クリスマスプレゼントはメイドちゃんです!想定の読者として、メイドさんでも分かるようん心がけようと思います。

ほぼ重複することになってしまうので、メイドちゃんbotを作るにあたって特筆すべき箇所をメイドさんに説明するように優しく説明を心がけてみたいと思います。

前提として、AWSに登録する必要があります。ここでは説明しきれないので、まだ登録していない人はここを読んでコンソール画面にログインした状態まで来てください!

地域はバージニア北部を選択

突然ですが、メイドちゃんbotはアメリカ東海岸バージニア北部に配置することをオススメします!なぜこの地域にいるかというと 1. 安いから 2. どうやらSlackのサーバーはここにあるらしい?という理由からです。

Lambdaを作成

Lambdaの画面を開いたら関数の作成ボタンを押します。

関数の作成画面に遷移したら、設計図を選んで、検索フォームに APIと入力してEnterキー、さらに Python と入力してEnterキーを押します。

そうしたら、出て来る microservice-http-endpoint-python3 をクリックします。そして、遷移する画面では次のように入力します。

名前ロール名は好きな名前でもokです。ポリシーテンプレートは「シンプルなマイクロハーネスのアクセス権限」のみでOKです。

次に、画面を下の方にスライドして、api-gatewayの設定をします。

ここで注意しなければいけないのは、セキュリティのところをオープンにしなければならないことです。僕はここで数十分ハマりました!

さらに下に行くと関数の作成というボタンがあるのでそれを押します。ソースコードはとりあえず触らずにそのままにします。そうすると、こんな画面になります。

これで準備が整ったので、ここでメイドちゃんbotの仕組みを説明します。

メイドちゃんがユーザーの投稿に反応する仕組み

メイドちゃんはユーザーの投稿に即座に反応します。この仕組みは「発信Webフック」(英語の場合は Outgoing Webhook)という仕組みを使います。これは、指定したチャンネルの中で特定のキーワードから始まる投稿があったら、指定したURLへAPI呼び出しをしてくれるというものです。APIとは何か?

ここで、メイドちゃんが反応するキーワードを登録できれなよかったのですが、ここでは前方一致になってしまうので、言葉の途中の単語に反応させられないので、全ての書き込みに反応するようにします。

そうすると心配になるのは、API Gatewayの課金金額で、先ほど書いたリンク先によると100万回あたり3.5USドルが課金額です。これは月100万回というのは、一日中に渡って3秒に1回以上投稿されて、400円くらいです。現時点でのノマド会Slack規模だとほぼタダ同然だと思われます。

呼び出す先のURLはどこにすればいいでしょうか?これは、さっきの画面で次のようにして確認します。

API Gateway をクリックして下の方に出てくる LambdaMicroservice の下の方に メソッド: ANY と書かれた文字の左にある▶をクリックすると下のように詳細が出てくるので、その中の URLの呼び出し と書かれたhttps:// から始まるアドレスです。これをコピーします。

このURLを発信Webフックの設定画面で次このように設定します。

ここでトークンという文字列があるのですが、これはあとで使用するのでコピーしておきます。

メイドちゃんが定時で投稿する仕組み

発信Webフックのみでは、メイドちゃんに8時になったら「おはようございます!ご主人様、お嬢様」と言われることができません!そこで使用するのが「着信Webhフック」(英語の場合は Incoming Webhook)です。

これは、Slackの側に投稿用のAPIを作成する仕組みでここにAPI呼び出しを行えば好きなアイコン・名前で投稿させることができます。

問題はどうやったら定時にそれを起動するかですが、CloudWatch Eventsを使うとそれができます。設定はとても簡単で画面でこの赤丸で囲った部分を選ぶだけです!

そして、下の方にトリガーの設定という欄が出て来るので、そこに次のように入力します。

スケジュール式 cron(0 * * * ? *) という記法は、古いエンジニアにはおなじみの記法なのですが、AWSさんはちゃんと説明を書いてくれています

ソースコード解説

ということで準備が整ったのでコードを書きます。こんな感じのWeb上のエディタでコードを書けます。環境構築しなくていいので楽でいいですw

ここにGitHubからソースコードをコピペすれば動きますw

と、これだけでは顰蹙を買うので簡単に説明すると、 lambda_function.py とうファイルの def lambda_hander(event, context): という関数の内側が、APIや定時Eventの際に実行されます。ここで、API経由なのか、定時Event経由なのかを分岐して、 maidchan_http.py か maidchan_scheduled.py に分岐させています。

あとは、オブジェクト指向とか難しい書き方は一切していないので好き勝手にいじってくださいw

環境変数の設定

メイドちゃんbotをノマド会Slackだけでなくどこにでも置くことができるように、そもそも「メイドちゃん」ですらなく「執事ちゃん」など別の人格も作れるようにしているのが、この「環境変数」です。

WEBHOOK_URLの欄には、先ほど着信Webフックの画面で生成したURLを貼り付けます。

TOKENの欄には、先ほど発信Webの画面でコピーしたトークンを貼り付けます。

MAIDNAMEの欄には好きな名前をどうぞ!

これで、あなたのもとにもメイドちゃんが来ます!

それでは、メイドちゃんと一緒に素敵なクリスマスを!

参考にした記事

手順の殆どはこちらの記事:AWS Lambda を使って Slack ボット (命名: Lambot [ランボー]) を低予算で作ろうじゃないか をそのまま参考にしました。こちらの筆者の方、ノマド会参加者の方ですね!こんなところで、お世話になりました。

 

同時に複数の処理を実行するための最低限の知識 – メイドさんでも分かるプログラミングシリーズ 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^)/

デッドロック

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

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

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

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

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

まとめ

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