tokuhirom's blog

-Dsun.net.inetaddr.ttl=1 するよりも networkaddress.cache.ttl 使おう

jvm はデフォルトで DNS cache が 30sec かかっている。これはやや長過ぎると web service では判断されるケースが多い。 そこで、通常ではこれを短く設定して本番環境のデプロイをしている場合が多い。 手元のあるコードでは -Dsun.net.inetaddr.ttl=1 が指定されていたが、現在では -Dnetworkaddress.cache.ttl=1 を利用すべき。

https://www.glamenv-septzen.net/view/1346 このページが挙動について詳しい。 基本的に sun.net.inetaddr.ttl は歴史的経緯で指定されている名称であり、現代では networkaddress.cache.ttl を利用する方が良い。

Created: 2017-12-01 07:26:03 +0000
Updated: 2017-12-01 07:26:03 +0000

homebrew との付き合い方を見直す 2017

  • 最近の homebrew では、OS に含まれるコマンドも利用可能なので積極的に利用していく
    • なんとかenv 系の管理コマンドは、LL で本格的に開發している場合には便利だが、最近はバージョンを固定して開發するようなことが減ってるのと JVM 言語メインなので気にしないで brew install perl などする。
    • system perl 等にアプデさせると、
  • 古いバージョンのバイナリは brew cleanup で消せる
  • 最近は vim の拡張をゴリゴリ入れたりしてないんで、vim も OS 標準のものでいい
    • たぶん、lua を使うために brew で入れるようにしてたのだが、lua が必要になる理由の根源であった neonantoka シリーズを最近使ってないんで、もはや system vim で良い。
  • brew cask は積極的に利用している。

というわけで現在利用してるのは以下。 * ant(歴史的事情によりデプロイツールが ant に依存しており、動作確認のために手元に入れておく必要がある) * bvi(vi binding で利用できるバイナリエディタ。バイナリの中身をサッと見るときに便利) * cheat(ちょっとしたメモ代わりに使ってて便利) * coreutils(GNU コマンドに慣れすぎてるんで。。) * go * hub(github からの clone とかでたま〜につかう) * jq(json を prettify する用途ぐらいにしか使ってないけど) * maven * ngrep(packet を capture するときにめっちゃ使ってる) * node * peco * perl * protobuf * python3 * redis * rename * ruby * scala * sbt * tcping * tcptraceroute * thesilversearcher * thrift * sqlite * tree * tmux * w3m * wget(ファイルをダウンロードする時は wget のほうが楽な気がしてる) * wrk(最近は ab よりこっちメイン)

その他、brew cask で入れているものが以下。 * alfred(なんとなく継続しているが、真面目に設定してないので quick silver との違いは screen lock をショートカットキーでできることぐらい) * evernote(本来は web ui で十分という気もするが、web ui の出来が微妙なので一応入れてる) * firefox(最近アプデされたこともあり、久々に使ってみている) * filezilla(たまーに使う) * freemind(たまーに考えをまとめるときに使う) * google-chrome * google-japanese-ime * iterm2(選択範囲が iterm2 のほうが好み、という理由だけでなんとなく使い続けている) * java * java8(9 だと lombok が発狂するので。。) * karabiner(英かなちゃんと動くようになってよかったね、という感じ) * kindle * skitch * skype(最近は使ってない) * vagrant(最近は社内IaaS使う事が多くて、使ってない) * virtualbox * visualvm

Created: 2017-11-23 14:05:47 +0000
Updated: 2017-11-23 14:05:47 +0000

spring boot 2 にしたら `springBoot { executable = true }` が通らない

bootJar {
    launchScript()
}

にしましょう。

Created: 2017-11-21 02:55:57 +0000
Updated: 2017-11-21 02:55:57 +0000

spring boot 2 にしたら InvalidConfigurationPropertyNameException が発生するとき

