GitLab

今お世話になっているプロジェクトでも導入しはじめたので
私もそろそろ本格的にGitを習得する。

WordPressもなんだか飽きてきたので、そろそろ独自に何か作りたいなぁ
なんだか色々ごちゃごちゃしているのでフルスクラッチで作りたい。

WordPressよりもRedmineのほうが捗る気がする。
ただし、個人的にはRedmineは直感的でなく好きではないのでなんとかしたい。
Trelloなんかが合いそうなのでそちらも導入したい。
大規模には向かないみたいなこともあるみたいだけど、しばらくは無縁だろう。
。。。TrelloはWebサービスだったのか。。。Restyaboardを導入してみよう

話はそれたけど、今回はGitLab

■前提

CentOS Linux release 7.2
Gitlab 8.7.0-ce.0.el7

参考サイト
gitlab公式
GitLabをrpmでインストール

なんかほとんど公式情報で行けそうな気がする。
手順1はインストール準備。
ssh接続ができるようにしたりFirewallなどの設定外したりなど

手順2でGitLabのインストール
色々種類があるようで、下側に書いているのは例みたいなことを書いているのでSKIP

手順3で設定の反映

その後、gitlab-ctl startで実行

実施コマンド

sudo yum install curl policycoreutils openssh-server openssh-clients
sudo systemctl enable sshd
sudo systemctl start sshd
sudo yum install postfix
sudo systemctl enable postfix
sudo systemctl start postfix
sudo firewall-cmd --permanent --add-service=http
sudo systemctl reload firewalld


curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash
sudo yum install gitlab-ce


sudo gitlab-ctl reconfigure

gitlab-ctl start

デフォルト設定でFQDNで接続可能となるようにConfigファイルが作られていますが
私の場合、Apacheが動いている環境なのでポートを変更。

vi /etc/gitlab/gitlab.rb

nginx['listen_port'] = 8080

実際には事情があって違うポートにしてますが、こんな感じで修正。
もう穴だらけになってきたし、一度ちゃんと作り直したい。。。

設定変更後、再度gitlab-ctl reconfigureで設定反映。
動作確認。

gitlab

遅い・・・。
どうやらこの画面でrootユーザのパスワードを決めるらしい。
うーん。。。

wordpressと併用しているのでサブディレクトリの設定を反映。
公式のドキュメントを参考。昔に比べると大分楽になったようだ。

Gitlabで502エラーが出る。単純にサーバースペックどうにかしたほうが良い気が。サーバ起動直後はしょうがないかもしれない。
一応参考

本格的に導入するならhttpsの設定、パフォーマンス改善も視野に入れたい。

中々良さそうな認証局をみつけたのでメモ。

どうやらGitLabは開発速度優先でi18nは対応していない様子。

1Core-1GBはそろそろ限界。
せっかくだしそろそろ4Core-8GBくらいに切り替えようかなー。

apache spark 6

今回は第4回と同様sparkといいつつscala寄りのお話し。

なんとなくscalaの全体像も掴めてきたのでここからは加速して作っていけそう。

第5回ではしょぼいソース載せたけど、今回はもう少しスマートに記載。
Gitが流行っているせいか、ソースはGitで見てねパターンが多くて中々ピンとくるサイトが出ないことが多い気がする。

個人的にはまず、一枚の大きな絵で全体像が知りたいのでGitで見てねパターンのサイトは嫌いだけど
GitとWEBサイトの親密度が今後どのように上がるか期待したい。

自分の中ではこんなサイト作ればいいじゃんっていうイメージはあるけど
それを作るの面倒だなぁって言ってるからイノベーターには成れないんだろう。。
そもそもGitもってないし。

外部Storageに保存するのに抵抗はないんだけど、外部Serviceに保存するのは抵抗があるので
GitLabなど含めてこれが落ち着いたら挑戦してみよう。

import org.apache.spark.{SparkContext, SparkConf}
import org.apache.spark.graphx._
import org.apache.spark.rdd.RDD

object UserTransition {

    def main(args: Array[String])
    {
        val conf = new SparkConf().setAppName("WordCount Application")
        conf.setMaster("local")
        val sc = new SparkContext(conf)
        val livebaseUser = sc.textFile(args(0))

        val data = livebaseUser.filter(isData)
        
        // RDD[User]
        val user = data.map(parseSql)
        
        val wordCount = user.map(n => (n.area,1)).reduceByKey(_ + _)
        wordCount.sortBy(-_._2).foreach(println)
        
        sc.stop
    }

    def isData(line: String): Boolean = {
        line.startsWith("(")
    }
    
    def parseSql(line: String): User = {
        // 前後の()を除去してカンマ区切り
        val pieces = line.substring(1,line.length).split(',')        
        new User().init(pieces)
    }
    
