2016年3月28日月曜日

【Rails Elasticsearch】unexpected token at {json}

記事概要

Railsでelasticsearchを利用した時に発生したエラーの修正方法をまとめた記事です

環境

  • centos6.5
  • rails4.2.5
  • ruby2.3.0
  • rbenv
  • elasticsearch2.2.0

railsとelasticsearchの連携

elasticsearchには、railsで利用するための公式のgemが用意されています。

上記のgemを利用したところ、検索メソッド(search)を呼び出した時に

unexpected token at

エラーが発生しました。

このエラーは、rubyでjsonのパースに失敗した時に発生するエラーです。なので、すぐに修正できると思っていましたが、推測がことごとく外れ、エラーにはまってしまいました。結局、理解にほぼ丸一日を費やしてしまいました。

エラーの原因

elasticsearchのデータ投入をする際に、elasticsearch-railsライブラリではなく、elasticsearchのbulk APIでコマンドラインからデータを投入したのが原因でした。利用したコマンドは以下です。

terminal

curl -XPOST 'localhost:9200/{index_name}/{type_name}/_bulk?pretty' --data-binary "@data.json"

上記のコマンドでデータを投入すると、elasticsearch-railsで実装されているメソッドを使ってデータを取得する際に、unexpected token atが発生します。
しかし、コマンドからelasticsearchのAPIを叩く場合は、正常に動作します。

terminal

// エラーが発生せずに、うまくいく
curl -XGET 'http://localhost:9200/{index_name}/{type_name}/1'

また、railsから呼び出す場合でも、取得データ件数が0件の場合は正常に動作します。

{project_folder}/app/controllers/elastic_controller.rb

client = Elasticsearch::Client.new log: true

// 結果がo件ならエラーが発生しない。
response = client.search index: '{index-name}', type: '{type-name}', q: 'tags:tagname'
response.map {|data|
  p logger.debug data
}

このため、エラーの原因調査に時間がかかりました。

エラーパターン

elasticsearch-railsとelasticsearchの連携でエラーが発生するパターンを以下にまとめました。

データの投入方法 検索方法 結果
bulk api railsからsearchメソッド呼び出し × railsでunexpected token atエラー発生
bulk api コマンドから {index}/{type}/_searchAPI呼び出し ○ コマンドラインに結果が出力される
rails api railsからsearchメソッド呼び出し
rails api コマンドから {index}/{type}/_searchAPI呼び出し ○ コマンドラインに結果が出力される

エラー修正方法

上記のエラーパターンより、rails apiを利用してデータを投入すればよいことがわかります。
railsからのデータの投入方法は以下のようになります。

{project_folder}/app/controllers/elastic_controller.rb

client = Elasticsearch::Client.new log: true
client.create index: '{index-name}', type: '{type-name}', id: 1, body: { tags: 'tagname' }

createメソッドを呼ぶことでコード側からデータを投入できます。
railsコンソールを使ってデータを投入しても同じです
なので、本番にデータ投入の際は、railsコンソールを利用することになります。

検索実装

上記のようにrailsを介してElasticsearchのindexとtypeにデータを登録したら、railsから検索可能なことを確かめてみましょう。

{project_folder}/app/controllers/elastic_controller.rb

client = Elasticsearch::Client.new log: true

// 結果を取得してもエラーが発生しない。
response = client.search index: '{index-name}', type: '{type-name}', q: 'tags:tagname'
response.map {|data|
  p logger.debug data
}

うまく検索できるはずです。

まとめ

railsでElasticsearchを使い、elasticsearch-railsのgemを利用する場合は、railsコンソールからelasticsearch-railsを使ってデータのメンテナンスをしましょう。
railsをうまく使うには規約に従うことが重要です。自分なりのスタイルに変更するのは、慣れてきてからにしましょう。

以上。

PICK UP オススメ書籍

運営サイト(railsで作成しています)


この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