spring boot 2 だと @ConfigurationProperties("fooBar") みたいなのを指定することができなくなる。 @ConfigurationProperties("foo-bar") なら通るので、変更必要。

Created: 2017-11-21 02:48:47 +0000
Updated: 2017-11-21 02:48:47 +0000

spring boot2 にしたら `bootRun { systemProperty 'spring.profiles.active', 'local' } }` が動かないよって場合

spring-boot 2 では以下の書き方は許容されなくなった。

bootRun {
  systemProperty 'spring.profiles.active', 'local'
}

以下のように変更する。

bootRun {
    execSpec {
        systemProperty 'com.example.foo', 'bar'
    }
}

https://twitter.com/ankinson/status/918498381768658944 ref. https://docs.spring.io/spring-boot/docs/2.0.0.M5/gradle-plugin/reference/html/#running-your-application

Created: 2017-11-21 02:22:37 +0000
Updated: 2017-11-21 02:22:37 +0000

/dev/urandom を fork して読み込んでもいいんかって話

tokuhirom /dev/urandom って開いたまま fork して読み込んだらまずいんですっけ?
親 process で /dev/urandom 開いたまま、fork してそれぞれの子プロセスで読んだら同じの取れる?
kazuho 同じの取れないですね
一般論なファイルについてもそう
つまり、open file descriptionは同一なので、readしたらその中にあるfile offsetは進むので (edited)
Created: 2017-11-13 03:32:48 +0000
Updated: 2017-11-13 03:32:48 +0000

spring-boot-actuator 使いたいけど spring-webmvc はいらないよってケース

management.port のほうは開きたいけど server.port のほうは開きたくないってときは

server.port: -1

とかやっときゃいいとのこと。

Created: 2017-11-08 05:39:24 +0000
Updated: 2017-11-08 05:39:24 +0000

Perl Web application に於ける Data::UUID の利用について

本文書について

本文書では Perl における Data::UUID での UUID 生成について議論する。 特に、Linux 環境に於ける Data::UUID->new->create_str の挙動について考察する。

Data::UUID について

Data::UUID は Alexander Golomshtok 氏が開発したモジュールで、メンテナンスされなくなった結果として、現在は rjbs 氏がパッチの適用などの消極的なメンテナンスを実施している。

このモジュールは以下の文言からドキュメントが開始されている。

This module provides a framework for generating v3 UUIDs

しかし、期待に反して、実際にはほとんどのユーザーは v1 UUID を生成している。 Data::UUID->new->create_str を利用するのが一般的なケースであるためだ。

UUIDv1 の構造について

timestamp 60bit, clock sequence 16bit, node 48bit

となっている。

  UUID                   = time-low "-" time-mid "-"
                           time-high-and-version "-"
                           clock-seq-and-reserved
                           clock-seq-low "-" node

↓つまり以下のような形式となる。

   TIMESTAM-PTIM-ESTA-CLOC-NODEID

/tmp/.UUID_NODEID について

Data::UUID->new で nodeid は生成されます。

/tmp/.UUID_NODEID が存在しない場合、nodeid は md5(gettimeofday(), gethostname()) で生成され、 /tmp/.UUID_NODEID に保存されます。 /tmp/.UUID_NODEID が存在する場合、slurp(/tmp/.UUID_NODEID) + $$ の結果が nodeid となります。

このロジックにより、二回目以後の nodeid 生成は process ごとに独立した nodeid になります。

/tmp/.UUID_STATE について

/tmp/.UUID_STATE に clockseq などが保存されます。これにより、プロセスが再起動した場合などにも動作を続けることができる、という設計に見えます。

このファイルの保存タイミングは以下。

  • UUID 生成時に、前回保存時刻より 10秒おきに保存されます。
  • Data::UUID#DESTROY のコール時にも保存されます。

しかし、現実的には、あまり意味ないかも。

Data::UUID を web application で利用した場合に発生する可能性がある問題について

