人生シーケンスブレイク

シーケンスブレイク(Sequence breaking、シークエンスブレイクとも)とは、テレビゲームにおいて開発が想定している攻略ルートを逸脱し、ショートカットする行為のことである。

Mercari Corporate Solutions Engineering Meetup #2 レポート

mercari.connpass.com に行ってきたので今更ながらメモ。

カヤックの組織課題を解決する人事データベースシステム

カヤック紹介

  • カヤックの社員構成はディレクター, エンジニア, デザイナーで9割を占める
  • カヤックの制度紹介
    • スマイル給
      • 毎月相互FBを送り合う
    • おもしろ指数
      • 社員が楽しく働けているか評価

課題

  • 社員情報が一元管理されていない
  • 社員マスタが複数ある

解決策

  • 人事データベース案件
  • まず SmartHRと連携して動くシステムを開発(MVP: Minimum Viable Product)
    • API充実
    • 入退場もSmartHRで管理
    • 労務管理ソフトウェア
    • なのでSmartHRを従業員情報をマスタにすると楽。

成果物

  • SmartHR webhookと夜間バッチでデータ同期
  • 管理画面からポイポチ
  • 入出力はスプレッドシート
  • ロールによる権限管理, システム管理者、名簿管理者, データ編集者

環境

  • Rails, ECS(app, worker), MySQL, SQS, S3 + cloudfront

体制

ディレクター1, エンジニア1.5 で1ヶ月で作る。=> だめでした。

大変

  • webhookのリトライ回数が3日間で最大17回
  • rate limit自体を取得するAPIがないので監視がしにくいのが課題

We are "Corporate Solutions Engineers

speakerdeck.com

「経営課題をエンジニアリングで解決する」のがミッション

  • 経営課題例

    • 事業の成長に伴い増え続けるオペレーション
    • マネジメントの具体化
    • あらゆる作業の効率化と精度の向上
  • 現在のワークフローを整理

  • あるべきワークフローの構築
  • 国内外でも統一の実現を目指す

プロダクト

最近の動き

Corporate Solutions Engineering という名前

  • 最初は Corporate Engineering という名前
    • 業務フローそのものの見直しや、あるべき姿の追求をすべき。
    • -> Corporate Solutions Engineering になった。

Zapier

  • Corporate Solutions Engineering を広げて行きましょう!

メルカリ  希代のスタートアップ、野心と焦りと挑戦の5年間

メルカリ 希代のスタートアップ、野心と焦りと挑戦の5年間

Gmailを"メッセージと連絡先のインポート"でないやり方で引っ越しをした

なんで?

Googleのアカウントが気がついたら7アカウントぐらいあったのでGmailを整理しようとした。

が、 メッセージと連絡先のインポート でのShuttleCloudを使った引っ越しでは件数が多いのか途中で失敗したので。

やり方

昔ながらのPOP3 Gmailのメールを別なGmailのアドレスに移行する方法 | マイナビニュース を踏襲する形で引っ越す。

事前準備

引越し元の2段階認証を一時的にオフにする

引っ越しの際にオンだと途中で何度も失敗したので、https://myaccount.google.com/u/0/security から2段階認証を一時的にオフにする。

f:id:ShineSpark:20181127172719p:plain

安全性の低いアプリからのアクセスを一時的に有効にする

引っ越しの際に無効だとエラーが出て取り込めなかったので、 https://myaccount.google.com/u/0/lesssecureapps から一時的に有効にする。

f:id:ShineSpark:20181127172704p:plain

引っ越し

1. 引っ越し元のPOPを有効にする

Gmailの設定 > メール転送と POP/IMAP からすべてのメールでPOPを有効にする。

f:id:ShineSpark:20181127172949j:plain

2. 引っ越し先でメールアカウントを追加する

Gmailの設定 > アカウントとインポートから、 メールアカウントを追加するをクリックして、引越し元のメールアドレスを取り込む。

