読者です 読者をやめる 読者になる 読者になる

UUUM攻殻機動隊

UUUMのエンジニアによる技術ブログです

スクラムどうでしょう?

こんばんは! エンジニアのナカハシです。

UUUMコンテンツの総合アカウント「UUUM FANS」、カリスマブラザースのファンサイト「CBF」がオープンしました! 開発に携わるUUUMエンジニア陣も、これらのサイトがよりよいサービスになるよう、日々精進しまくっております!!!!!!!!

さて、UUUMでのソフトウェア開発は、どのチームもアジャイルで進めています。

「アジャイル開発」と一口にいっても、体制やアウトプットの形式によって様々な手法が考えられます。

今回はそのうちの一つである「スクラム」の概要を軽くまとめてみました。

続きを読む

サーバーレスアーキテクチャの事例まとめ

エンジニアのタナカです。

2015年にAWS Lambdaがリリースされて以降、サーバーレスアーキテクチャの注目度が高まっています。
サーバー管理が不要、スケーリングも自動、しかも安いと夢のような技術ですが、これまでの開発手法とは異なるため導入に躊躇している方も多いと思います。
弊社での利用はまだこれからですが、日本でのサーバーレスの採用事例も増えてきたようなので参考までにまとめて見ました。


thinkit.co.jp 日経電子版アプリ、Gunosyのほか、ゲームのバックエンドでの採用事例が紹介されています。

www.stylez.co.jp IoT通信サービスTrackrr.ioのアーキテクチャが紹介されています。spring bootを組み合わせたマイクロサービスで作られているようです。

www.publickey1.jp 一休ではサムネイル生成でLambdaを利用しているようです。

www.techscore.com イベント来場者管理システムのデータ登録APIにLambdaが利用されているようです。

www.jiji.com 有料動画配信サービスでLambdaを全面採用し3ヶ月でシステムを完成させたそうです。


2016後半から国内でもサーバーレスの採用事例が増えているようです。
IoTや動画配信システムで全面採用した事例も出てきて、2017年はさらに利用が広がりそうですね。

RailsアプリをUnicornサーバー&Symlink切り替えデプロイ環境下で安定運用する

nazoです。

Railsアプリを本番で運用する際、アプリケーションサーバーは現在ではUnicornかPumaを使うことが多いと思います。特にPumaを使う方が多いと思いますが、現在のプロジェクトではUnicornで構築しております。

Webサーバーを安定運用させるには無停止で再起動するGraceful Restartは必須ですが、いくつか注意すべき点があったので、運用例と共に紹介したいと思います。

続きを読む

UUUMにて、次世代のITを担う方々へ向けた「未踏」説明会がおこなわれました

こんにちは、新人エンジニアのハトネコエです。
12月17日(土曜日)、UUUMオフィスにて、
一般社団法人未踏がおこなう「未踏」事業の小中高生向け説明会
『未踏の魅力を知ろう - 2017年度未踏説明会』がおこなわれました。

「未踏」事業は国の『突出したIT人材の発掘と育成』を目的としておこなわれているもので、
25歳未満の方であればどなたでも研究テーマの応募ができ、採択されれば国のプロジェクトとして全力で支援されます。
誰も見たことのない未来の技術を実現しようと世界を切り拓く人たちの研究内容が知れ、説明会中はすごさのあまり「ほわぁ………」という気持ちでした。

Twitchの方々によって説明会は全世界へ生配信され、
アーカイブはこちらからご覧になることができます。
講演内容を覗いてみたい方はアクセスを。モノづくりの気持ちを思い出させてくれます。

さて、今回UUUMが会場提供をしたきっかけには、
UUUMのCTOである尾藤正人さんが「未踏」出身者という経緯があります。
尾藤さんも登壇されたのですが、当時なにを研究されていたのかという話は登壇テーマにはありませんでしたので、
このブログではそこに焦点を当てインタビューしてみたいと思います。

続きを読む

正規表現エンジン入門 - 正規表現の概念

おはこんばんちは!! 尾藤 a.k.a. BTO です。

みなさん正規表現使ってますでしょうか? 正規表現はプログラムを書く時にも使いますが、エディタや grep で検索するときなど文字列検索をするときには非常にお世話になっていると思います。 正規表現を書くことはあっても、正規表現がどのように処理されているのかを知らない人も多いのではないでしょうか。