以下では pre-fork モデルのウェブアプリケーションで Data::UUID を利用した場合に発生し得る問題について議論する。 (Starlet, Starman などの web server が pre-forking モデルです)

時刻の巻戻り

UUID v1 の特性上、NTP などにより時刻が巻き戻った場合、重複した uuid が発行される可能性があります。 時刻の巻き戻りが発生した場合に発生する重複が許容出来ない場合、Data::UUID の利用は避けるべきでしょう。

clock sequence を初期化するタイミングで初期値を random にするなどの軽減策は取られているものの、問題が発生する可能性はそこそこあります。

local 攻撃への脆弱性

  • /tmp/.UUID_NODEID
  • /tmp/.UUID_STATE

の2つのファイルが生成されるが、tmp directory に生成されるために、悪意のあるユーザーが設置することが可能。

nodeid の生成ロジックの問題

/tmp/.UUID_NODEID がある場合にだけ pid が nodeid に考慮される。 このため、Data::UUID を一度も利用したことがない新しいサーバーの初回起動時などに nodeid が同一の Data::UUID インスタンスを持つ process が複数発生する可能性がある。

AWS などで頻繁にインスタンスの作り直しを実施している場合、この問題が発生しやすいと考えられる。

Data::UUID->new() を fork 前に呼んではいけない

Data::UUID->new の中で nodeid を初期化しているので、fork 前に呼ぶと同一 nodeid ですべての子プロセスで利用されることになり、相手は死ぬ。

srand の呼び出し

Data::UUID->new の中で、現在時刻をシードに srand() を呼び出し、それ以後は rand() をコールしている。。 現在時刻は srand のソースとして使うにはよろしくないので、これは、他の rand() を利用している XS module に悪影響を与えている可能性がある。 (Perl 本体は drand48() を利用しているので問題ない)

対案

完全に random な UUID 生成方法である UUID v4 を利用しとくか、sfujiwara さんが作ってたみたいなやつ使うのがいいんじゃないすかね。 ただし、UUID v4 の生成系を利用する場合、fork 時の seed 最初期化などについては考慮を忘れずに。

Created: 2017-11-08 04:34:44 +0000
Updated: 2017-11-08 04:34:44 +0000

spring-boot で tomcat の設定するときのやり方

server:
  use-forwarded-headers: true
  tomcat:
    accesslog:
      directory: /PATH/TO/logs/tomcat/
      pattern: common
      enabled: true
      rotate: true
      # It's required when using remote-ip-header.
      request-attributes-enabled: true
    remote-ip-header: x-forwarded-for
    protocol-header: x-forwarded-proto

なんかこんな感じ? request-attributes-enabled を設定するの忘れると RemoteIpValve で設定した値が AccessLogValve で拾われないので死ぬ。

Created: 2017-11-02 08:11:47 +0000
Updated: 2017-11-02 08:11:47 +0000

spring-boot で ConfigurationProperties に ZonedDateTime を書く場合のやり方

application.yml に日付データを入れて ZonedDateTime にマッピングしたい、みたいな場合。

http://blog.rakugakibox.net/entry/2015/12/04/springboot-with-java8time ↑こちらのブログに掲載されているように以下のようなクラスをおけばよい。

@Configuration
public class ConversionServiceConfiguration {
    @Bean
    public ConversionService conversionService() {
        FormattingConversionServiceFactoryBean factory = new FormattingConversionServiceFactoryBean();
        DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
        registrar.setUseIsoFormat(true);
        factory.setFormatterRegistrars(Collections.singleton(registrar));
        factory.afterPropertiesSet();
        return factory.getObject();
    }
}

便利~


追記: http://www.logicbig.com/tutorials/spring-framework/spring-boot/custom-configuration-properties-binding/ のようなやり方もあるとのこと。 https://twitter.com/wreulicke/status/925613009728290817

Created: 2017-11-01 04:19:13 +0000
Updated: 2017-11-01 04:19:13 +0000

