カテゴリー: テクノロジー

簡単なプログラミング用語

こんにちは。開発担当のマットです。

私の初めての仕事は15歳の時でした。父の会社で、紙資料(パンフレットなど)を折りたたむ役でした。毎日8時間、紙を印刷して折りたたんで折りたたんで、フォルダーに綴じてをやっていました。つまらない仕事で時給はたったの 500 円でした。その後、日本に移住して保育園で働きながら日本語を必死に勉強して、翻訳や通訳の仕事もやりました。

そして、途中で私はプログラミングに憧れました。ソフトウェアの翻訳の仕事をしていたら自分でもソフトウェアを作りたいな!という気持ちになりました。ただ、その翻訳の仕事で多くの言葉に初めて出会いました。日本語でも英語でもないような言葉・・・英和辞典で調べても、どうしても理解できないプログラミング用語。

この記事でその用語をできるだけ簡潔でわかりやすく説明したいと思います。プログラミングは幅広い分野なので主にウェブアプリケーションを中心に説明しますが、ご興味があればぜひお読みください!

とても短い辞典ですが・・・

API

Application Programming Interface
アプリケーション通しの通話窓口ですね。

例えば、Youtube に動画をアップすると自動的にTwitterに投稿する、という設定があるとしましょう。それを成し遂げるにはYoutubeはTwitter のサイトを開いてテキストボックスにメッセージを入力し「ツイート」ボタンを押しているわけではありません。

実は Twitter が裏で API というウェブページ(みたいなもの)を用意しています。 Youtube は特定の情報を添えて(認証データ、送りたいツイートの内容)、そのページにアクセスするだけでTwitter がそれを処理してツイートを投稿してくれます。

つまり、Twitter の API は他のアプリケーション(YoutubeやFacebookや個人が作ったサイトやゲームでも) が Twitter に仕事をお願いできるところです。

ウェブサイトだけではなく、ソフトウェア・アプリケーションやハードウェアにも、APIが存在しています。

バックエンド・フロントエンド

ウェブ系のアプリケーションでよく聞く言葉ですが、バックエンドとは、ユーザーが見えない部分です。フロントエンドはユーザーが見える部分となります。

たとえば、ウェブページのレイアウトはユーザに見られる部分ので、そのサイトのフロントエンドです。逆に、ウェブページの内容が保存されているデータベースはバックエンドと言います。

クライアントサイド・サーバーサイド

フロントエンド・バックエンドには似ていますが、クライアントが「ユーザのブラウザ(Chrome、Safari等)」、サーバーが「サービス側のサーバー」と考えたら、わかりやすいです。

例えば、ウェブサイトに都道府県の一覧があるとします。都道府県の順番を並べてあげたいのですが、ウェブページを送る前に並び替えてあげるならその処理はサーバーで行うので「サーバーサイド」です。
もし、ウェブページを送る時に並び替えスクリプトもページの中に埋め込んで、並び替え処理はサーバーではなくユーザのブラウザでされる場合は「クライアントサイド」と言います。

Google の検索結果の順番はGoogle が決めるのでサーバーサイドとなります。
逆に、Wikipedia での一覧リストの順番は(だいたい)ボタンを押せば、ブラウザが並び替えをしてくれるのでクライアントサイドとなります。

キャッシュ

一度完了した処理の結果を一時的に覚えることです。
例えば、通販サイトの場合ユーザがページを見ると今セール中の商品一覧を出したいかもしれませんね。
でも、誰かがページをアクセスすると毎回毎回何がセール中であるかをわざわざデータベースに確認して処理をするより一度だけやってその結果をメモリーは一時間だけ覚えます。

こうすると、データベースへの負荷が軽くなりウェブサイトのスピードが速くなるのでユーザが快適に買い物ができます。

暗号化・復号化

とても賢い数学を使って、データをごちゃごちゃで読めない状態にして(暗号化)、また読める状態に戻す(復号化)ことです。
暗号化の数学処理で指定の数字を使いますので、その「鍵」がないと復号化できません。