    class User {
        var primary_id: String = _
        var email: String = _
        var password: String = _
        var name: String = _
        var area: String = _
        var birthday: String = _
        var hobby: String = _
        var creation_time: String = _
        var update_time: String = _

        def init(args: Array[String]) : User = {
            primary_id = args(0)
            email = args(2)
            password = args(3)
            name = args(5)
            area = args(6)
            birthday = args(7)
            hobby = args(12)
            creation_time = args(14)
            update_time = args(15)
            
            this
        }
    }
    
}

この辺までくるとJavaと結構変わってくる。

所感
昔から型の制約が強い言語ばかり使っているため、型推論はデメリットのほうが大きい気がする。
というよりも有効な使い方が良くわからないという感じか。
良く転がっているサンプルも型を省いているパターンが多いので変なところでハマる。
とりあえず、メソッドなどの戻り値で型を省略するとUnitになる。嬉しいパターンがあるのか知りたい。
なので、基本的に戻り値は型を書いたほうが良い。それの代入先は型推論のほうが楽といえば楽。

case classはやめました。
applyが標準でついてくるってことですが、まだこのapplyを使いこなせていない。
要勉強。

classのfield値にはvar(変更可能)で、対象の型の初期値が入るように指定(= _ )
ここの=を省略するとunitになるとかでたるい。
記述量が減る型推論とはいったい。。

コンストラクタはJavaとは異なり、色々機能が充実しているように思える
ただし、個人的にはJavaでもコンストラクタは滅多に使わないので素敵な使い方がわからない。
要勉強。

return文は省略可能。
メソッドの一番最後に書かれているものが戻り値となる。
そこで、自分自身を返したいときにどのように記述すればいいのか悩んだ。
Javaerな人は上記のサンプルだけでやっていけるかと。
※javaerで検索したら、最近はJavaerが馬鹿にされる対象なんですね。

確かに会社員やめた理由のひとつは、『勉強しない人しかいない』これだ。
これに関してはオフショアに関しても思うので、今のビジネスモデルがいつまでもつかは興味がある。

次はClass単位にファイルを分けたり、ディレクトリの構成とかかなー?

追記。
出力はピボットテーブルに組み込める形にする。ピボットテーブルは食わず嫌いしてたので勉強。

グループ化を使えばいいので日付は細かくてもOK
累計して推移を見たい場合もこちらの方法でOK

大体、これらの組み合わせでなんとかなる。
あとは粒度を変更するために情報を増やしていくことかなぁ。。。
どうやって増やすか。
これを入力させるのは嫌なので形態素解析をして情報量増やす。

apache spark 5

やりたいことがまとまらない。
単純な計算ならSQL使ったほうが簡単に感じる。

DB使わなくてもできるという点にはそれほど魅力を感じない。
DBよりももっとファジーな物を扱うためにうまれたんだろうけど
どうしても正規化すればいいじゃんという発想になってしまう。

とはいえ、その発想では簡単な例も試せないので、いくつか試してみる。

■参考
http://qiita.com/arthur87/items/197a77f37245a9e7e2d4

やりたいことはWordCount
DBのカラムは決まっているので、上記サイトの例2がやりたいことには近い。

他のサイト見てみると、
ScalaのflatMapはJavaのStringTokenizerのように1行を単語に分割したもの
map は txtファイルを1行ずつ読み込むJavaのbufferedReader.readLine()みたいな認識をすればいいぽい。
takeは配列の一部を、別の配列として出しているだけ。
なので、user.take(10).foreach(println)のforeachはコレクションに対して行っている。

今回のサンプルデータの特徴
①東京都は23区に分ける
②東京都以外は都道府県ごとに分けている
③未入力あり
④フリーフォーマットの入力ではないので、表記ゆれはない。

その他の列情報は不要なので切り落とす

DBにはいわゆるMasterDataは存在しないし、ForeigneKeyも当然ない。
なので、0件となるような出力はない。

それはそれとして、実行方法がいくつかあるが、sbtで実行すると下記のメッセージがでるようになった。

ERROR ContextCleaner: Error in cleaning thread

困ったときのStackOverFlowを見ると、sc.stopしてないからだということで追加。

一部公開できない情報も含まれているので省略しています。

import org.apache.spark.{SparkContext, SparkConf}
import org.apache.spark.graphx._
import org.apache.spark.rdd.RDD


object UserTransition {

    def main(args: Array[String])
    {
        val conf = new SparkConf().setAppName("WordCount Application")
        conf.setMaster("local")
        val sc = new SparkContext(conf)
        val livebaseUser = sc.textFile(args(0))

        val data = livebaseUser.filter(isData)
        
        // RDD[User]
        val user = data.map(parseSql)
        
        // RDD[(String, Int)]
        val wordCount = user.map(n => (n.area,1)).reduceByKey(_ + _)
        wordCount.sortBy(-_._2).foreach(println)
        
        sc.stop
    }