2016年3月18日金曜日

【コラム】Android案件を見積もる場合に考えておくことリストを読んで思ったこと

  • 公開日:2016年03月18日

記事概要

コラム記事。


アプリの見積もりは難しい

このサイトの意見に、ほぼ同意なので読んでみることをおススメします。
少しだけ追記事項をコラム風に記載しました。

外注するな

もし、あなたの会社がアプリの開発を外注で作成しようとしているなら、それは間違いなくリスクの高い仕事になる。
web開発とアプリ開発は違う。WEBと同じ感覚だと、まともなアプリは作れない。結局はWEBviewメインのアプリになるだろう。
もし、あなたが仕事を受注して開発する立場なら、かかった工数だけ請求できるように契約しておこう。基本は内製するべきということを認識しないといけない。

更新を続けろ

作成したアプリを2年も放置すれば、作成者か上級開発者以外は触れることができないアプリになるだろう。googleやappleのプラットフォームを利用するなら、彼らの開発の流れに乗らないといけない。彼らは国家からの命令をも拒否するくらい規約に忠実だ。君の意見など通らない。

純正のライブラリを使用しろ

アプリのライブラリはなるべく純正を利用しよう。Androidの進化はとてつもなく早い。素早くに対応していくためには、基本に忠実に作るのがベストプラックティスである。遠回りに見えるが、実は近道だ。

学習を続けろ

止まると死ぬ。

まとめ

つまり、アプリの受託開発はオススメしないってのが結論です。
周り全部が不幸になる可能性が高いです。内製しましょう。

この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

2016年3月14日月曜日

【Rails Unicorn】Unicorn logrotate

記事概要

Unicornのログローテーションの設定方法をまとめた記事です

環境

  • centos6.5
  • rails4.2.5
  • ruby2.3.0
  • rbenv
  • unicorn

はじめに

railsのWEBアプリでunicornを利用している人は多いと思います。
nginxとunicornは相性がよく、デフォルト設定でも優れたパフォーマンスを発揮します。
しかし、デフォルトだとunicornのログローテートが実行されません。
このままにしておくと、ログの容量が一気に増えてしまいます。

なので、unicornのログローテートの設定は必須です。

unicornログローテーション

unicornのログローテーションは、logrotateで設定します。
logrotateファイルに記述してもよいのですが、logrotate.d配下にunicorn用のログローテートファイルを置くのが良いでしょう。

terminal

cd /etc/logrotate.d

[root@vagrant-centos65 logrotate.d]# ls -l
total 32
-rw-r--r--. 1 root root 103 Nov 29  2013 dracut
-rw-r--r--  1 root root 185 Aug 15  2014 httpd
-rw-r--r--. 1 root root 172 Nov 23  2013 iscsiuiolog
-rw-r--r--  1 root root 844 Sep 11  2014 mysql
-rw-r--r--  1 root root 302 Sep 16  2014 nginx
-rw-r--r--  1 root root 207 Jun 10  2015 php-fpm
-rw-r--r--. 1 root root 210 Aug 15  2013 syslog
-rw-r--r--. 1 root root 100 Dec 17  2013 yum

unicornのログローテートを設定するファイルを作成します

terminal

touch unicorn

作成したunicornファイルに設定を記載します

/etc/logrotate.d/unicorn