apscheduler で add_job するときは misfire_grace_time の指定が必須

python で job の定期実行を実装するには apscheduler が便利だが、misfiregracetime の指定をしないと job が実行されないことがあるので注意が必要。 指定していないと以下のようなエラーに悩まされることになる。

Run time of job "send_menu (trigger: cron[day_of_week='mon-fri', hour='11'], next run at: 2016-05-31 11:00:00 CEST)" was missed by 0:00:01.51075

これは、予定された実行時間よりも scheduler の起動が遅れてしまったから実行しないようにしましたよ、というメッセージである。 デフォルトでは 1 秒以上実行が遅延した場合、ジョブは実行されない。 https://github.com/museumsvictoria/nodel/issues/13

しかし実際、1.5秒遅れても実行はしてほしいわけなので以下のように misfiregracetime を指定し、delay の許容時間を指定する方が良い。

scheduler.add_job(func, trigger='cron', hour='10,11,12', misfire_grace_time=60*60)
Created: 2017-10-28 08:39:17 +0000
Updated: 2017-10-28 08:39:17 +0000

spring.profiles.include は array で指定可能

https://github.com/spring-projects/spring-boot/issues/6995

spring.profiles.include は従来、string型でしか指定できなかったので以下のようなクソみたいな設定をするしかなかった。

---
spring.profiles: default
spring.profiles.active: local

---
spring.profiles.include: "\
  logging-devel,\
  mybatis-common,\
  freemarker-devel,\
  freemarker-common
"

---
spring.profiles: release
spring.profiles.include: "\
  mybatis-common,\
  freemarker-release,\
  freemarker-common
"

しかし、これは使いづらすぎるので以下のように書けるようにしてくれ、という要望を上げていた。


---
spring.profiles: default
spring.profiles.active: local

---
spring.profiles.include:
  - logging-devel
  - mybatis-common
  - freemarker-develo
  - freemarker-common

---
spring.profiles: release
spring.profiles.include:
  - mybatis-common
  - freemarker-release
  - freemarker-common

これが 2017 年の前半でリリースされてる spring-boot 1.5.0 では取り込まれているので、積極的に使うと良い。

Created: 2017-10-24 09:04:08 +0000
Updated: 2017-10-24 09:04:08 +0000

僕が情報収集に使っているブログ

僕が最近主に見ているブログについて以下に述べさせていただきます。 以下にあげたやつ以外に1000ぐらい購読してるけどそのへんのはあんま実用的というよりは趣味に近い感じです。

idea blog

https://blog.jetbrains.com/idea/

IDEA の最新機能とかがわかって便利。

Java Annotated Monthly ってのが毎月このブログにのるので、コレだけ読んでおけばJava界隈のトピックに乗り遅れることはない。

Reddit の /r/java

https://www.reddit.com/r/java/

なんだかんだ情報集めるのに便利なのは reddit。

spring blog

https://spring.io/blog

spring 関連のアプデ情報が集まるぞ!

github blog

https://github.com/blog

github のアプデ情報がわかるし、github で盛り上がってるレポの状態とかもわかる~

netflix tech blog

https://medium.com/netflix-techblog

netflix は尖った java 運用してるんで参考になる。

Debian security

https://www.debian.org/security/

なんとなく security 関連の update を追うのに便利

vue.js

https://medium.com/the-vue-point

vue.js 情報

AUTOMATON

http://jp.automaton.am/

洋ゲーの情報とか

Created: 2017-10-19 02:54:51 +0000
Updated: 2017-10-19 02:54:51 +0000

Spring cloud config client が Could not locate PropertySource: 400 Bad Request になるときの対処方法

spring cloud config を試しているときにハマったののメモ。

spring cloud config のチュートリアルは server を 8888 番ポートで listen させろと書いてある。 コレに従って進めていくと、Could not locate PropertySource: 400 Bad Request というエラーになって困った。

ngrep を実施して様子を見ていると以下のようなログが取れた。

