unless’s blog

日々のちょっとした技術的なことの羅列

FAXで障害報告を受信したときにSlack通知する

やりたいこと

FAXで障害報告が送られて来たときにSlackに内容を通知してエンジニアが気がつけるようにしたい

前置き

Kyashでサーバサイドエンジニアをやっている @uncle__ko です
色々なシステムやベンダーと接続をしていると障害報告がFAXで来るなんてこともあります
現実問題、FAXで連絡が来たところでリモートワークなこのご時世では気がつくことは困難
しかも休日や夜間にもFAXで届くこともあります
レガシーだと嘆いていても仕方がないのでSlackに通知させて気がつけるようしたいと思います

Zapier

zapier.com

ポチポチするだけで色々なツールを繋ぐことが出来る便利なやつです

KyashではZapierを使って様々なものを自動化しています

blog.kyash.co

Zap Summary

Trigger: FAX.PLUS

FAX PLUSとはオンライン上でFAXを送受信できるサービス FAX PLUSはSlackやZapier等色々なツールのintegrationがあって便利です

www.fax.plus

  • Trigger Eventは New Fax Received

Action: Filter by Zapier

  • Only continue if... にfilterを追加します
    • 今回はベンダーの送信番号でFilterしてます
      f:id:gettergot:20210402173844p:plain
      action_filter

Action: Slack

  • Action Eventは Send Channel Message
  • fileはFAX PLUSで受信したものを設定します
    f:id:gettergot:20210402174035p:plain
    action_slack

FAX PLUSは色々なツールとのintegrationが豊富でとてもよいのですが
admin権限がないとZapier側のTriggerやActionの連携が出来なくて無駄にハマったりしたので気を付けましょう
admin権限以外でも連携出来るようになるともっと使いやすくなるのになと思ったりしました

実行結果

f:id:gettergot:20210402174414p:plain
slack_notify

Happy !!

Goのhello worldを小さくする

これはなに?

ふとGolangのbinaryを小さく出来ないかなと思い立ったのでhello worldをスリムにしていこうと思う

hello world

Golangでのhello worldはこちら

package main

import "fmt"

func main() {
  fmt.Println("hello, world")
}

普通にbuild

これを普通にbuildするとどうなるか

# go build hello.go
# ll hello
-rwxr-xr-x 1 root root 2008801 Feb 20 02:01 hello*
# ll -h hello
-rwxr-xr-x 1 root root 2.0M Feb 20 02:01 hello*

2MBもあるようだ

-ldflags

とりあえずldflagsをつけてbuildしてみる
-sはデバッグのために使われるシンボルテーブルを生成しないようにする

# go build -o hello_ld -ldflags="-s" hello.go
# ll hello_ld
-rwxr-xr-x 1 root root 1433600 Feb 20 02:05 hello_ld*
# ll -h hello_ld
-rwxr-xr-x 1 root root 1.4M Feb 20 02:05 hello_ld*

だいぶ削れた
けどまだ削れる気がする

elfファイルを見てみる

とりあえず消せそうなsectionあるか見てみる