/var/www/rails/app/current/log/*.log {
  daily
  missingok
  rotate 7
  dateext

  compress
  delaycompress

  lastaction
    pid=/tmp/unicorn.pid
    test -s $pid && kill -USR1 "$(cat $pid)"
  endscript
}

上記で設定している詳細内容は以下の通りです。

Assertion Purpose
daily ログローテーションを毎日行う
missingok 指定のログファイルがなくてもエラーを出さずに処理を続行する
rotate ログローテートの世代管理は7
dateext ログローテートを日付形式にする

スクリプト

unicornには、USR1シグナル(プロセスの動作を中断させたり、再開、変更といった合図を送るための指定)を送ると、ログファイルを開き直してくれる機能があります。

この機能を利用して、lastactionとendscriptで囲んだシェルスクリプトを実行するように設定します。

/etc/logrotate.d/unicorn

  lastaction
    pid=/tmp/unicorn.pid
    test -s $pid && kill -USR1 "$(cat $pid)"
  endscript

上記の設定の意味は、test -s $pid「ファイルが存在すれば」kill -USR1 "$(cat $pid)"「pidをUSR1でkillする」ということになります

テスト実行

設定が終了したらテストで実行します。

terminal

cd /etc/logrotate.d

logrotate -df /etc/logrotate.d/unicorn

dがデバッグモードで、fは強制となります。

terminal

[root@vagrant-centos65 log]# logrotate -f /etc/logrotate.d/unicorn

[root@vagrant-centos65 log]# ls -l
total 652
-rw-rw-r-- 1 vagrant vagrant 553843 Sep 20 12:19 development.log-20160213
-rw-rw-r-- 1 vagrant vagrant  99141 Sep 20 12:19 unicorn.stderr.log-20160213
-rw-rw-r-- 1 vagrant vagrant      0 Dec 21  2014 unicorn.stdout.log-20160213

logrotateはcronから起動されるので、以上で設定完了です。再起動は不要です。

まとめ

ログは放置しておくとあっという間にサーバーの容量を圧迫してしまいます。
ログローテーションを利用して、サーバーの容量には注意を払うようにしましょう。

以上。

PICK UP オススメ書籍

運営サイト(railsで作成しています)


この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

2016年3月6日日曜日

【Android】Error:Execution failed for task ':app:dexDebug'. Google Play Servicesの更新で起きたこと

  • 公開日:2016年03月06日

記事概要

androidのアプリ開発で発生したError:Execution failed for task ':app:dexDebug'エラーの修正方法を記載した記事です。
(この記事はJavaプログラミングでもさらに詳しく掲載予定です。)

環境

  • android sdk 23
  • Build Tools, Revision 23.0.2
  • com.google.android.gms:play-services:8.4.0

事象

Androidアプリで利用しているGoogle Play Servicesのバージョンを8.3.0から8.4.0に更新しました。その後、gradleでビルドした時にError:Execution failed for task ':app:dexDebug'が発生した。

変更前
{project_folder}/build.gradle

dependencies {
    compile 'com.mcxiaoke.volley:library:1.0.19'
    compile 'com.android.support:support-v4:23.1.0'
    compile 'com.google.android.gms:play-services:8.3.0'
    compile 'com.google.code.gson:gson:2.3'
    compile files('libs/twitter4j-core-4.0.2.jar')
    androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1'
    androidTestCompile 'com.android.support.test:runner:0.4.1'
    compile 'com.android.support:appcompat-v7:23.0.0'
    compile project(':libraries:facebook')
    compile 'com.android.support:cardview-v7:23.0.0'
    compile 'com.android.support:recyclerview-v7:23.0.0'
    compile 'com.android.support:design:23.0.0'
}

変更後
{project_folder}/build.gradle

dependencies {
    compile 'com.mcxiaoke.volley:library:1.0.19'
    compile 'com.android.support:support-v4:23.1.0'
    compile 'com.google.android.gms:play-services:8.4.0'
    compile 'com.google.code.gson:gson:2.3'
    compile files('libs/twitter4j-core-4.0.2.jar')
    androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1'
    androidTestCompile 'com.android.support.test:runner:0.4.1'
    compile 'com.android.support:appcompat-v7:23.0.0'
    compile project(':libraries:facebook')
    compile 'com.android.support:cardview-v7:23.0.0'
    compile 'com.android.support:recyclerview-v7:23.0.0'
    compile 'com.android.support:design:23.0.0'
}

発生箇所

android studioを使ったgradleビルド時。

エラー原因

Androidアプリでメソッド数が64k(65536)を超えるとビルド時やインストール時にエラーになる。このメソッド数はライブラリも含めてカウントされる。
つまり、Google Play Servicesのバージョンを8.3.0から8.4.0にあげたことにより、Androidアプリ全体のメソッド数が64k(65536)を超えてしまったために発生した。

修正方法

修正方法は以下のように複数あります。

  • メソッドを減らす。
  • proguardを使用する
  • multidex supportを利用する

ここではmultidex supportで解決する方法を選択します。

変更後
{project_folder}/build.gradle

    defaultConfig {
        // something

        // Enabling multidex support.
        multiDexEnabled true

    }

上記の変更でgradleビルドが可能になります。
また、Google Play Servicesは利用するライブラリだけをビルドすることもできます。修正する時間があればその方が良い選択です。現在のGoogle Play Servicesは全てのライブラリを導入すると容量が増えるので、必要なライブラリだけに絞る方が良いです。

結論

dexについて理解が浅い場合は、簡易的な修正をするだけでなく、この機会に学んでおくことをオススメします。

以上です。

PICK UP

運営サイト


この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

2016年3月4日金曜日

【コラム】どのプログラム言語から学ぶべきか。

  • 公開日:2016年03月04日

記事概要

コラム記事。


facebookのCEOザッカーバークはphpでfacebookを開発した。

もうすぐ4月になる。
夢と希望を胸に抱いた(?)多くの若者達が、新社会人としてデビューする。

君がITエンジニアとして社会人デビューするのであれば、プログラミングを学ぶことになるはずだ。また、新入社員でなくても4月から心機一転、プログラミングを学ぼうと思っている考えている人も大勢いるだろう。

もしそうであれば、はじめてのプログラミングにどの言語を学習しようか迷っているかもしれない。
そもそも、今からはじめてのプログラミングを勉強する場合、どの言語を選択するのが良いのだろうか。

そんなわけで、今回は、はじめて学ぶプログラミング言語について言及しようと思う。

はじめて学ぶ言語とは

君がどんなプログラミング言語を勉強するかはわからない。しかし、確実なことが一つある。君がはじめて覚えた言語が、プログラミング的な思考をするベースとなる。

君ははじめて習得したプログラミング言語を用いて、プログラミングの文法を覚え、アルゴリズムを覚え、デザインパターンを覚え、さらにはテクノロジー全般の知識を広げていくことになる。そこで得ていく知識と技術は、君の生涯の宝となり、人生の進路をも形成していく。

このコラムを読んでいる君はおそらく日本人だろう。であれば、君の思考の基本となっているのは日本語だ。
はじめて習得したプログラミング言語は、ITの世界における君の日本語となる。

プログラミング言語の学習は、最初のプログラミング言語の学習がもっとも大変である。海外の言葉の学習と同じだ。そして、一度習得してしまえば、他の言語を学ぶのはそんなに難しくはない。
だからこそ、最初はひとつの言語に集中して深く学習するのをオススメする。逆に、全てのプログラミング言語を浅く学んでも、あまり役には立たない。

だから、君と最初のプログラミング言語は付き合いが長くなる。なので、あなたが一番好きな(興味のある)言語を選ぶべきだ。

もしかしたら、君が好きな言語は仕事として必要な言語とは別かもしれない。ならば、仕事の後に自宅に帰ってその言語を利用してプログラミングするべきだ。もしくはツールの作成に利用するべきだ。

「続けること」「好きになること」。

この2点こそが、君を素晴らしい技術者へと変化させるのである。

とはいえ、選択肢がないと迷ってしまうかもしれない。なので、ここでは個人的にお勧めの言語を3つ選んでみた。

Java

君がエンジニアとしてずっとやっていくつもりならjavaを選ぼう。この世界はCとJavaが発展させたと言っても過言ではない。CとJavaはプログラミングの基礎である。
とはいえ、WEB開発、スマホアプリ開発においては、C言語は触れる機会が少ないだろう。なので、今からならjavaを選択するのが良いだろう。

しかし、もしかしたら君のメンターはC言語を勉強することを激しく勧めてくるかもしれない。しかし、WEB開発やスマホアプリ開発が君の仕事なら、その提案は断ってよい。
C言語は必要になってから学習すればよい。長くIT業界でやっていれば、WEB開発エンジニアでもCに触れる機会が必ず出てくる。その時の君は、すでに大きな技術が備わっているはずだ。その時、必要な箇所のみを学習すればよい。

また、これからjavaを学習するならandroidの開発を中心に据えるとよいだろう。androidのフレームワークは特殊だが、javaを学習するには優れたフレームワークだ。android内のコードには、先人の様々な英知が詰まっている。コードを書いて書いて、書きまくると良い。

一方で、WEBアプリをjavaで作ろうとしているなら、やめるべきだ。WEBアプリを作るなら、RubyかPythonを選ぼう。
今の時代にjavaでWEBアプリを作るのは効率が悪い。大規模なWEBアプリでなければ、javaの力の恩恵を受けることは少ないだろう。

Ruby

君がWEBアプリを作って世界で勝負をしたいと考えているならRubyを選ぼう。RubyのデファクトフレームワークであるRuby on Railsは君をその舞台に連れて行ってくれる。
しかし、同時に、Ruby on Railsは君の心を何度も打ち砕こうとするだろう。なかなか思い描いたようにWEBアプリは作れないかもしれない。その時は、仕様がレールに沿っているかも考えよう。Ruby on Railsを使いこなすには、それなりの知識と技術を身に着ける必要がある。

また、WEBアプリを作り終えると、すぐにバージョンアップしたRuby on Railsが登場するかもしれない。君は更新作業を開始し、またエラーと格闘しないといけない。バージョンアップを放置すれば、そのWEBアプリは誰も触れることのできないパンドラの箱のようなWEBアプリになる。

だが、粘り強くバージョンアップを続けていけば、時代にマッチした素敵なWEBアプリを顧客に提供し続けることができる。
僕も今は、メインでRuby(Ruby on Rails)を使っている。

Python

最後の言語はpythonだ。もし君が機械学習や人工知能の仕事に就きたいのなら、pythonを選択することをおすすめする。pythonは素晴らしい言語だ。計算をするのに優れたライブラリが用意されている。

また、君がなにげなく利用しているyoutubeもpythonで作成されている。pinterestも同様だ。WEBアプリを作成するにも効率が良い言語である。まさに万能の言語だ。

一方で、pythonの欠点は日本での需要がほとんどないことだ。当然、日本語のドキュメントも限られている。pythonを使うのに英語ができないのは、竹槍でB29と対峙するのと同じだ。機械学習や人工知能の学習も英語での学習が基本となる。

まとめ

現状でのオススメ言語は、「Java」「Ruby」「Python」とした。
もちろん、これらの言語が嫌だという人もいるだろう。その場合は、自分の好きな言語を学習すると良い。ザッカーバークはphpで世界最大のSNSとなるfacebookを開発した。

大切なのは、プログラムで何をするかであり、プログラム言語そのものではない。プロジェクトに応じてプログラム言語を変えることは日常茶飯事だ。
英語圏なら英語を使い、中国なら北京語を使い、日本であれば日本語を使うのが当たり前だ。
日本(ruby)で英語(java)を使う必要はない。
システムでも同様で、そのときそのときに応じた言語を使えばよいと思う。

せっかくプログラム言語を学ぶのなら、長く続けて欲しい。
そして、君が世界の生活をより豊かにするようなシステムを作りだすことを期待している。
それが可能なのが、プログラム技術である。

参考サイト

この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加
Related Posts Plugin for WordPress, Blogger...