##########
T 127.0.0.1:50448 -> 127.0.0.1:8888 [AP]
GET /a-bootiful-client/default HTTP/1.1.
Host: 127.0.0.1:8888.
User-Agent: curl/7.54.0.
Accept: */*.
.

##
T 127.0.0.1:8888 -> 127.0.0.1:50448 [AP]
HTTP/1.1 400 Bad Request.
Content-type: text/plain.
Connection: Keep-Alive.
Content-length: 58.
.
400 Bad Request
'json' or 'msgpack' parameter is required

curl http://localhost:8888 でリクエストした場合には以下のようになっていた。

#####
T ::1:50441 -> ::1:8888 [AP]
GET /a-bootiful-client/default HTTP/1.1.
Host: localhost:8888.
User-Agent: curl/7.54.0.
Accept: */*.
.

##
T ::1:8888 -> ::1:50441 [AP]
HTTP/1.1 200 .
X-Application-Context: application:8888.
Content-Type: application/json;charset=UTF-8.
Transfer-Encoding: chunked.
Date: Wed, 11 Oct 2017 06:07:25 GMT.
.
97.
{"name":"a-bootiful-client","profiles":["default"],"label":null,"version":"94427c7a809dbb3550d6db2902eccd4f93eec63d","state":null,"propertySources":[]}.

同じ http://localhost:8888/ を読んでいるが、返しているサーバーが違うようだ。

'json' or 'msgpack' parameter is required というメッセージで検索してみると、fluentd の in_http に含まれるエラーメッセージだということがわかる。

昔、手元のマシンで td-agent を起動してそのままになっていた結果、in_http が 8888 番ポートを見続けていたようだ。

curl http://127.0.0.1:8888 するとたしかに in_http に行ってることが確認できた。

同じ http://localhost:8888 へのリクエストでも、違う process にリクエストがいくことがあるので注意が必要だということがわかった。

対応は sudo pkill -f td-agent です!

Created: 2017-10-11 06:19:59 +0000
Updated: 2017-10-11 06:19:59 +0000

DBIx::Sunny と DBIx::Class の組み合わせでコメント自動挿入機能が微妙なことになっていたのを直した

https://github.com/kazeburo/DBIx-Sunny/issues/8

DBIx::Sunny は自動的にクエリ呼び出し元の位置をコメントに入れる機能がある。

しかし、DBIx::Class は Try::Tiny, Context::Preserve の内側でクエリ生成を行うため、Try::Tiny が呼び出し元として記録されてしまう。 つまり、以下のようなクエリが発行されてしまう。

SELECT /* /Users/tokuhirom/.plenv/versions/5.26.0-RC1/lib/perl5/site_perl/5.26.0/Try/Tiny.pm line 99 */ me.id, me.e FROM foo me

これは不便なので pr を出した。

https://github.com/kazeburo/DBIx-Sunny/pull/10

マージされ、リリースされ、システムに適用され、僕の周りにはキレイな slow query log が生まれることになった(根本的には slow query log はそもそも生まれないほうがいいという説もある)

Created: 2017-09-29 03:16:33 +0000
Updated: 2017-09-29 03:16:33 +0000

[python] IDEA で `if __name__=='__main__':` って簡単に入力したい

main って入力して補完すれば、java でいう psvm みたいなことができるとのこと。

Created: 2017-08-23 04:27:32 +0000
Updated: 2017-08-23 04:27:32 +0000

kotlin で -parameters 相当のことをしたい

http://qiita.com/kazuki43zoo/items/d000c87db98a68c6edba ここにかいてあるとおりにやれば良い。 デフォルトでやってくれ!頼む!! という気分になる

Created: 2017-07-05 20:08:49 +0000
Updated: 2017-07-05 20:08:49 +0000

[kotlin] ktor で config を読みたい

前提として、ktor のサンプルコードは、

    embeddedServer(Jetty, 8080, module = Application::module)
            .start()        

