サクサク読めて、アプリ限定の機能も多数!
トップへ戻る
TGS2024
qiita.com/joker1007
Kafka StreamsにはWindow Aggregationという仕組みがある。 特定の時間間隔毎にイベントの数を数えたり等を行うための機能だ。 で、それを利用してユーザー毎のイベント実行回数をカウントする処理を書いていたのだが、何故か結果が合わない。 テストコードでは再現しないし確率的に結果がズレるという状況が発生した。 物凄くハマったが、原因は未来のtimestampが来た時の処理にあった。 検証バージョン kafka-streams-2.4.0 問題の詳細 一度書き込んでバックエンドのKafkaトピックまでデータが届いているにも関わらず、データを再度取得しようとした時に既存の集計カウントが取得できない。 そのためカウントがリセットされるし、他の箇所でも結果が取得できない状態になっていた。 確実にput処理は行われている 紐付いているKafkaのトピックには確実にデータが届いてい
AWSの新しいロードバランサであるNLB(Network Load Balancer)を使ってfluentdのforwardパケットを分散してみたので、レポートをまとめておく。 NLB自体については、クラスメソッドのブログ等で紹介されているのでそちらを参照するのが分かり易い。 静的なIPを持つロードバランサーNetwork Load Balancer(NLB)が発表されました! 試してわかった NLB の細かいお作法 ざっくり言うと、TCPプロトコルを対象にしたALBって感じ。 ターゲットグループはポートレベルで設定できるので、コンテナ環境と相性が良い。 ポート違いで複数fluentdが立っていても同じグループとしてまとめて分散できる。 利用までの流れ ターゲットグループを作成し、TCPレベルでコネクションが貼れるかのヘルスチェックの設定をする インスタンスもしくは対象IPと、ポートの組を
ある時間になったらジョブを起動するスケジューラを実装したgemは、世の中に色々とあります。 javan/whenever: Cron jobs in Ruby adamwiggins/clockwork: A scheduler process to replace cron moove-it/sidekiq-scheduler: Lightweight job scheduler extension for Sidekiq しかし、いまいち自分の用途に合致するものがなかったので自作しました。 基本的に上記のgemは、事前に設定ファイルを書いてあるジョブクラスをトリガーするスケジュールを登録するスタイルです。 システムの運用に関わるバッチのトリガーとかならそれでも便利なんですが、サービスの機能としてユーザーにスケジューラを提供したい場合に困ります。 例えば、ユーザーが毎日12時に広告メール
できるだけproductionに近い状態でAWSの各コンポーネントと通信したり、DBのデータを取得できる環境で、アプリケーションの動作確認をしたいことがある。 共有の開発者用のステージング環境等で、それを行うこともできるが、開発者が増えてくると利用が競合して順番待ちが発生したりとかする。 RDBのスキーマを弄ったり、データ投入フロー自体を修正する様な場合は、排他的に利用するべきだが、必ずしも全ての修正がそんなにヘビーな修正ではない。 コンテナの独立性を利用すれば、開発者個別にもっと自由に使える環境を開放できるはず。 というわけで、terraformと組み合わせて、そこそこ手軽に作る方法を考えてみた。 resource "aws_alb" "per_developer" { count = "${length(var.users)}" name = "${element(var.users,
この記事は、大江戸Ruby会議06で発表した Docker時代の分散RSpec環境の作り方 // Speaker Deck の補足です。 何人かに質問されたことや、良いことばかりじゃなくて現状存在している課題について補足として、ここで書かせてもらいます。 まず、良く質問されたのがテストケースの分割方法です。 テストケースの分割は、現状とても雑にやってます。 まず、featureスペックのファイルだけをリストアップして適当にシャッフルして詰めます。 その後で、他のテストケースを順番に詰める、という感じです。 多少、無駄ではあるんですが、前のテスト結果のプロファイルの収集と詰めるロジックを書くのをサボっても、現状大分早くできたので、とりあえず作りを簡単にする方を優先しました。 課題の中で最も大きな問題は、ログが見辛いという点です。 ECSはログを準リアルタイムで確認するのが、かなり難しいという
ECS optimized AMIはAmazon LinuxでDockerを動かす様になっている。 Amazon LinuxのDockerはデフォルトでdevice mapperをストレージのバックエンドにしている。 device mapperではコンテナに変更が入った時のレイヤーやベースイメージがsnapshotで表現されており、その上限が10GBになっている。 つまり、10GB以上の変更を加えられないので、例えば10GBを越えるファイルを一度にDLしてきて一時ファイルとして保持するとかの場合にディスクが足りなくなる。 バッチ処理のワーカーとかだと割とそれを越えるのはあり得る。 イメージごとカスタマイズしてしまえば簡単に実現できるが、管理イメージが増えるより、起動時のコンフィグという形で定義できる方が良かったので、どういう順序で設定が行われているかを調べてみた。 ECS optimize
最近、手元でRSpecを全部流すなんてことはあんまり無くなってきた。 CIサービス上で結果は確認できても、色々情報を収集したり加工したりしたい場合ローカルのファイルシステムに吐くより、S3とかGCSとかに吐ける方が何かと便利なことが多い。 というわけで、gemで何とかしてみた。 https://github.com/joker1007/rspec-storage RSpec自体にこういう処理を差し込めるAPIが無いので、出来るだけメンテしやすい形でモンキーパッチを当てている。 こんな感じで使う。(GCSの場合はgs://) $ rspec -r rspec/storage spec/example_spec.rb -f doc -f json -o s3://your-bucket/spec_result.json パースして加工することを前提にするならjsonフォーマットで吐いておくのが
基本的にassetsファイル系はクラウドなりCDNに上げてるはずで、dockerイメージの中にそんなものを含めたくはないわけですよ。 しかし、未だにsprocketsという世界から抜け出ることはできてないわけで、デプロイまでのどこかでassets precompileをしなければならない。 で、基本的にイメージビルド時にやるかデプロイ時にやるか、になるのですが今のところ私の環境ではデプロイ時にやってます。 イメージをビルドする時はassetの事は考えない。 そして、deployをする時にデプロイ前にフックを挟んでコンテナでrakeを動かし、assets:precompile及びassets:sync(asset_sync gemを使っている場合)を行う。 しかし、rake実行コンテナと、アプリケーションが起動するコンテナは別々のため、manifestファイルをどこかに保持しておく必要がある
ちなみに、最初に結論だけ言っておくと、まずSandi Metzの「オブジェクト指向設計実践ガイド」を読め、という話です それだけで終わってしまいたい気持ちはあるが、不親切過ぎるしもうちょっとRails向けの話を書こうと思う。 ただ言いたいことは、よく分かってないのに使うのは止めろということ。 自分も本で書いたりした手前、それが参考にされた結果なのかもしれないが、世の中には本当に酷いクラスが存在するもので、雑にサンプルで書くと以下の様な感じのコードが存在したりする。 class HogehogeService # Hogehogeはモデル名まんま def process(hogehoge, option_a: nil, option_b: nil, option_c: false) history = hogehoge.histories.last unless hogehoge.activ
Bigqueryはしばらく前から、AVROフォーマットでデータをエクスポートできるようになっています。 AVROフォーマットは、Apacheプロジェクトの一つとして開発されているシリアライズフォーマットで、以下の様な特徴を持ちます。 バイナリフォーマットでとてもコンパクト 型情報を持ったスキーマがある、スキーマはJSONで定義する JSONの様に入れ子が可能 null可かどうかをスキーマで表現可能 シリアライズして出力した後でも別のスキーマに変更できる 恐らく一番大きな特徴は型付きでバイナリにシリアライズしているのに、後からカラムを追加したり削除して読み出すことができる点です。 スキーマ情報はファイル内に埋め込まれていますが、別途定義したものと組み合わせて読み出すことができ、後からデフォルト値を追加したりできるようになっています。 また、Hadoopから直接データを読み出せるライブラリが揃
あんまりEC2ノードごと増やしたり減らしたりってのは、やらないで済むに越したことはないんですが、お金に限りがある世界では、無駄に何十台もサーバー立ててられないので、適宜減らしたりしたいわけです。 増やす分には、Serviceのdesired countを上げて、Autoscaling Group(以下ASG)のdesired capacityを上げればほっとけば勝手に収束してくれるので、特に問題ありません。 問題は減らす場合で、ASGのcapacityを単純に下げると、どのノードがterminateされるかを厳密にコントロールすることができません。 そうすると、現在タスク稼動中のノードが落ちたりして無駄なコンテナの上げ下げが発生したり、いざログの転送とかが詰まってたりすると、データロストの危険が高まって心理的に余り嬉しくない。 というわけで、順番に行儀良く落とす方法を考えてみました。 まず
Amazon ECSはコンテナの管理をしてくれるサービスという体になってますが、実際には普通のEC2インスタンスの上で動作します。 コンピューティングリソースは、基本的にEC2のAuto Scaling Groupで管理をします。 別にAMIから手動で立てても動作しますが、落ちた時の再起動とかリソースのサイズを管理する上ではASの方が便利でしょう。 一応、CloudFormationのスニペットみたいなのはあったりするんですが、イマイチCloudFormationが好きではないのでECSのクラスタを構築してterraformで管理するための設定を準備しました。 参考までにまとめておきます。 まず、起動設定を管理できるterraformモジュールを作る。 variable "name" {} variable "image_id" { default = "ami-010ed160" } v
最近、Rails界隈でDocker使い始めました、という話を聞く機会が増えてきたので、自分が開発環境整備用に構築したDockerの設定をまとめておく。 ちなみに、production運用については以前書いたので適当に探してくださいw 結論から書いておくと、volumeをちゃんと活用すればいい、ってだけの話です。 まず、本番用と開発用のDockerfileは分けた方が良い。一つでやろうとするとどうにも無理がでるので。 自分はDockerfileとDockerfile-devというものを用意している。 docker-composeはほぼ必須です。少なくともrailsプロセスとDBだけでも二つは必要だし、Dockerfileを分けてると事故るので。 Dockerfileはこんな感じ。 FROM mybase:ruby-2.3.1-debian RUN echo "deb http://http.
最近、仕事が忙しくて、小物のgemを作るというoutputが無かったので、思い付いたものを無理矢理形にしてみた。 タイトル通りで、キーワード引数で受け取った値をHashとしてまとめて取得するgem。 どういうものかというと以下の様な感じになる。 joker1007/given_keyword_args require 'given_keyword_args' class Dummy def dummy(foo:, bar: "bar", **options) given_keyword_args end def dummy_with_rest(foo:, bar: "bar", **options) given_keyword_args_with_rest end end p Dummy.new.dummy(foo: "foo", other1: "other1", other2: "ot
EMRでembulkのmapreduce executorを動かすまでに割と苦労したのでメモっておく。 そもそもあんまHadoopエコシステムに詳しくないし、Javaにも詳しくない。 そして、余り情報源が無いので、本当に合ってるのかどうかはちょっと怪しい。 とりあえず、EMRでHadoopクラスタを作る。 使ったのは、emr-4.2.0で、Hadoopのバージョンは2.6.0。 最新じゃないのだが、この理由は後で書く。 HadoopとYARNさえあれば動くので、他のコンポーネントは要らない。 構築時にカスタムブートストラップを使って、embulk、その他必要なjar等をインストールする。 適当な例は以下。 set -e sudo wget http://dl.embulk.org/embulk-latest.jar -O /usr/bin/embulk sudo chmod 755 /us
以前、yaml_vault というyamlで書いた設定ファイルを暗号化するgemを作りました。 そのyaml_vaultでAWS KMSを利用した暗号化をサポートしました。 AWS KMSで作った暗号化キーで、4kバイトまでの文字列を直接暗号化できます。 普通のconfigパラメーターは4kバイトも無いので、ほとんど直接暗号化だけでカバーできるでしょう。 使い方はこんな感じ % yaml_vault encrypt secrets.yml -o encrypted_secrets.yml --cryptor=aws-kms \ --aws-region=ap-northeast-1 \ --aws-kms-key-id=<kms-cms-key-id> \ --aws-access-key-id=<AWS_ACCESS_KEY_ID> \ --aws-secret-access-key=<
Register as a new user and use Qiita more conveniently You get articles that match your needsYou can efficiently read back useful informationYou can use dark themeWhat you can do with signing up
実際には、まだ本当の本番環境では運用できてなくて開発用のステージングで運用が開始できたぐらいで、他にもやること一杯あるんだけど、ある程度知見が溜まったのでまとめておく。 ちなみに、規模はそんなに大きくないがデータ量は多いアプリケーションで運用環境はAWSのECSを想定しており、現時点で普通のEC2ノードとコンテナで並行稼動している。 docker-swarmなりで自前でコンテナプールを構築してもいいのだが、そうするとサービスディスカバリとか考えなければいけないことが増えるので、後回しにしている。 (注: かなりサービス固有の事情が含まれるため、もし参考にされる方が居たとしても、そのままの形では適用できない可能性が高い) 追記: RailsアプリのためのDockerfileとdocker-compose.ymlのサンプル - Qiita コンテナ化のモチベーション CentOSのお守りからの
Bigqueryを使ったバッチジョブを色々と実行しているのですが、Rakeで複雑な依存関係を管理したり、並列実行させたりするのが辛くなってきたのでRukawaというワークフローエンジンを自作しました。 自作したのは、RailsプロダクトにAirflowとかLuigiとかAzkabanとか入れるにはちょっと重厚過ぎる感じだったのと、Rubyで書ける方が楽で良いやという理由からです。 RukawaとはRUby KAntan Workflow Assistantの略です(後付け) (本当はミッチーとか水戸の方が好きなんだけど良い名前が浮かばなかった) 実際は、並列実行を可能にして書き方を変えてみたRakeとそんなに大差無い。 Rukawaの機能 ジョブの定義 まず実行したい処理をジョブクラスに記述します。 module ExecuteLog def self.store @store ||= {
以前embulkのjava pluginをbundlerっぽくgithubからインストールして実行できるラッパーを作った - Qiitaという記事を書いた。 要はJava製のプラグインをgithubから直接インストールしてリリース前のものを使いたいというものだ。 で、コマンドをラップするgemを作ってみたのだが、DSLの挙動をちゃんと制御するのは面倒だしコマンドをラップするのは色々とポータビリティが悪い。 しかし、ある時天啓が降りてきた。 「Bundlerを弄ればいいや」と。 で、ソースコード読んで、gemspecの判別がどうなってるのかとモンキーパッチを当てるのにちょうど良い場所を探して試してみた所、とてもシンプルなハックで上手くいった。 Gemfile上でBundlerにモンキーパッチを当てるというダーティさに目を瞑れば割と便利ではないだろうか。 こんな風に書く。 require 'b
embulkのプラグインを一つ作りました。 joker1007/embulk-filter-ruby_proc embulk-filter-eval というプラグインがあって、Rubyのコードをそのままevalするんで何でもできるんですが、一レコード毎に毎回evalするのはデータ量多くなってくると効率悪いだろうと思い、もうちょっと自由度下げても良いならprocだけ事前に準備してしまえばいいだろうという発想で作ったプラグインです。 もう自由に何でもかんでもやりたい場合は、filter-evalを使いましょう。 config # ... filters: - type: ruby_proc requires: - cgi columns: - name: data proc: | ->(data) do data["events"] = data["events"].map.with_inde
まあ、タイトルは若干釣りで、特定のユースケースにおいて3割程度の高速化が見込める、というだけです。 joker1007/curl_escape: This gem provides fast URL escape by libcurl. 以下、実装経緯。 Railsのurl_forを辿っていくと、最終的にクエリパラメーターとして渡したハッシュやらArrayやらに対して、Object#to_queryを発行します。 このObject#to_queryの実装は、ほぼCGI.escapeの実行です。 やたらとlink_toの数が多くて、クエリパラメーターをそれなりに渡している、というページを表示しようとすると、割とこの処理時間が馬鹿にならない感じになってきます。 ということで、CGI.escapeを早くすれば、ちょっとはマシになるんじゃないかと思いました。 しかし、CGI.escapeの実装をR
{"id": 1, "nickname": "joker1007", "comments": [{"id": 1, "body": "comment body"}, {"id": 2, "body": "next comment"}] SELECT CONCAT( '{', '"id":',users.id, ',"nickname":',IF(users.nickname, CONCAT('"', users.nickname, '"'), "null"), ',"comments":',CONCAT('[', GROUP_CONCAT((CONCAT('{"id":', comments.id), CONCAT(',"body":"',comments.body,'"}')), ']'), '}' ) AS payload FROM users INNER JOIN comments
bigquery上でデータを加工して集計する時、このSQLが本当に合ってんのかテストコードで検証したくなる。 しかし、こういう外部サービスを使った処理のテストコードを書くのはとても面倒臭い。 とはいえ、書かんわけにもいかんし、実際に動かしてみないと分からないこともあるので、実際にbigqueryで処理を実行してテストする方法をまとめてみる。 テストデータのロード bigqueryにデータを突っ込む方法はバルクロードするかStreaming Insertの二つ。 しかし、バルクロードはテストコードを書く時に困るのが、データ量に関わらず処理に一定時間かかること。 どれだけ小さいデータでも最低1分前後は待たされる上に、時々謎の刺さり方をして最悪数分かかる場合がある。 一方でStreaming Insertはまずテーブルを作っておかなければいけないし、Streaming Insertのレスポンスが
Ruby AdventCalendarの最終日です。 締切をオーバーしました……。orz Refinementsの使い道が無いとか、使ったことがないという人が結構居るみたいなので、いくつかのユースケースを紹介しようと思います。 テストコードのDSL 一つはrspec-parameterized。 # Table Syntax Style (like Groovy spock) # Need ruby-2.1 or later describe "plus" do using RSpec::Parameterized::TableSyntax where(:a, :b, :answer) do 1 | 2 | 3 5 | 8 | 13 0 | 0 | 0 end with_them do it "should do additions" do expect(a + b).to eq answ
embulk meetupの後にsonots先輩に何か書いてくださいよーって言われたので、 embulkに限った話ではないのですが、関連する話題なのでEmbulk Advent Calendarに書かせてもらおうと思います。 embulkは設定ファイルがYAMLです。 現時点ではテンプレート機能はまだ限定的な機能しかなくて、それ程表現力がありません。 それならもう、YAMLの生成を別に任せようと思って簡単なgemを作りました。 joker1007/yaml_master YAMLの設定ファイルの大本になるマスターファイルを作っておいて、そこから特定の範囲だけを別のYAMLとして出力するだけのgemです。 その際にerbでRubyを埋め込めるようにしているので、Rubyで表現できることは何でもできます。 環境変数から日付を取ってそれをRangeにしてループしたり、ActiveRecordから
以前Nodeで作っていたものをElectronで作り直していて、同じ問題にまたハマったので書いておく。 所謂、UTF-8-MAC問題である。もう遥か昔にNodeでハマった時の記事がある。 node.jsでUTF-8-MACを扱う - joker1007の日記 Macのファイルシステムはファイル名に対してNFDとかいう正規化を行っていて、ファイルシステムにアクセスする時に勝手に変換しやがる仕組みになっている。 このせいで、濁点が入ると急に死ぬとか、本当辛い問題が起きる。何の嫌がらせなんだと……。この世界は文字が8ビットで済む様な国ばっかじゃねえんだよ! とりあえずMac NFDでググると辛いのは俺だけじゃない気持ちになれる。 で、昔は上で貼ったブログに書いたような方法で解決していたのだが、正直、この解決策は2015年にもなって面倒過ぎるだろと思っていた。 (マジかよーってググって自分の記事が
最近、データ分析と可視化の基盤構築をやってる関係で、GrafanaとinfluxDBについて調査してみようと思ったので、そのついでにRedshiftからinfluxDBにサマリーテーブルのデータを突っ込む際にembulkを使ってみようと思った。 既にあると思ってたinfluxDBへのアウトプット用プラグインが無かったので自分で書いた。 やっぱ、まだ新しいプロダクトだから色々と貢献の余地があるのは良い。 redshiftからinfluxDBへのデータ転送は手元で動作確認済みですが、とりあえず自分が今必要な機能だけ雑に実装したので、tagsを投入できなかったりエラー処理が適当だったりする。 (メトリクス収集とかじゃなくて、単純なサマリーを保存してるだけなので必要無かった) 落ち着いたらやるけど、必要な人はさっさと書いてプルリクしてくれる方が早いと思う。 jrubyでサクっと書けるのはありがたい
今更ながらブロック引数の受け取りにキーワード引数が使える事に気付いた。 よくよく考えるとブロック引数の受け取りはメソッドの引数受け取りと同じ処理してるんだから、メソッドの定義で使えるものは基本的に使えるはずで、至極当たり前の事といえばその通りなのだが……。 (自分は今日意識するまで気付いてなかった……) だからこんな感じで書ける。 [23] pry(main)> [{hoge: "fuga", foo: "bar"}].each do |hoge:, foo:| [23] pry(main)* puts hoge [23] pry(main)* puts foo [23] pry(main)* end fuga bar
次のページ
このページを最初にブックマークしてみませんか?
『qiita.com』の新着エントリーを見る
j次のブックマーク
k前のブックマーク
lあとで読む
eコメント一覧を開く
oページを開く