f:id:ShineSpark:20181127174835j:plain

f:id:ShineSpark:20181127173435p:plain

f:id:ShineSpark:20181127173528j:plain

自分は2万件ほどメールが溜まっていたが一晩程で引っ越しできました。

オマケ: フィルタのエクスポート / インポート

ここからフィルタもエクスポートできたので、引越し先でインポートすればOK。

f:id:ShineSpark:20181127173754p:plain

同報@メール5 /R.2 通常版

同報@メール5 /R.2 通常版

Engineering Manager Drink Meetup #1 レポート

mercari.connpass.com を今更ながらメモ。

VPoE挨拶

エンジニア1000人採用するとすると... エンジニアマネージャー100人 VPoE 10人必要

・明日からできるアクションを探す

メルカリのEM / PM体制

Project Owner体制の課題

  • すべての負荷がPOに集中していた

EM / PM 体制とは

  • 責務の明確化でスケールできる組織
  • 専門性を特化し、組織や個人としての強みを強化する

EM / PM 体制とは

縦横にProjectと領域がクロスしたマトリクス上の画像

PM: 従来どおり EM: Backend , iOS, Androidみたいな領域ごとのマネジメント EMはEngineering Manager TL: テックリード、幾つかのマス目の中で存在。

各ロールの役割

PM: Whatのプロフェッショナル Engineer: Howのプロフェッショナル EM: Howの最大化のプロフェッショナル Tech Lead: 役割と責任のみ定義。個別の行動はプロジェクトごとに考える

パネルディスカッション

All about engineering Manager in mercari

メモ

機械学習について

  • 全自動化はまだ難しいが、進んではいる
  • 属人化を撤廃する努力は大事。
  • 日々変わり続けるモデルの管理をどうするか
    • 極力アップデート処理を自動化する
    • 特定の人に持たせない

メルカリは3つのバリュー

  • Go Bold
  • All for One
  • Be Professional

エンジニアはBe Profetssonalを更に細分化し3つに分けている

メルカリ  希代のスタートアップ、野心と焦りと挑戦の5年間

メルカリ 希代のスタートアップ、野心と焦りと挑戦の5年間

さくらVPSにCentOS7の初期設定(sshd, zsh, yum-cron他)を行う

Dockerを動かす箱が欲しかった。

sshdの設定を行う

Web上には様々なドキュメントがあるが、ここは公式ドキュメント チュートリアル:CentOS 7(さくらのVPS)サーバ作成直後に設定しておくべき初期セキュリティ設定 – さくらのVPSニュース が最も適切だと判断して以下の設定を行う。

なお、さくらVPSでの初期設定は、クリップボードからのペーストが必要な為、さくらのVPS シリアルコンソール - β版 がオススメ。

ユーザーの作成とsudo権限の付与

# sshで接続するユーザーの作成とパスワードのセット
$ useradd <username>
$ passwd <username>

# 作成したユーザーをwheelグループに追加し、sudo可能にする
$ usermod -G wheel <username>

sshdの設定

sshdの設定は規定ポート22で尚且つパスワードでのログインが有効となっており、ブルートフォースアタックが可能な為安全とは言い切れない為、鍵認証のみに設定を変更する。

$ vi /etc/ssh/sshd_config

# 以下を編集する
Port 10022 # 10000以上の任意の番号に変更する(10022は例)
PermitRootLogin no # rootユーザーのsshログイン禁止
PasswordAuthentication no # パスワードでのsshログイン禁止

sshdの設定適用と起動の確認

$ sudo systemctl restart sshd
$ sudo systemctl status sshd

firewalldの設定も変更する

sshdのポート変更しただけでは、変更したポートが開いていない為、firewalldの設定も変更し、ポートを開く。

$ vi /usr/lib/firewalld/services/ssh.xml

# <port protocol="tcp" port="22"/> 部分を変更する
<port protocol="tcp" port="10022"/>

$ sudo firewall-cmd --reload
success