# readelf -S hello_ld
There are 14 section headers, starting at offset 0x1c8:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .text             PROGBITS         0000000000401000  00001000
       000000000008bf19  0000000000000000  AX       0     0     16
  [ 2] .rodata           PROGBITS         000000000048d000  0008d000
       000000000004f550  0000000000000000   A       0     0     32
  [ 3] .shstrtab         STRTAB           0000000000000000  000dc560
       000000000000008a  0000000000000000           0     0     1
  [ 4] .typelink         PROGBITS         00000000004dc600  000dc600
       0000000000000c68  0000000000000000   A       0     0     32
  [ 5] .itablink         PROGBITS         00000000004dd268  000dd268
       0000000000000050  0000000000000000   A       0     0     8
  [ 6] .gosymtab         PROGBITS         00000000004dd2b8  000dd2b8
       0000000000000000  0000000000000000   A       0     0     1
  [ 7] .gopclntab        PROGBITS         00000000004dd2c0  000dd2c0
       000000000006b67c  0000000000000000   A       0     0     32
  [ 8] .go.buildinfo     PROGBITS         0000000000549000  00149000
       0000000000000020  0000000000000000  WA       0     0     16
  [ 9] .noptrdata        PROGBITS         0000000000549020  00149020
       000000000000d0d8  0000000000000000  WA       0     0     32
  [10] .data             PROGBITS         0000000000556100  00156100
       0000000000007050  0000000000000000  WA       0     0     32
  [11] .bss              NOBITS           000000000055d160  0015d160
       000000000001b870  0000000000000000  WA       0     0     32
  [12] .noptrbss         NOBITS           00000000005789e0  001789e0
       0000000000002768  0000000000000000  WA       0     0     32
  [13] .note.go.buildid  NOTE             0000000000400f9c  00000f9c
       0000000000000064  0000000000000000   A       0     0     4
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  l (large), p (processor specific)

.gosymtabとか.note.go.buildidは削れそうだけどスズメの涙だろうなと思いつつ削除

# readelf -x13 hello_ld

Hex dump of section '.note.go.buildid':
  0x00400f9c 04000000 53000000 04000000 476f0000 ....S.......Go..
  0x00400fac 6c656668 6e656c37 74716b75 72507254 lefhnel7tqkurPrT
  0x00400fbc 5335634a 2f794f50 62666478 494d4357 S5cJ/yOPbfdxIMCW
  0x00400fcc 6147766b 66435546 792f7a4f 78425866 aGvkfCUFy/zOxBXf
  0x00400fdc 4f7a632d 505f4d41 43306d56 675f2f6e Ozc-P_MAC0mVg_/n
  0x00400fec 6e50494a 6c6c532d 632d4443 6842386b nPIJllS-c-DChB8k
  0x00400ffc 674c4e00                            gLN.

# strip -R .gosymtab hello_ld
# strip -R .note.go.buildid hello_ld
# ./hello_ld
hello, world
# ll hello_ld
-rwxr-xr-x 1 root root 1430712 Feb 20 02:11 hello_ld*
# ll -h hello_ld
-rwxr-xr-x 1 root root 1.4M Feb 20 02:11 hello_ld*

これ以上むりそうに感じる...
upxを使えば削減できるだろうが負けた気分になるので他の手を使いたい

medium.com

fmt.Printlnやめればいいのでは?

syscallを直接よべばもう少し削減できるんじゃね?(なんの意味もないけど減らしたい気持ちになった)
と思ったのでsyscallを呼んでみることにした

golang.org

package main

import (
    "syscall"
    "unsafe"
)

func main() {
  p := []byte("hello, world\n")
  var _p0 unsafe.Pointer
  _p0 = unsafe.Pointer(&p[0])
  syscall.Syscall(syscall.SYS_WRITE, uintptr(1), uintptr(_p0), uintptr(len(p)))
}

buildしてみる

# go build -o hello_sys -ldflags='-s' hello_sys.go
# ll hello_sys
-rwxr-xr-x 1 root root 851968 Feb 20 02:17 hello_sys*
# ll -h hello_sys
-rwxr-xr-x 1 root root 832K Feb 20 02:17 hello_sys*

めっさ小さい!

もうちょっとだけ悪あがき

# strip -R .gosymtab hello_sys
# strip -R .note.go.buildid hello_sys
# strip -s hello_sys

消せそうなのを消していく

# ll hello_sys
-rwxr-xr-x 1 root root 849880 Feb 20 02:19 hello_sys*
# ll -h hello_sys
-rwxr-xr-x 1 root root 830K Feb 20 02:19 hello_sys*

個人的にはこれが限界かな
そもそもsyscallなんて普通呼ばないから意味もないし自己満足だけど
容量は減ってなんだかうれしくなったからいいか

CとGoのhello world時のシステムコール数