今回、正規表現エンジンがどのような仕組みでできているのかを社内勉強会でやったので、その内容をまとめてみます。

正規表現技術入門

正規表現エンジンに関しては、正規表現技術入門というとてもわかりやすい本が出ています。

正規表現技術入門 ――最新エンジン実装と理論的背景 (WEB+DB PRESS plus)
新屋 良磨 鈴木 勇介 高田 謙
技術評論社
売り上げランキング: 117,162

実は本ブログで書いた内容も、かなりの部分はこの本から得た知識になっています。 正規表現エンジンに興味のある方には、ぜひ読んでみてください!!

チョムスキー階層

ノーム・チョムスキーという著名な言語学者がいます(ご存命です)。 チョムスキーは、形式言語を定義する形式文法を階層化しました。 これをチョムスキー階層と呼びます。

チョムスキー階層は次の4つに分かれます。

  • 制限のない文法
  • 文脈依存文法
  • 文脈自由文法
  • 正規文法

上の階層ほど、言語としての自由度が高く、計算機で処理するのが難しくなります。 名前から想像できると思いますが、正規表現はこのチョムスキー階層で言うところの正規文法にあたります。

正規表現とは

では、正規表現とは一体何なんでしょうか?

先程のチョムスキー階層で出てきた正規文法で定義された言語が正規言語です。 そしてこの正規言語を表現するための記法が正規表現です。

このように元々は正規言語を表すために作られた正規表現ですが、みなさんご存知のように現在では文字列のパターンマッチングのために使用されるようになっています。

正規表現による文字列の検索はとても便利だったので、いろんなツールに導入されました。 より便利にするために様々な機能拡張がおこなわれてきました。 そのため現在では本来の正規表現の定義を超えた機能を実装とかも出てきています。

世界初の正規表現エンジン

世界初の正規表現エンジンは、QEDというテキストエディタの文字列検索機能として実装されました。 この世界初の正規表現エンジンを実装したのがケン・トンプソン(ご存命です)です。

ケン・トンプソンは知る人ぞ知る超有名な計算機科学者で、業績は多岐に渡ります。 彼の業績には次のようなものがあります。

  • UNIX
  • C言語
  • 正規表現エンジン
  • ed(ラインエディタ)
  • UTF-8
  • Plan 9
  • golang

ちょっとやばいですね... レジェンド過ぎます...

正規表現の限界

とても便利な正規表現ですが、チョムスキー階層で最下層に分類されているところからも分かる通り、その能力には限界があります。良く出てくる例としては、正規表現は括弧の対応を処理することができません

つまり、次のような文字列、左に現れた開き括弧と同じ数の閉じ括弧が右側に現れるような文字列を処理することができません。

((( ... )))  # このような文字列は正規表現で処理できない

括弧の対応が組み込まれている文字列はいろいろとあります。

  • 四則演算
  • プログラミング言語
  • HTML, CSS のような形式言語

これらの言語を処理する能力は正規表現にはありません(もちろん部分文字列を処理する能力は当然あります)。

メールアドレスは正規表現で処理できるか?

よくある話として、メールアドレスは正規表現でできるかどうかという話があります。 結論から言うと、本来の定義での正規表現でメƒールアドレスを表現することはできません。

メールアドレスはネストしたコメントを持つことができます。 上記の ((( ... ))) のような正規表現で処理できない構造は、ネストした構造を持つために使われるものですので、正規表現では表現できないことになります。

ただし、現在の正規表現には様々な拡張が行われていて本来の正規表現の能力を超える処理を提供しているものがあります。 具体的には、再帰の機能を持った正規表現エンジンでは、ネストしたコメントを表現することができます。 Perl や Ruby で使われている正規表現は再帰の機能を持っているので、メールアドレスを正規表現で処理することができます。

正規表現の定義

ちょっと前置きが長いですが、正規表現の話を進めましょう。 そのために、まずは正規表現を定義します。 正規表現の定義は次のようになります。 このでの定義は文字列処理に使われる正規表現について考えています。

  • 文字は正規表現である
  • X, Y が正規表現とする
    • XY は正規表現である(連接)
    • X | Y は正規表現である(選択)
    • X* は正規表現である(繰り返し)