ハッシュ

ハッシングとは暗号化のようです。
データをごちゃごちゃに読めない状態にできますが、暗号化と違ってそのごちゃごちゃのデータを復号化できません。

復号化できないので、あまり用途がないように思えますが、アプリケーションがパスワードを保存する時に使えます。
パスワードをデータベースに保存してしまうと万が一ハッキングされてしまった時に漏洩してしまうので、復号化できないのはそれを避けるためです。

逆に、パスワードをハッシュして、ごちゃごちゃの状態で保存します。
そして、ユーザさんがログインする時にそのログインで使ったパスワードをハッシュして照合する。
どちらのごちゃごちゃも一致していると同じパスワードを入力したと判断できます。

MD5 と SHA1 はハッシュ・アルゴリズムの種類です

まとめ

他にもたくさんありますが、用語をちょっとでも紹介できたら嬉しいと思います。ここまで読まれているということはプログラミングに少しでも興味があると思いますので、私が以前に書いた「プログラミング言語とは」の記事もぜひ併せてお読みください!


Solrのリファレンスガイドをビルドする

Solr のリファレンスガイドは、たとえばバージョン8.7のものは
https://lucene.apache.org/solr/8_7_0/index.html
というURLで閲覧できますが、リリース直後などにおいては最新のバージョンに対応したリファレンスガイドが公開されていないこともあります。
そういった場合を踏まえて、Solr のソースからリファレンスガイドを自前でビルドしてみました。

リファレンスガイドのソースは Solr のソースコードの solr/solr-ref-guide 以下にあります。ビルドに必要な手順が Readme.adoc に書かれています。

リファレンスガイドのソースは Asciidoc 形式で記述されているので、Asciidoc を扱える ruby のツール群をインストールします。

gem install jekyll --force --version 3.5.0
gem install jekyll-asciidoc
gem install slim
gem install tilt
gem install concurrent-ruby

ビルドには ivy が必要なので、まだ使ったことが無ければ準備しておきます。

ant ivy-bootstrap

ビルドします。

cd solr/solr-ref-guide
ant default

生成されたHTMLは solr/build/solr-ref-guide/html-site 以下にあります。

各所に DRAFT の文字列が見られますが、オフィシャルのリファレンスガイドとほぼ同じものをローカルに閲覧できるようになります。


Solrの記事リスト(〜2020年12月)

はじめに

ふと気付けばこのブログの Solr の記事が40本を超えていました。Solr タグで検索していただくこともできますが、もう少し見やすくなるようにトピックで分類して記事タイトルとリンクの形でリスト化してみました。

Prometheus連携

パッケージ管理

JSON Request API

Docker

日付表現

SolrCloudのリーダー選出

SolrCloud

インデックス作成

distinct

その他


SolrのCirtcuit Breakerは具体的に何を見ているのか

はじめに

前回紹介した Circuit Breaker には MemoryCircuitBreaker と CPUCircuitBreaker の2種類があります。それぞれメモリとCPUの使い過ぎに対応しているのだなと何となくは想像が付きますが、具体的にはシステムの何を参照しているのかを調べてみました。

MemoryCircuitBreaker

リファレンスによると、JVMのヒープ使用率が設定値を超えると503を返すと書かれています。MemoryCircuitBreaker の実装をみると、取得しているのは ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed() でした。これは現在のヒープ使用量をByteで返すものです。

一方、設定ではヒープの使用率を記述するので、比較するには使用率か使用量かのどちらかに変換して合わせる必要があります。
ソースを確認すると、MemoryCircuitBreaker のコンストラクタで memThreashold を読み込んだときに、ヒープの最大値 * memThreshold / 100 で閾値となるメモリ使用量を計算しておき、MemoryMXBean から取得したメモリ使用量がその値を超えたらリクエストを拒否するという実装になっていました。

CPUCircuitBreaker