    def isData(line: String): Boolean = {
        line.startsWith("(")
    }
    
    def parseSql(line: String) = {
        // 前後の()を除去してカンマ区切り
        val pieces = line.substring(1,line.length).split(',')
        
        User(pieces(0),pieces(1),pieces(2)・・・一部省略)
    }
    
    case class User(
        primary_id: String,
        email: String,
        name: String,
・・・一部省略
        area: String,
        creation_time: String,
        update_time: String
    )
}

apache spark 4

apache sparkのタイトルの癖にどっちかというとScalaの話です。

Scalaのコンソール(REPL)で色々試してみて何となく理解したので
Scriptを書けばいいのかなーと思ってたけど
sparkでの実行方法がよくわからない。。

どうやらscalaファイルはsbtコマンドでコンパイルできるらしいので
script言語よりもjavaぽくコードを書いてみた。

そしてこのあたりから大分アレンジ。
自分がわかればいいや程度のメモになってきてるので
本質を知りたい人は別サイトを参考にしてください。

■sbtインストール

$ curl https://bintray.com/sbt/rpm/rpm | sudo tee /etc/yum.repos.d/bintray-sbt-rpm.repo
$ sudo yum install sbt

参考:http://www.task-notes.com/entry/20151220/1450541851

■コンパイル
sbtファイルを作る必要性があるらしいので、公式情報をベースにカスタマイズ
ディレクトリ構成なども適当に。
sbtコマンド実行するディレクトリに、コンパイルしたいソースと下記のsimple.sbtファイルを配置
参考:http://qiita.com/kanuma1984/items/45412a82536d94e18631

name := "Simple Project"
version := "1.0"
scalaVersion := "2.10.5"
libraryDependencies += "org.apache.spark" %% "spark-core" % "1.6.1"
libraryDependencies += "org.apache.spark" %% "spark-graphx" % "1.6.1"

ここが中々コンパイル通らず苦労した。。
* SampleではlibraryDependeciesが1行だけなので書き方がわからなかった
* grahpxパッケージを利用するのにどのように書くと良いのかわからなかった
* %%と%の違いがわからなかった(%%でscalaVersionを省略可能になる)

グラフ出力をしたいので最後の行を追加。
sbtはmavenみたいなものなのだと理解。
統合環境みたいなものがあると使いやすいのかなー。

あとはコンパイル対象のソース。
転がってる情報から適当に作成。

mainが欲しかったのでmain文作成。

参考ソース(一部書き換え)

import org.apache.spark.{SparkContext, SparkConf}
import org.apache.spark.graphx._
import org.apache.spark.rdd.RDD


object UserTransition{

	def main(args: Array[String])
	{
		val conf = new SparkConf().setAppName("UserCount Application")
		val sc = new SparkContext(conf)
		val livebaseUser = sc.textFile("user.sql")
		livebaseUser.filter(isData).foreach(println)
	}

	def isData(line: String): Boolean = {
		line.startsWith("(")
	}

}

ファイルの中で「(」で始まる行のみ表示される。

実行

/opt/spark-1.6.1/bin/spark-submit --class UserTransition --master local[*] target/scala-2.10/simple-project_2.10-1.0.jar

REPLではscというオブジェクトが既にインスタンス化されてつかえたが
compileするときは普通にnewしないといけなかった。

まだ全然Graph使えていないし、
http://xxx.xxx.xxx.xxxx:4040/で利用できていない。
まだまだこれから。

apache spark3

http://www.oreilly.co.jp/books/9784873117508/

こちらの本を参考に実施。
割と速攻で本の内容つまづいたり
読み替えが必要だった感じなので実際にやった内容をトレースできるようにしておく。

カリフォルニア大学アーバイン校のMachineLearningRepositoryに含まれるサンプルデータセットらしい。
手順ではLinuxから取得していたが、なぜかうまくいかなかったのでWindowsでdownloadしてSCPでアップロード。

http://bit.ly/1Aoywaq

hadoop のコマンドは使えないため省略

spark-shell --master local[*]
  • *の部分はスレッド数の指定も可能。
  • 他のサービスと併用してサーバを利用していない限り問題ないと思うのでこのまま使用。
val rawblocks = sc.textFile("/root/linkage")
  • 当たり前なのかもしれないけど、ローカルマシンのフルパスで指定可能。ただし、~/linkageはException
  • SCはSparkContextの略。
  • 指定しているのはディレクトリ
  • var, valの差は理解しておこう
rawblocks.first
rawblocks.take(10)
  • 読み込んだファイルの1行目を表示したり、10行表示
  • take(10)では改行されずに表示されるので、take(10).forearch(println)と書くと想定通りの出力。一個一個の単語はJava likeだけど値の渡し方に違和感。。

    あとはfilterやforeachなどを利用してクレンジングしていくことが第2章で語られている。
    Script言語みたいな使い方。