鍵の登録

ホストOSの鍵はGitHubとかで既に所有していると思うので省略。 Generating a new SSH key and adding it to the ssh-agent - User Documentation

ホストOSにて、自分の公開鍵をクリップボードにコピーする。

$ pbcopy < ~/.ssh/id_rsa.pub

次にVPS側で、authorized_keysに先程の公開鍵をペーストする

$ cd /home/<username>
$ mkdir .ssh
$ chmod 700 .ssh
$ vi .ssh/authorized_keys

# ここで先程のid_rsa.pubの内容をペーストして保存する

# 終わったらpermissionを変更する
$ chmod 600 .ssh/authorized_keys

ssh接続を試みる

諸々設定が終わったら、

$ ssh <hostname> -p <設定したポート番号>

で接続できるようになる。

ホストOSにて、.ssh/config で楽に接続できるようにする

.ssh/config に以下のような設定を書く

ForwardAgent yes
IdentityFile ~/.ssh/id_rsa
AddKeysToAgent yes
UseKeychain yes

Host sakura
  HostName <hostname(xxx.vs.sakura.ne.jpみたいなやつ>
  User <username>
  Port <sshdに設定したポート>

と、以後は

$ ssh sakura

で接続できる。

zshを利用する

$ sudo yum install zsh
$ sudo usermod -s /bin/zsh <username>

yum-cronで自動yumアップデート

$ sudo yum install yum-cron.noarch

# yum-cron.confを編集する
$ vi /etc/yum/yum-cron.conf

# yum-cron.conf内のapply_updates = yes に変更し、アップデートを有効にする。
apply_updates = yes

# yum-cronの自動起動を有効にしつつ、サービスを開始する
$ sudo systemctl enable yum-cron
$ sudo systemctl start yum-cron

他にも初期設定が必要だったら追記する。

zsh最強シェル入門

zsh最強シェル入門

Mercari Tech Conf 2018レポート

techconf.mercari.com に行ってきたメモを今更ながら。

概要

発表内容はスライドURLがあるので、以降は気になったポイントだけ箇条書きメモ。

Microservices Platform at Mercari

MTC2018 - Microservices Platform at Mercari - Speaker Deck

1年で79個にマイクロサービス化した話。

  • API gatewayを用意して、そこから各サービスにルーティング
  • マイクロサービス化する際には、application templeteを用意してカンタンに初期構築できるように
  • デプロイ周りは terraform
  • githubのcode owner機能を利用して、専門のレビューは最初だけ、各チームに任せられるようになったら、権限を与える
  • spinnaker というCDツールが便利

Mercari ML Platform

MTC2018 - Mercari ML Platform - Speaker Deck

SREだけどなぜかML Platformをやっている中河さんの話。

  • Metrics には Prometheus を利用
  • 実装は主にGo

  • なぜコンテナを使うのか

    • 再利用可能で
    • 共通の環境を構築できるので
  • でかいモデルをどうするか

    • メルカリではポータビリティを重視して、imageに含めてしまっている
      • -> 後で訊いたらケース・バイ・ケースとのこと。
    • MLモデルを lstio で A/Bテストしている
  • Katib

    • 多くのモデルが求められている
    • 画像認識で、メルカリで平均いくらで売れるのかをリアルタイムに出したりしてる

どうして僕らは決済処理をマイクロサービス化しようとしているのか

MTC2018 - Why Are We Trying to Turn Payment Processing Into a Microservice? - Speaker Deck

決済処理もマイクロサービス化することで、決済の属人性を廃止した話。

  • 疎結合, 保守性が目的
  • 決済処理に触れる人材は限定的で、スケールできないのが課題。それをマイクロサービス化することで解消させる

  • 疎結合な決済処理の課題と解決策

  • ステートマシン
  • 決済システムとの連携
  • 併行期間は現システムと新システムで併行書き込み

GO BOLD DAY

MTC2018 - GO BOLD DAY - Speaker Deck

USでもGo Boldで開発してるんだ。アメリカでも受け入れられているよ。という話

(英語頑張って聞き取ろうとしたけどだいぶ情報欠落してしまった...)

Learning to think like a Machine: How Machine Learning changes the way we solve problems

MTC2018 - Learning to think like a Machine: How Machine Learning changes the way that we solve problems - Speaker Deck

Software 2.0 の話。

Listing Service: モノリスからマイクロサービスへ

MTC2018 - Listing Service: From Monolith to Microservices - Speaker Deck

  • 時代はgRPC
  • 変更追跡用ブランチをつくって開発
    • goに移植しながら、移植した箇所を既存PHPリポジトリの変更追跡用ブランチからは削除していく
    • もし、変更追跡用ブランチとmasterブランチの間にコンフリクトが発生すれば、コードに変更があったことが検知できる。
  • PHPの例外との互換性を保つためのGoの共通ライブラリの開発
  • 正解がない中正しさを求める楽しさ

Customer Experience Improvement

MTC2018 - Customer Experience Improvement - Speaker Deck

  • ワード検索による監視とAIによる監視は共存
  • CSToolからはGraphQLで取得
    • GraphQLは、 Go + gqlgen で

Web Application as a Microservice

MTC2018 - Web Application as a Microservice - Speaker Deck

  • Renewal でなく Re-architect
  • まずは小さなチャレンジで失敗を積み重ねる

  • 移行対象の判断ポイント

  • Web Gatewayによるルーティング、制御

    • パス制御
    • 公開制御( 0 -> 100%, WIPらしい)
    • セッション制御(WIPらしい)
  • 1年で79個のマイクロサービス化。全部の仕様を把握するのは辛い

-> そこで、BFF(background for frontend)ってのを挟むようにした -> GraphQL には apollo ってのを使っている。俺らはJS好きだからGoでなくapollo

  • セッション同期問題
  • セッション管理を行うマイクロサービスを立てて解決

    • スライドの該当箇所の図を参照
  • SSR server <-> session service <-> monolicserver でセッション管理

  • 物理的の距離課題がある
    • キャッシュストレージを配置して対応

数十億規模のデータと機械学習で描く未来

MTC2018 - Leveraging billions of data items and machine learning to map the future - Speaker Deck

  • 感動出品やばい
  • ユーザーを感動させる為の仕組み

  • 感動出品v2がもっとやばい

  • バーコード読み取り機能があり、CD, DVD, 書籍などのマスタデータから補完してた
  • 表紙をバーコードに紐づけた
  • 表紙を取るだけで商品データが補完される

1人で↓の環境を1週間でつくったらしい。これがテックカンパニーだ!!!!! f:id:ShineSpark:20181127165733p:plain

メルカリにおける検索サービスの現在と未来

MTC2018 - Mercari's Search Service: Now and the Future - Speaker Deck

  • Query Rewriter : 動的クエリ調整 -> 重要
  • 名寄せ: タップ回数の多い順に

雑感

メルカリ  希代のスタートアップ、野心と焦りと挑戦の5年間

メルカリ 希代のスタートアップ、野心と焦りと挑戦の5年間

Docker Compose + Rails + Postgresでいい感じにUUID v4を利用する

やりたかったこと

Docker Compose環境下のRailsでプライマリキーをUUIDにしたかった。
ググるとPostgresでUUIDを使う為のDockerfileが散見されたが、最適な手段で実装したかった。

Rails Guides の UUID Primary Keys を参考に実施していく。

PostgreSQL >= 9.4 を使う

UUIDの実装には、Postgresの pgcrypto モジュールを利用するのでPostgres >= 9.4を利用する。 MySQLでは同様の機能がなく、MySQL上で実現するには一手間必要なので今回はPostgresを利用することとした。

version: '3'

services:
  rails:
    build: .
    command: "bundle exec rails s -p 3000 -b '0.0.0.0' -e development"
    environment:
      - TZ=Asia/Tokyo
      - WEB_CONCURRENCY=1
      - RAILS_MAX_THREADS=5
    volumes:
      - ./rails:/app
      - bundle_volume:/usr/local/bundle
    ports:
      - '3000:3000'
    depends_on:
      - postgres
  postgres:
    image: postgres:11-alpine
    restart: always
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=app_development
    ports:
      - '5432:5432'
    volumes:
      - postgres_volume:/var/lib/postgresql/data

volumes:
  postgres_volume:
    driver: local
  bundle_volume:
    driver: local

pgcrypto か uuid-ossp どちらを利用すべきか?

Active Record and PostgreSQLRuby on Rails Guides](https://edgeguides.rubyonrails.org/active_record_postgresql.html#uuid-primary-keys) に従うと pgcrypto or uuid-ossp エクステンションを有効にする必要がある。

検索する限りだと、 uuid-ossp を利用している記事も多く見つかったが、 uuid-ossp に依ると、 uuid-ossp はあまりよく維持されておらず、

注意: ランダムに生成された(バージョン4)UUIDのみが必要な場合には、代わりにpgcryptoモジュールのgen_random_uuid()を利用すること検討してください。

とあるので pgcrypto を使う。

pgcryptoエクステンションの有効化

下記のようなのマイグレーションファイルを作って実行した。

class EnableExtensionPgcrypto < ActiveRecord::Migration[5.2]
  def change
    enable_extension 'pgcrypto' unless extension_enabled?('pgcrypto')
  end
end

pgcryptoやuuid-osspを有効にするだけのshスクリプトを実行するよう拡張されたDockerfileも確認したが、ぶっちゃけ有効化にはSQLコマンドを実行するだけでよいので、マイグレーションファイルでの実行の方がDockerイメージを使い回せてスマート。

UUIDの利用する際にはマイグレーションファイルに下記のように書く。

class CreateUsers < ActiveRecord::Migration[5.2]
  def change
<200b>    create_table :posts, id: :uuid, default: 'gen_random_uuid()' do |t|
<200b>      t.text :body

      t.timestamps
    end
  end
end

のように型は uuid になり、

class CreateUsers < ActiveRecord::Migration[5.2]
  def change
    create_table :comments, id: :uuid, default: 'gen_random_uuid()' do |t|
      t.references :post, type: :uuid
      t.text :body

      t.timestamps
    end
  end
end

参照する場合には、 t.references を使う。

プライマリキーのデフォルトをUUIDにする

application.rbに下記を書けばOK

    config.generators.orm :active_record, primary_key_type: :uuid

デメリット

至るところで言われているが、first, lastメソッドが意図通りには利用できなくなる。 first, lastメソッドの順番は、 rails/finder_methods.rb at 5-2-1 · rails/rails には、

def ordered_relation
  if order_values.empty? && primary_key
    order(arel_attribute(primary_key).asc)
  else
    self
  end
end

となっている為、時系列ではないランダムなUUID v4ではcreated_atを利用した取得方法になるだろう。

どうしてもIDの順序を保証する必要がある場合には、UUID v4以外の選択肢も検討した方がよさげ。

参考

HomeBrewのアップグレードが面倒なのでLaunchAgentsで自動化した

TL;DR

  • 気が向いた時に $ brew upgrade --cleanup してたけど面倒なので LaunchAgents で自動化した。
  • 開発環境は Docker か pyenv / rbenv などで開発しているので、HomeBrewでインストールしているフォーミュラは全自動で勝手にアップデートしても問題なかった。
  • 実際超便利。

LaunchAgentへ登録

まず、BrewUpgrade.plist ファイルを作成する。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>BrewUpgrade</string>
    <key>ProgramArguments</key>
    <array>
      <string>/usr/local/bin/brew</string>
      <string>upgrade</string>
      <string>--cleanup</string>
    </array>
    <key>StartCalendarInterval</key>
    <dict>
      <key>Hour</key>
      <integer>5</integer>
      <key>Minute</key>
      <integer>0</integer>
    </dict>
    <key>StandardOutPath</key>
    <string>/Users/<user_name>/dotfiles/logs/brew_upgrade.out</string>
    <key>StandardErrorPath</key>
    <string>/Users/<user_name>/dotfiles/logs/brew_upgrade.err</string>
  </dict>
</plist>

上記では、 /usr/local/bin/brew upgrade --cleanup コマンドを毎日05:00に実行する。
スリープ状態だった場合には、スリープから復帰したタイミングで実行される。

つくったファイルを、 ~/Library/LaunchAgents/ 以下へ配置し、$ launchctl load ./BrewUpgrade.plist して完了。

~/Library/LaunchAgents $ ll
total 80
drwxr-xr-x  12 user_name  staff   384B  8 22 16:48 ./
drwx------+ 84 user_name  staff   2.6K  5 15 14:36 ../
-rw-r--r--   1 user_name  staff   768B  8 20 17:36 BrewUpgrade.plist
-rw-r--r--   1 user_name  staff   1.4K  2  7  2018 com.github.facebook.watchman.plist
-rw-r--r--   1 user_name  staff   485B  8 30 14:39 com.jetbrains.AppCode.BridgeService.plist
-rw-r--r--   1 user_name  staff   613B  8 29 11:31 com.jetbrains.toolbox.plist
-rw-r--r--   1 user_name  staff   909B  6 24 20:50 com.valvesoftware.steamclean.plist
-rw-r--r--@  1 user_name  staff   677B  4 26 11:51 org.virtualbox.vboxwebsrv.plist


~/Library/LaunchAgents $ launchctl load ./BrewUpgrade.plist
~/Library/LaunchAgents $ # 何もメッセージは出ない。

--cleanup オプションについて

--cleanup オプションを付けると、古いバージョンのフォーミュラを削除してくれる。
gitやgoなどはかなりサイズが大きく、古いバージョンを残すメリットはほぼないので最近は $ brew upgrade --cleanup にしている。 *1

$ brew upgrade --help
brew upgrade [install-options] [--cleanup] [--fetch-HEAD] [--ignore-pinned] [--display-times] [formulae]:
    Upgrade outdated, unpinned brews (with existing install options).

    Options for the install command are also valid here.

    If --cleanup is specified or HOMEBREW_UPGRADE_CLEANUP is set then remove
    previously installed version(s) of upgraded formulae.

    If --fetch-HEAD is passed, fetch the upstream repository to detect if
    the HEAD installation of the formula is outdated. Otherwise, the
    repository's HEAD will be checked for updates when a new stable or devel
    version has been released.

    If --ignore-pinned is passed, set a 0 exit code even if pinned formulae
    are not upgraded.

    If --display-times is passed, install times for each formula are printed
    at the end of the run.

    If formulae are given, upgrade only the specified brews (unless they
    are pinned; see pin, unpin).

ログファイルについて

    <key>StandardOutPath</key>
    <string>/Users/<user_name>/dotfiles/logs/brew_upgrade.out</string>
    <key>StandardErrorPath</key>
    <string>/Users/<user_name>/dotfiles/logs/brew_upgrade.err</string>

としておくと、実行時の標準出力とエラーが指定ファイルに書き込まれる。
その為、万が一アップグレード後に問題が発生した場合でも、ログを元に発生時期を辿れる。

環境ごとに専用ディレクトリをつくるのが面倒だったので、自分は dotfilse/logs/.gitkeep を配置して .gitignore で除外してそこに吐き出させるようにした。

参考

サッポロ ヱビスビール [ 350ml×24本 ]

サッポロ ヱビスビール [ 350ml×24本 ]

  • 発売日: 2016/03/15
  • メディア: 食品&飲料

*1:個別に実行したい場合には、 $ brew cleanup もアリ