CPUCircuitBreaker で監視しているのは ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverate() なので OS から取得するロードアベレージです。設定するのはCPU使用率なので、こちらも何らかの変換をしているのかと思いきや、何とソースコードではCPU使用率の閾値(%)とロードアベレージ(0以上の数値、CPUの数にもよるが通常はせいぜい10未満)を直接比較していました。

これだと使用率のつもりで75などと設定しても全く引っ掛からないのはずで不思議に思って調べてみたところ、どうやらバグのようで JIRA に Issue が作られていました。

CPU circuit breaker needs to use CPU utilization, not Unix load average

タイトルそのまんまですね。
ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverate() の代わりに ManagementFactory.getOperatingSystemMXBean().getSystemCPULoad() (0.0-0.1の間のCPU使用率)を使うことが提案されており、近いうちに修正されることと思います。


Solr 8.7で追加されたCircuit Breaker機能

はじめに

Solr 8.7 に Circuit Breaker 機能が追加されました。
いわゆるブレーカーは一定以上の電流が流れたときに回路を遮断する仕組みです。Solr においては想定を超える負荷が掛かったときにサーバが落ちる前にリクエストの受付を停める仕組みになっています。

設定方法

Solr 8.7 に付属の solrconfig.xml には Circuit Breaker 関係の設定が追加されています。説明のコメント部分を除くと以下のような内容です。

    <circuitBreakers enabled="true">
      <!--
       <memBreaker enabled="true" threshold="75"/>
      -->
      <!--
       <cpuBreaker enabled="true" threshold="75"/>
      -->
    </circuitBreakers>

circuitBreakers 要素の enabled 属性が true のときだけ Circuit Breaker 機能が有効になります。
他の部分はコメントを外して設定を有効にすれば良いのかと思ったのですが、リファレンスにはちょっと違うことが書いてあります。リファレンスによると、JVMのヒープ使用率ベースの Circuit Breaker の設定は以下の2項目です。

<str name="memEnabled">true</str>
<str name="memThreshold">75</str>

また、CPU使用率ベースの Circuit Breaker の設定は以下の通りと記載されています。

<str name="cpuEnabled">true</str>
<str name="cpuThreshold">75</str>

CircuitBreakerManager.java を確認すると以下のような読み込み処理があるので、solrconfig.xml ではなくリファレンスの記述の方が正しいようです。

      if (args != null) {
        cpuCBEnabled = Boolean.parseBoolean(args._getStr("cpuEnabled", "false"));
        memCBEnabled = Boolean.parseBoolean(args._getStr("memEnabled", "false"));
        memCBThreshold = Integer.parseInt(args._getStr("memThreshold", "100"));
        cpuCBThreshold = Integer.parseInt(args._getStr("cpuThreshold", "100"));
      }

以下は SearchHandler で circuitBreakerManager によるチェックを実行している箇所です。チェックに引っ掛かると SolrQueryResponse オブジェクト(rsp)に SERVICE_UNAVAILABLE をセットして終了していることが分かります。

    if (req.getCore().getCircuitBreakerManager().isEnabled()) {
      List trippedCircuitBreakers;

      if (timer != null) {
        RTimerTree subt = timer.sub("circuitbreaker");
        rb.setTimer(subt);

        CircuitBreakerManager circuitBreakerManager = req.getCore().getCircuitBreakerManager();
        trippedCircuitBreakers = circuitBreakerManager.checkTripped();

        rb.getTimer().stop();
      } else {
        CircuitBreakerManager circuitBreakerManager = req.getCore().getCircuitBreakerManager();
        trippedCircuitBreakers = circuitBreakerManager.checkTripped();
      }

      if (trippedCircuitBreakers != null) {
        String errorMessage = CircuitBreakerManager.toErrorMessage(trippedCircuitBreakers);
        rsp.add(STATUS, FAILURE);
        rsp.setException(new SolrException(SolrException.ErrorCode.SERVICE_UNAVAILABLE, "Circuit Breakers tripped " + errorMessage));
        return;
      }
    }

おわりに

Circuit Breaker 機能は地味ながら、安定運用のためには便利な機能といえます。今後監視項目をプラグインできるようになる可能性もあり、要注目です。