本来の正規表現では、空集合も受け付けるので、空集合は正規表現であるという定義が入りますが、ここでは省略しています。 なぜなら文字列処理を目的とする場合は、空文字(空集合)を処理する必要がないからです。 実際、文字列処理の正規表現では空文字を表現する記法がありません。

正規表現3つの基本演算

上記の正規表現の定義を見ると、正規表現は基本的な演算の組み合わせで構成されていることがわかります。 その基本的な演算は次の3つになります。

  • 連接
  • 選択
  • 繰り返し

正規表現はとても便利なものなので、様々な拡張機能が実装されてきましたが、この基本演算の組み合わせで表現することができます。

一部上記の基本演算では表現できない機能もあります。 メールアドレスのところで出てきた再帰がそれにあたります。 この様な機能は便利なものではあるのですが、同時に正規表現の定義から外れてしまっているので数理的な意味を失うことにもなってしまいます。

連接

連接は非常に単純で、正規表現を繋げたものになります。 例えば次のような正規表現が連接になります。

abcdef

選択

選択は複数の正規表現から選択する機能です。 複数の正規表現を | で区切ります。 例えば次のような正規表現は、a, b, ab のいずれかの文字列を表します。

a|b|ab

繰り返し

繰り返しは、正規表現の0回以上の繰り返しを表します。 繰り返しの記号は * です。 例えば次のような正規表現は、aの0回以上の繰り返しを表します。

a*

拡張演算

上記の3つの演算に加えて、現在の正規表現では様々な拡張機能を提供しています。 機能はいろいろありますが、どれも3つの基本演算の組み合わせで表現することが可能です。

全てではありませんが、拡張された演算には次のようなものがあります。

  • プラス演算: 1回以上の繰り返し
  • 疑問符演算: 0回か1回
  • 範囲量指定: n から m回の繰り返し

正規表現エンジンの実装方法

では、正規表現エンジンの実装をみていきましょう。 正規表現エンジンの実装方法は大きく分けると2種類あります。

  • DFA型
  • VM型

では、実装の説明を... と思ったのですが、長くなってきたので次回以降で。

まとめ

正規表現エンジン入門と言いつつ、エンジンの説明までたどり着きませんでした... ですが、正規表現の基本的な概念は理解していただけたのではないかと思います。 正規表現エンジンの実装には、正規表現自体への理解は必要不可欠です。

次は有限オートマトンと呼ばれる DFA での実装について書いていきます。

Elasticsearchの基本的な使い方と弊社サービスでの利用

UUUMに入って2か月のkitabatakeです。 任される仕事が多くなってきて、面白くなってきたと思う一方、ちゃんと捌ききれるかどうかのせめぎ合いの日々です。

弊社のシステムでも使っている、Elasticsearch の基本的な使い方と、弊社内での利用方法など書いてみたいと思います。

Elasticsearchとは?

全文検索エンジン

大量にあるドキュメントデータの中から、目的のワードを含むドキュメントデータを検索する。 検索するということに特化したミドルウェア

RDBMSとの違い

「RDBMS」は、検索条件にマッチするデータ取得できる。

Elasticsearchのような「全文検索エンジン」は、「検索条件との関係性/関連性が高いデータを抽出して返す」という特徴がある。

RDBMSにも全文検索機能が搭載されているものもあるが、検索機能に最適化されている分、パフォーマンスや機能性は一般的に「全文検索エンジン」の方が優れている。

データの登録から関連性の紐付けについての概要

下記資料のサザエさんのところにかなり解りやすく説明されています

ElasticSearch入門 // Speaker Deck

実際に試してみる

弊社のクリエイターポータルサイト「CREAS」では素材の検索にElasticsearchを使っています。 同じようなケースの想定で、解りやすくミニマムのデータ構造で試してみます。 Elasticsearchがインストール済みの想定で進めます。

簡易素材データ

  • ID
  • name
  • description

Indexの作成

Indexとは?

データを保存する場所。 RDBMSのdatabaseのようなもの

indexの一覧を確認するコマンド

curl -XGET 'localhost:9200/_aliases?pretty'

---

{}

?pretty はレスポンスのjsonを見やすく表示させるオプションです。 まだ何もしていないので、空のレスポンスが返ってきます。

indexを作成します。今回はindex名を material_test とします。