のように書かれているものが多いのですが、embeddedServer() を呼んだだけでは設定ファイルは読まれません。

fun main(args: Array<String>) {
    val applicationEnvironment = commandLineEnvironment(args)
    JettyApplicationHost(applicationEnvironment).start()
}

のように commandLineEnvironment を利用するのがよさそうです。

こうすることで、コマンドライン引数もよしなに扱ってくれるようになり、たとえば -port=8080 のように port 番号をコマンドライン引数で指定できるようになります。

で、application.conf を src/main/resources/application.conf に起きます。ktor サーバーの port 番号や、起動時のエントリポイントなどの指定もここでおこなえますし、アプリケーション独自の設定もここに書くことができます。

ktor {
  deployment {
    port = 8080
  }
  application {
    modules = [ com.example.HelloKt.module ]
  }
}



myapp {
  foobar {
    baz = 5963
  }
}

あとは以下のようにすれば設定を読み込み可能です。簡単ですね。

    val baz = environment.config.property("myapp.foobar.baz").getString()
    environment.log.info("baz: $baz")

完全な例はこちらです。 https://github.com/tokuhirom/ktor-samples/tree/master

Created: 2017-05-30 23:12:05 +0000
Updated: 2017-05-30 23:12:05 +0000

[kotlin] ktor で basic auth したい

ktor-auth コンポーネントで簡単に設定できます。

    compile "org.jetbrains.ktor:ktor-auth:$ktor_version"

で、あとは以下のように認証を設定する。設定した principal をコントローラ内でも取得可能。

        route("/") {
                authentication {
                    basicAuthentication("your-app-realm") { credentials ->
                        val username = credentials.name
                        val password = credentials.password
                        if (checkAuth(username, password)) {
                            UserIdPrincipal(username, password)
                        } else {
                            null
                        }
                    }
                }

            get("/hello") {
                val name = call.principal<UserIdPrincipal>()!!.name
                call.respondText("Hello $name")
            }
        }

簡単ですね。

Created: 2017-05-26 23:45:20 +0000
Updated: 2017-05-26 23:45:20 +0000

kotlin で instance_eval 的なことをしたい

kotlin では ruby 的な block つきメソッド呼び出しができるので、以下のようにすると instance_eval 的な、rubyish な DSL もめっちゃ簡単に実現できる〜〜

class Foo {
    fun bar(cb: Foo.() -> Unit) {
        apply(cb)
    }

    fun berk() {
        println("berk")
    }
}

fun main(args: Array<String>) {
    Foo().bar() {
        berk()
    }
}
Created: 2017-05-24 13:17:09 +0000
Updated: 2017-05-24 13:17:09 +0000

osx の notification を kotlin で呼びたい

osascript で呼ぶのがいいかな。apple script の escape 方法はよくわからないので JavaScript で書くことにして、 JSON で serialize して渡すのが良さそう。

fun sendNotification(message: String, title: String=message, subtitle: String=message, soundName: String = "Frog") {
    // https://developer.apple.com/library/content/documentation/LanguagesUtilities/Conceptual/MacAutomationScriptingGuide/DisplayNotifications.html
    val params = jsonObject(
            "withTitle" to title,
            "subtitle" to subtitle,
            "soundName" to soundName
    )

    Runtime.getRuntime().exec(arrayOf(
            "osascript",
            "-l",
            "JavaScript",
            "-e",
            """var app = Application.currentApplication();
                app.includeStandardAdditions = true
                app.displayNotification(${message.toJson()}, $params)"""
    ))
}

JSON serialize は kotoson が便利。

compile 'com.github.salomonbrys.kotson:kotson:2.5.0'

で、こういうのちょっと頑張って書いてみたけど、LINE Notify 使うのが便利っぽいって話になった。。

Created: 2017-05-22 04:18:26 +0000
Updated: 2017-05-22 04:18:26 +0000
Next page