特に何かの役に立つわけでもないが取得する機会があったのでここに置いておく

環境

# cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04.1 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.1 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

C

cc version

# cc --version
cc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

hello.c

# include <stdio.h>

int main(void) {
  puts("hello, world");
  return 0;
}

build

# cc -o hello hello.c

strace

# strace -T -o hello.log ./hello
hello, world
# cat hello.log
execve("./hello", ["./hello"], 0x7ffdcbe878f8 /* 9 vars */) = 0 <0.000859>
brk(NULL)                               = 0x559b13f8e000 <0.000379>
arch_prctl(0x3001 /* ARCH_??? */, 0x7ffc73131180) = -1 EINVAL (Invalid argument) <0.000110>
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory) <0.000475>
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 <0.000190>
fstat(3, {st_mode=S_IFREG|0644, st_size=12932, ...}) = 0 <0.000137>
mmap(NULL, 12932, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fc2d788e000 <0.000163>
close(3)                                = 0 <0.000144>
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 <0.000161>
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\360q\2\0\0\0\0\0"..., 832) = 832 <0.000148>
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784 <0.000147>
pread64(3, "\4\0\0\0\20\0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0", 32, 848) = 32 <0.000147>
pread64(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0\t\233\222%\274\260\320\31\331\326\10\204\276X>\263"..., 68, 880) = 68 <0.000147>
fstat(3, {st_mode=S_IFREG|0755, st_size=2029224, ...}) = 0 <0.000145>
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc2d788c000 <0.000145>
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784 <0.000240>
pread64(3, "\4\0\0\0\20\0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0", 32, 848) = 32 <0.000238>
pread64(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0\t\233\222%\274\260\320\31\331\326\10\204\276X>\263"..., 68, 880) = 68 <0.000168>
mmap(NULL, 2036952, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fc2d769a000 <0.000205>
mprotect(0x7fc2d76bf000, 1847296, PROT_NONE) = 0 <0.000234>
mmap(0x7fc2d76bf000, 1540096, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x25000) = 0x7fc2d76bf000 <0.000232>
mmap(0x7fc2d7837000, 303104, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x19d000) = 0x7fc2d7837000 <0.000406>
mmap(0x7fc2d7882000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1e7000) = 0x7fc2d7882000 <0.000219>
mmap(0x7fc2d7888000, 13528, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fc2d7888000 <0.000319>
close(3)                                = 0 <0.000345>
arch_prctl(ARCH_SET_FS, 0x7fc2d788d540) = 0 <0.000117>
mprotect(0x7fc2d7882000, 12288, PROT_READ) = 0 <0.000168>
mprotect(0x559b12344000, 4096, PROT_READ) = 0 <0.000122>
mprotect(0x7fc2d78bf000, 4096, PROT_READ) = 0 <0.000121>
munmap(0x7fc2d788e000, 12932)           = 0 <0.000170>
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0), ...}) = 0 <0.000128>
brk(NULL)                               = 0x559b13f8e000 <0.000123>
brk(0x559b13faf000)                     = 0x559b13faf000 <0.000119>
write(1, "hello, world\n", 13)          = 13 <0.000618>
exit_group(0)                           = ?
+++ exited with 0 +++

call数

# cat hello.log | wc -l
36

Go

go version

# go version
go version go1.13.8 linux/amd64

hello.go

package main

import "fmt"

func main() {
  fmt.Println("hello, world")
}

build

# go build hello.go

strace

# strace -T -o hello.log ./hello
hello, world
# cat hello.log
execve("./hello", ["./hello"], 0x7fff18c90078 /* 9 vars */) = 0 <0.000343>
arch_prctl(ARCH_SET_FS, 0x55e0f0)       = 0 <0.000023>
sched_getaffinity(0, 8192, [0, 1])      = 16 <0.000028>
openat(AT_FDCWD, "/sys/kernel/mm/transparent_hugepage/hpage_pmd_size", O_RDONLY) = 3 <0.000050>
read(3, "2097152\n", 20)                = 8 <0.000029>
close(3)                                = 0 <0.000012>
mmap(NULL, 262144, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f655058f000 <0.000032>
mmap(0xc000000000, 67108864, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xc000000000 <0.000025>
mmap(0xc000000000, 67108864, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xc000000000 <0.000030>
mmap(NULL, 33554432, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f654e58f000 <0.000025>
mmap(NULL, 2164736, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f654e37e000 <0.000029>
mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f654e36e000 <0.000025>
mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f654e35e000 <0.000030>
clock_gettime(CLOCK_MONOTONIC, {tv_sec=3985, tv_nsec=825706741}) = 0 <0.000024>
clock_gettime(CLOCK_MONOTONIC, {tv_sec=3985, tv_nsec=825791841}) = 0 <0.000042>
clock_gettime(CLOCK_MONOTONIC, {tv_sec=3985, tv_nsec=825877341}) = 0 <0.000029>
clock_gettime(CLOCK_MONOTONIC, {tv_sec=3985, tv_nsec=825952241}) = 0 <0.000061>
clock_gettime(CLOCK_MONOTONIC, {tv_sec=3985, tv_nsec=826186341}) = 0 <0.000042>
clock_gettime(CLOCK_MONOTONIC, {tv_sec=3985, tv_nsec=826313741}) = 0 <0.000052>
clock_gettime(CLOCK_MONOTONIC, {tv_sec=3985, tv_nsec=826501941}) = 0 <0.000095>
clock_gettime(CLOCK_MONOTONIC, {tv_sec=3985, tv_nsec=826726741}) = 0 <0.000035>
clock_gettime(CLOCK_MONOTONIC, {tv_sec=3985, tv_nsec=826836541}) = 0 <0.000042>
clock_gettime(CLOCK_MONOTONIC, {tv_sec=3985, tv_nsec=826922741}) = 0 <0.000034>
clock_gettime(CLOCK_MONOTONIC, {tv_sec=3985, tv_nsec=827010941}) = 0 <0.000034>
clock_gettime(CLOCK_MONOTONIC, {tv_sec=3985, tv_nsec=827093841}) = 0 <0.000042>
clock_gettime(CLOCK_MONOTONIC, {tv_sec=3985, tv_nsec=827173641}) = 0 <0.000027>
clock_gettime(CLOCK_MONOTONIC, {tv_sec=3985, tv_nsec=827258941}) = 0 <0.000046>
rt_sigprocmask(SIG_SETMASK, NULL, [], 8) = 0 <0.000028>
clock_gettime(CLOCK_MONOTONIC, {tv_sec=3985, tv_nsec=827907041}) = 0 <0.000025>
clock_gettime(CLOCK_MONOTONIC, {tv_sec=3985, tv_nsec=828037441}) = 0 <0.000056>
sigaltstack(NULL, {ss_sp=NULL, ss_flags=SS_DISABLE, ss_size=0}) = 0 <0.000032>
sigaltstack({ss_sp=0xc000002000, ss_flags=0, ss_size=32768}, NULL) = 0 <0.000026>
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0 <0.000031>
gettid()                                = 5133 <0.000026>
rt_sigaction(SIGHUP, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000036>
rt_sigaction(SIGHUP, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000180>
rt_sigaction(SIGINT, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000029>
rt_sigaction(SIGINT, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000025>
rt_sigaction(SIGQUIT, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000022>
rt_sigaction(SIGQUIT, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000024>
rt_sigaction(SIGILL, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000027>
rt_sigaction(SIGILL, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGTRAP, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000127>
rt_sigaction(SIGTRAP, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000021>
rt_sigaction(SIGABRT, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGABRT, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000021>
rt_sigaction(SIGBUS, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGBUS, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGFPE, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGFPE, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGUSR1, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGUSR1, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGSEGV, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGSEGV, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGUSR2, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGUSR2, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGPIPE, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGPIPE, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGALRM, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGALRM, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGTERM, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGTERM, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGSTKFLT, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGSTKFLT, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGCHLD, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGCHLD, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGURG, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGURG, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGXCPU, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGXCPU, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGXFSZ, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGXFSZ, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000023>
rt_sigaction(SIGVTALRM, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGVTALRM, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGPROF, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGPROF, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGWINCH, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGWINCH, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000021>
rt_sigaction(SIGIO, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGIO, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGPWR, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGPWR, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGSYS, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGSYS, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGRTMIN, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGRT_1, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGRT_2, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGRT_2, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGRT_3, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGRT_3, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGRT_4, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGRT_4, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGRT_5, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGRT_5, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGRT_6, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGRT_6, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGRT_7, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000134>
rt_sigaction(SIGRT_7, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGRT_8, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGRT_8, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGRT_9, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGRT_9, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGRT_10, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGRT_10, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGRT_11, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGRT_11, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGRT_12, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGRT_12, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGRT_13, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGRT_13, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000021>
rt_sigaction(SIGRT_14, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGRT_14, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGRT_15, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGRT_15, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGRT_16, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGRT_16, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGRT_17, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGRT_17, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGRT_18, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGRT_18, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000020>
rt_sigaction(SIGRT_19, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000020>
rt_sigaction(SIGRT_19, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000017>
rt_sigaction(SIGRT_20, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000118>
rt_sigaction(SIGRT_20, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000017>
rt_sigaction(SIGRT_21, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000016>
rt_sigaction(SIGRT_21, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000016>
rt_sigaction(SIGRT_22, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000016>
rt_sigaction(SIGRT_22, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000016>
rt_sigaction(SIGRT_23, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000016>
rt_sigaction(SIGRT_23, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000016>
rt_sigaction(SIGRT_24, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000016>
rt_sigaction(SIGRT_24, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000016>
rt_sigaction(SIGRT_25, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000016>
rt_sigaction(SIGRT_25, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000016>
rt_sigaction(SIGRT_26, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000016>
rt_sigaction(SIGRT_26, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000016>
rt_sigaction(SIGRT_27, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000016>
rt_sigaction(SIGRT_27, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000094>
rt_sigaction(SIGRT_28, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000016>
rt_sigaction(SIGRT_28, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000016>
rt_sigaction(SIGRT_29, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000016>
rt_sigaction(SIGRT_29, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000016>
rt_sigaction(SIGRT_30, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000016>
rt_sigaction(SIGRT_30, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000017>
rt_sigaction(SIGRT_31, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000016>
rt_sigaction(SIGRT_31, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000016>
rt_sigaction(SIGRT_32, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 <0.000016>
rt_sigaction(SIGRT_32, {sa_handler=0x4551e0, sa_mask=~[], sa_flags=SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer=0x455310}, NULL, 8) = 0 <0.000016>
rt_sigprocmask(SIG_SETMASK, ~[], [], 8) = 0 <0.000017>
clone(child_stack=0xc000042000, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM) = 5134 <0.000090>
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0 <0.000014>
rt_sigprocmask(SIG_SETMASK, ~[], [], 8) = 0 <0.000017>
clone(child_stack=0xc000044000, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM) = 5135 <0.000064>
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0 <0.000007>
clock_gettime(CLOCK_MONOTONIC, {tv_sec=3985, tv_nsec=837951841}) = 0 <0.000021>
clock_gettime(CLOCK_MONOTONIC, {tv_sec=3985, tv_nsec=838005841}) = 0 <0.000025>
rt_sigprocmask(SIG_SETMASK, ~[], [], 8) = 0 <0.000016>
clone(child_stack=0xc00003e000, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM) = 5136 <0.000037>
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0 <0.000016>
futex(0xc000032848, FUTEX_WAKE_PRIVATE, 1) = 1 <0.000041>
futex(0xc0000324c8, FUTEX_WAKE_PRIVATE, 1) = 1 <0.000039>
clock_gettime(CLOCK_MONOTONIC, {tv_sec=3985, tv_nsec=838769641}) = 0 <0.000021>
readlinkat(AT_FDCWD, "/proc/self/exe", "/root/testgo/hello", 128) = 18 <0.000043>
fcntl(0, F_GETFL)                       = 0x8002 (flags O_RDWR|O_LARGEFILE) <0.000018>
futex(0xc0000324c8, FUTEX_WAKE_PRIVATE, 1) = 1 <0.000028>
mmap(NULL, 262144, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f654e31e000 <0.000013>
fcntl(1, F_GETFL)                       = 0x8002 (flags O_RDWR|O_LARGEFILE) <0.000015>
fcntl(2, F_GETFL)                       = 0x8002 (flags O_RDWR|O_LARGEFILE) <0.000013>
write(1, "hello, world\n", 13)          = 13 <0.000051>
exit_group(0)                           = ?
+++ exited with 0 +++

call数

# cat hello.log | wc -l
171

Locust + AWS ECS(Fargate)で負荷試験環境を作った話

これはなに?

Kyash Advent Calendar 2020 21日目の記事です。

今回はKyashに導入した負荷試験環境について紹介します。

経緯

Kyashでは決済や入金周りの性能試験は実施していましたが、シナリオベースの負荷試験など不十分な部分がありました。
そのためキャンペーンなどで通常より多くのアクセスが発生した場合に、

  • どのくらい耐えれるのか
  • どこのサーバがボトルネック
  • 適切なスケール具合はどの程度か

などの情報で曖昧な部分がありました。

そこでシナリオベースな負荷試験を実施することにより、
事前にどの程度までスケールすればどの程度の負荷まで耐えられるのかを把握し
適切なタイミングでの適切なスケーリングを実現することで
システムを安定稼働をさせていきたいと考えました。

ツールの選定

負荷試験を実施するにあたり主な要件は下記でした。

  • loginしないといけないのでsession管理ができるもの
  • ある程度のシナリオを組めるもの
  • CloudServiceとのintegrationが容易なもの

色々なツールを比較し下記理由からLocustを使うことにしました。

  • 情報が多いのでいろいろ参考にできそう
  • ecsやfargateとの親和性も高そう
  • 分散実行がサポートされているためスケールも容易そう

locust.io

また、インフラ部分は基本的にAWSを使用しているのでAWS ECS(Fargate) でworkerを簡単にスケールできるようにしました。

構成

f:id:gettergot:20201203105802p:plain
kyash_locust

workerはFargateのtask数を変更することでスケール可能にしてます。
オートスケールにしなくても負荷が出ないなら手でtask数あげれば問題ないかなという判断です。
また、LocustのUIはOneLoginで認証(OIDC)を行ってます。
さらにDatadogでLocustの監視をしながらworkerの負荷状況もdashboardで確認できるようになっています。

Locustの構成

Locust側のDirectory構成は下記

$ tree -I '__pycache__' --prune locust/
locust/
├── common
│   ├── __init__.py
│   ├── auth.py
│   ├── const.py
│   └── env.py
├── locustfiles
│   └── 20203Q
│       └── locustfile.py
└── task_set
    ├── __init__.py
    ├── const.py
    └── wallet_tab.py

基本的には、どこをシミュレートして負荷を掛けるかによってファイルを別けています。

例としてtop画面に負荷を掛けるシナリオだと、SequentialTaskSetを使用してTop画面を表示するのにCallされるAPIを登録しています。 (コードはあくまで例なので実際は少し違います)

docs.locust.io

locustfile.py

from locust import HttpUser, constant
from task_set import wallet_tab

class KyashUser(HttpUser):
    tasks = {wallet_tab.WalletTabTaskSet: 1}
    wait_time = constant(0.01)

wallet_tab.py

from locust import SequentialTaskSet, task
from common import auth
from task_set.const import *


class WalletTabTaskSet(SequentialTaskSet):
    token = ""

    def on_start(self):
        auth_task = auth.AuthTask(self)
        self.token = auth_task.login(const.EMAIL, const.PASSWORD)

    @task
    def device(self):
        res = self.client.post("/v1/hoge", json={"device": {
            "token": const.DEVICE_TOKEN}}, headers={auth.AuthTask.getHeader(): self.token})
        print(res.text)

.....

LocustのUI

f:id:gettergot:20201208104632p:plain
locust_UI
負荷試験を開始するときは上記画面から値を設定します。

Number of users to simulateには、作成するクライアント数を指定します。 Hatch rateには、クライアント数の増加ペースを指定します。

どのくらい負荷を掛けているのかが簡易的ではありますが、ビジュアライズされていてわりと見やすい感じになってます。

f:id:gettergot:20201204101202p:plain
UI

まとめ

負荷試験を実施することで、課題であった、

  • どのくらい耐えれるのか
  • どこのサーバがボトルネック
  • 適切なスケール具合はどの程度か

を把握して戦略的にスケールすることが可能になりました。
また、いつの日かCI環境でリリースフローの中に組み込みたいという夢もあるので、引き続き負荷試験環境も整備していければと思ってます。

Kyash Advent Calendar 2020 の他の記事もぜひ読んでみてください。

goenvでGOPATHの間にversionが入ってしまう場合の対処法

Golangの環境構築をしていてハマった箇所があったので解決法を書いておく

goenvを使ってGolangをインストールした時にGOPATHにversionが入ってしまって困った

goenv/CHANGELOG.md at master · syndbg/goenv · GitHub

Changed goenv's bootstrap (eval $(goenv init -)) now to call goenv-sh-rehash --only-manage-paths. This means that it'll export and manage GOROOT and GOPATH env vars

上記にあるように goenv2.0.0beta6 以上だとGOPATHが $HOME/go/$GO_VERSION のようになってしまう

Add management of env variable GOPATH that can be disabled with env var GOENV_DISABLE_GOPATH=1, when calling goenv-sh-rehash (goenv rehash when eval $(goenv init -) was previously executed).

対処法も載っていて下記のように環境変数を設定すればよい

export GOENV_DISABLE_GOPATH=1

ローレンツアトラクターをpythonで組む

グラブルで10賢者の一人であるフラウを取得して
フラウのアビリティであるストレンジアトラクターの画像を見ていたら
これはローレンツアトラクターだなぁって思って描いてみたくなった
https://img.gamewith.jp/img/original_ccc7e1ceb0ec907345669057b46a9823.jpg

ストレンジアトラクター
https://img.gamewith.jp/img/318c22a31253454529108b0a6bea75fb.jpg

今回はEuler法ではなくRunge-Kutta法でやってます
いきなりコードを貼るとこんな感じ

gist.github.com

最近は仕事でGolangを使ってるからGolangで書いてみようかと思ったけどいいplotライブラリが見つからなかったので
無難にpythonに落ち着いた
にしても matplotlib は便利だなぁと...

ちなみに実行するとこんな感じのgifが生成される

f:id:gettergot:20201025104046g:plain

awkの変わりにPerlワンライナーを使う

たまにCapistranoとか使っててawk使いたい時とかにエスケープが難しすぎてイライラすることがある
そんなときにPerlワンライナーawkの変わりをさせたりするのでメモがてら載せておく

capistranorb.com

awk

その時によって違うのでなんとも言えないがこんな感じで使う

$ echo -e 'a b c\nd e f' | awk '{print $1 $2}'
ab
de

$ echo -e 'a b c\nd e f' | perl -anle '($first, $second)=@F; print $first . $second;'
ab
de

sed

わりと簡単にできる

cat a.txt | perl -pe 's/(a|f)/1/g'
1 b c d
e 1 g h

まとめ

Perlってべんり