curl -XPOST 'http://localhost:9200/material_test'

でindex一覧を確認

curl -XGET 'localhost:9200/_aliases?pretty'
---
{
  "material_test" : {
    "aliases" : { }
  }
}

作れました。

Mapping

外部データをElasticsearch上でどのようなスキーマとして表現するか定義することをmappingと呼びます。 (Elasticsearchチュートリアル - 不可視点より。参考: Mapping のイメージ)

マッピングの確認

curl -XGET 'localhost:9200/material_test/_mapping?pretty'
---
{
  "material_test" : {
    "mappings" : { }
  }
}

Elasticsearchはデータを投入すると、自動的にマッピングを作成してくれるので、まずはそれを試してみます。 データを投入します。

curl -XPUT 'localhost:9200/material_test/material/1' -d '{
    "title" : "アラビアンジュエル",
    "description" : "アラビアンナイトな雰囲気の怪しい楽曲です。 ゲームなどの、砂漠の街のイメージなどにおすすめです。"
}'

で、Mappingの確認

curl -XGET 'localhost:9200/material_test/_mapping?pretty'
---
{
  "material_test" : {
    "mappings" : {
      "material" : {
        "properties" : {
          "description" : {
            "type" : "string"
          },
          "title" : {
            "type" : "string"
          }
        }
      }
    }
  }
}

name, descriptionのtypeがstringと定義されました。 これでデータが検索できる状態になったので、 WEB UIから検索等のできるプラグイン

github.com

を使って試してみよう。

インストール後に、 http://localhost:9200/_plugin/inquisitor/#/queries にアクセスします。

Queriesタブで検索クエリーの発行、Analyzersタブで文章の解析結果が確認できます。

Queries画面

f:id:sissoko:20161122090137p:plain

Analyzers画面

f:id:sissoko:20161122090157p:plain

自動的に生成されたmappingでは日本語をうまく解析できていないですね。

いい感じに検索できるようにする

日本語対応 analyzer kuromoji(http://www.atilika.org/) というものがあり、これを設定することで、日本語の検索がいい感じになります。

mappingを手動で設定するコマンド

curl -XPUT 'localhost:9200/material_test' -d '
{
  "settings": {
    "analysis": {
      "filter": {
        "pos_filter": {type: "kuromoji_part_of_speech", stoptags: ["助詞-格助詞-一般", "助詞-終助詞"]},
        "greek_lowercase_filter": {type: "lowercase", language: "greek"}
      },
      "tokenizer": {
        "kuromoji": {
          "type": "kuromoji_tokenizer"
        },
        "ngram_tokenizer": {
          "type": "nGram",
          "min_gram": "2",
          "max_gram": "3",
          "token_chars": [
            "letter",
            "digit"
          ]
        }
      },
      "analyzer": {
        "kuromoji_analyzer": {
          "type": "custom",
          "tokenizer": "kuromoji_tokenizer",
          "filter": [
            "kuromoji_baseform",
            "pos_filter",
            "greek_lowercase_filter",
            "cjk_width"
          ]
        },
        "ngram_analyzer": {
          "tokenizer": "ngram_tokenizer"
        }
      }
    }
  },
  "mappings" : {
    "material" : {
      "properties" : {
        "name" : {
          "type" : "string",
          "analyzer": "kuromoji_analyzer"
        },
        "description" : {
          "type" : "string",
          "analyzer": "kuromoji_analyzer"
        }
      }
    }
  }
}'

急に複雑になってしまったので、細かく説明していきます。

まず Analyzerとは?

Analyzer = Tokenizer + Filter です。

Tokenizer?

文字を分割するもの

  • ngram_tokenizer:

    最小と最大の文字と対象にする文字の種類を設定し、分割する

  • kuromoji_tokenizer:

    日本語に対応したプラグインのtokenizer

Filter?

分割した文字を整形したり、フィルタリングするもの

  • kuromoji_baseform

    動詞と形容詞を原型に戻す。

  • pos_filter

    特定の品詞を除外し、マッチ精度を高める

  • greek_lowercase_filter

    英字を小文字化する

  • cjk_width

    全角英数字を半角に直し、半角カタカナを全角に直すなど、漢字圏の文字の全半角を整え、マッチしやすくする

設定を確認する

Analyzer, Tokenizer, Filterが何かわかったところで、上の設定のjsonを見ると、 settingsのところに、tokenizer, filter が設定されていて、それをanalyzerに設定している。 mappingsのところで、各フィールドにanalyzerを指定している、というのが解ると思います。

コマンド実行後にmappingを確認

curl -XGET 'localhost:9200/material_test/_mapping?pretty'
---
{
  "material_test" : {
    "mappings" : {
      "material" : {
        "properties" : {
          "description" : {
            "type" : "string",
            "analyzer" : "kuromoji_analyzer"
          },
          "name" : {
            "type" : "string",
            "analyzer" : "kuromoji_analyzer"
          }
        }
      }
    }
  }
}

文章の解析がいい感じになりました。

f:id:sissoko:20161122091408p:plain

以上が基本的な使い方でした。

弊社サービス「CREAS」ではどのように使っているか

creators.uuum.jp

CREASではクリエイター向けに様々な動画作成向けの素材を提供しています。

フレームワークはSymfonyを使っていて、

SymfonyでElasticsearchを簡単に扱えるFOSElasticaBundleの紹介 - UUUM攻殻機動隊

同ブログのnazo様の記事にSymfonyからElasticsearchをどのように使っているかが解りやすくまとめられています。

app/config/elastica.yml

に 上で話していた、analyzerなどの設定が書かれているので、見てみましょう。

settings部分抜粋

settings:
    index:
        analysis:
            tokenizer:
                kuromoji:
                    type: kuromoji_tokenizer
            analyzer:
                kuromoji_analizer:
                    type: custom
                    tokenizer: kuromoji
                    filter:
                        - kuromoji_baseform
                        - lowercase

kuromoji_analyzerが設定されています。

materialのmapping部分抜粋

material:
mappings:
id:
    type: integer
    index: not_analyzed
download_count:
    type: integer
    index: not_analyzed
type:
    type: string
    index: not_analyzed
material_categories:
    type: nested
    properties:
        id:
            type: integer
            index: not_analyzed
material_tags:
    type: nested
    properties:
        id:
            type: integer
            index: not_analyzed
        name:
            type: string
            index: not_analyzed
name:
    type: string
    index: analyzed
    analyzer: kuromoji_analizer
description:
    type: string
    index: analyzed
    analyzer: kuromoji_analizer
artist_name:
    type: string
    index: analyzed
    analyzer: kuromoji_analizer
artist_name_not_analyzed:
    type: string
    index: not_analyzed
    property_path: artist_name
artist_katakana:
    type: string
    index: not_analyzed
is_downloadable:
    type: boolean
    index: not_analyzed

name, descriptionなどはkuromoji_analyzerが設定されています。

id_downloadableなどのフラグは解析してもしょうがないので、 index: not_analzyed の指定がされています。 これにより、単純なフラグのon/offでの検索に対応することができます。

クエリ発行箇所

音源素材のtypeと、検索ワードから関連するデータを取得するメソッドの内容を一部抜粋

/**
     * キーワード検索結果でページネーション
     *
     * @param string $type MaterialType
     * @param string $word 検索キーワード
     * @return FOS\ElasticaBundle\Paginator\TransformedPaginatorAdapter
     */
    public function findPaginatedByKeywords($type, $word)
    {

...

        [
            'match' => [
   'is_downloadable' => true,
            ]
        ],
        [
            'query_string' => [
   'fields' => ['name', 'description', 'artist_name'],
   'query' => '"' . $word . '"',
            ],
        ],
        [
            'match' => [
   'type' => $type,
            ]
        ],

...

        return $this->elastica->createPaginatorAdapter('Material', $query);
    }

ダウンロードが可能(is_downloadable)で、対象の音源素材の種別から、 name, description, artist_name と検索ワードの関連があるデータを取得しているということが、わかると思います。

まとめ

kuromojiのfilterやtokenizerがよくできていたり、各種プラグインがよくできているので、触っているだけで結構面白くて、全文検索に対する理解も深まるのでオススメです!

参考にさせていただいたサイト

CSRF(クロスサイトリクエストフォージェリ)

エンジニアのspin13です. しばらくの間,地球そのものが敵となって花粉に苦しめられていました.

今回は クロスサイトリクエストフォージェリ(以後CSRF)について書きます.

続きを読む