Open-Lowcodeを触ってみようとして途中で諦めた
Open-Lowcodeを触ってみようぜという話が出たので見てみる。 ISUCONで使えるなんらかのアプリとか作れたらいいな。
情報
- 公式サイト
- 概要説明っぽいの:10 minutes Open Lowcode tutorial - Open Lowcode
- 環境設定:Open Lowcode Operation Guide · openlowcode/Open-Lowcode Wiki · GitHub
- 開発者ガイド:Open Lowcode Developper Guide · openlowcode/Open-Lowcode Wiki · GitHub
- ライセンスはEclipse Public License 2.0 → オープンソースライセンスについてまとめてみた - OthloBlog - オスロブログ -
- 日本語の情報は簡単な紹介以外出てこなかった。
とりあえずOperation-Guide読んで動かす
ガイドのPrerequisitesの部分
Open Lowcode Operation Guide · openlowcode/Open-Lowcode Wiki · GitHub
ある程度ubuntu上で作業してから気づいたが、手順にbatファイルがあってwindowsの方が良かった。Windows Serverでやり直す。
インストール
- chrome, 7zip
- https://cdn.azul.com/zulu/bin/zulu8.52.0.23-ca-fx-jdk8.0.282-win_x64.msi
- https://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/2018-09/R/eclipse-java-2018-09-win32-x86_64.zip
ガイドのInstallationの部分
「Open Lowcode zip file」って何?
ISUCON練習日記2021-03-13 ISUCON10予選
ISUCON10予選問題で練習した。色々忘れないようにメモ。
DB分割
DBの設定複製 estate/chairを触るSQLごとに振り分け
・DBインスタンス複製
分割前測定
{"pass":true,"score":902,"messages":[],"reason":"OK","language":"go"}
1,2号機CPU
## アプリプロファイル 16:20 key count sum avg main.searchChairs 1729 154460 150.25 main.searchChairs: part2 1729 114261 111.15 main.searchEstateNazotte 102 101176 991.92 main.searchEstateNazotte: part2 102 88169 864.40 main.searchEstates 2824 87232 84.86 main.searchEstates: part2 2824 60437 58.79 main.getEstateDetail 4712 43916 42.72 main.getChairDetail 3848 42513 41.36 main.searchChairs: part3 1729 38794 37.74 main.searchEstates: part3 2824 24082 23.43 main.searchEstateNazotte: part1 102 12918 126.65 main.getLowPricedEstate 744 11152 14.99 main.searchRecommendedEstateWithChair 459 11142 24.27 main.getLowPricedChair 744 10286 13.83 16:20 ## nginxログ 16:20 +-------+-----+-------+-----+-----+-----+--------+------------------------------+---------+-------+-------+-------+-----------+-----------+ | COUNT | 1XX | 2XX | 3XX | 4XX | 5XX | METHOD | URI | SUM | AVG | MIN | MAX | MIN(BODY) | MAX(BODY) | +-------+-----+-------+-----+-----+-----+--------+------------------------------+---------+-------+-------+-------+-----------+-----------+ | 1729 | 0 | 1714 | 0 | 15 | 0 | GET | /api/chair/search | 224.296 | 0.130 | 0.005 | 1.132 | 0.000 | 17925.000 | | 2824 | 0 | 2811 | 0 | 13 | 0 | GET | /api/estate/search | 203.415 | 0.072 | 0.004 | 1.062 | 0.000 | 27095.000 | | 4712 | 0 | 4667 | 0 | 45 | 0 | GET | /api/estate/\d+ | 171.501 | 0.036 | 0.004 | 0.984 | 0.000 | 705.000 | | 3848 | 0 | 3823 | 0 | 25 | 0 | GET | /api/chair/\d+ | 154.742 | 0.040 | 0.004 | 1.080 | 0.000 | 647.000 | | 102 | 0 | 99 | 0 | 3 | 0 | POST | /api/estate/nazotte | 100.232 | 0.983 | 0.676 | 1.464 | 0.000 | 33942.000 | | 744 | 0 | 744 | 0 | 0 | 0 | GET | /api/estate/low_priced | 12.096 | 0.016 | 0.004 | 0.340 | 13383.000 | 13426.000 | | 459 | 0 | 459 | 0 | 0 | 0 | GET | /api/recommended_estate/\d+ | 11.752 | 0.026 | 0.004 | 0.404 | 13081.000 | 13712.000 | | 744 | 0 | 743 | 0 | 1 | 0 | GET | /api/chair/low_priced | 10.976 | 0.015 | 0.004 | 0.684 | 0.000 | 12186.000 | | 674 | 0 | 674 | 0 | 0 | 0 | POST | /api/estate/req_doc/\d+ | 5.288 | 0.008 | 0.004 | 0.148 | 0.000 | 0.000 | | 228 | 0 | 228 | 0 | 0 | 0 | POST | /api/chair/buy/\d+ | 4.048 | 0.018 | 0.004 | 0.168 | 0.000 | 0.000 | | 1 | 0 | 1 | 0 | 0 | 0 | POST | /initialize | 4.044 | 4.044 | 4.044 | 4.044 | 23.000 | 23.000 | | 3 | 0 | 3 | 0 | 0 | 0 | POST | /api/estate | 3.404 | 1.135 | 0.528 | 1.516 | 0.000 | 0.000 | | 4 | 0 | 3 | 0 | 1 | 0 | POST | /api/chair | 3.403 | 0.851 | 0.187 | 1.380 | 0.000 | 0.000 | | 414 | 0 | 414 | 0 | 0 | 0 | GET | /api/estate/search/condition | 0.444 | 0.001 | 0.000 | 0.008 | 2563.000 | 2563.000 | ... +-------+-----+-------+-----+-----+-----+--------+------------------------------+---------+-------+-------+-------+-----------+-----------+ | 16720 | 0 | 16617 | 0 | 103 | 0 | +-------+-----+-------+-----+-----+-----+--------+------------------------------+---------+-------+-------+-------+-----------+-----------+ # Rank Query ID Response time Calls R/Call V/M # ==== =================================== ============== ===== ====== === # 1 0xB718722664D79180DE3386CFE9C21BF6 84.6158 23.1% 102 0.8296 0.02 SELECT estate # 2 0x4E8EAE12D58B73C2F3EFAD4903F0402F 27.5122 7.5% 281 0.0979 0.01 SELECT chair # 3 0x929E86BFE887C4E10B23D92EDD8D61BC 11.7012 3.2% 204 0.0574 0.01 SELECT estate # 4 0xE010F89F59F07FE84177E58CAC7321CE 10.8306 3.0% 102 0.1062 0.01 SELECT estate # 5 0xED731470FE91D25E31E27AD9C15C891F 10.3488 2.8% 191 0.0542 0.01 SELECT estate # 6 0x85EDDA9F02FE0A0E65DBB57A0B593F83 7.3063 2.0% 133 0.0549 0.01 SELECT chair # 7 0x3636444F1E726DFB63C508D1F648A860 6.6427 1.8% 80 0.0830 0.00 SELECT estate # MISC 0xMISC 207.6529 56.6% 6234 0.0333 0.0 <279 ITEMS>
分割後測定
{"pass":true,"score":1261,"messages":[],"reason":"OK","language":"go"}
1.5倍くらいになった。DB分割の効果がでている。
1,2,3号機CPU(右端の山)
## アプリプロファイル 16:30 key count sum avg main.searchEstateNazotte 210 162128 772.04 main.searchEstateNazotte: part2 210 138214 658.16 main.searchChairs 2784 125966 122.53 main.searchEstates 3374 117236 114.04 main.searchChairs: part2 2784 79401 77.24 main.searchEstates: part2 3374 74178 72.16 main.getEstateDetail 8151 51884 50.47 main.searchChairs: part3 2784 50158 48.79 main.searchEstates: part3 3374 35627 34.66 main.getChairDetail 7103 35234 34.27 main.searchEstateNazotte: part1 210 23718 112.94 main.getLowPricedEstate 1022 20305 19.87 main.searchRecommendedEstateWithChair 710 19414 27.34 main.postEstateRequestDocument 910 13805 15.17 16:30 ## nginxログ 16:30 +-------+-----+-------+-----+-----+-----+--------+------------------------------+---------+-------+-------+-------+-----------+-----------+ | COUNT | 1XX | 2XX | 3XX | 4XX | 5XX | METHOD | URI | SUM | AVG | MIN | MAX | MIN(BODY) | MAX(BODY) | +-------+-----+-------+-----+-----+-----+--------+------------------------------+---------+-------+-------+-------+-----------+-----------+ | 8158 | 0 | 8112 | 0 | 46 | 0 | GET | /api/estate/\d+ | 385.097 | 0.047 | 0.016 | 1.168 | 538.000 | 713.000 | | 3374 | 0 | 3366 | 0 | 8 | 0 | GET | /api/estate/search | 307.486 | 0.091 | 0.004 | 0.940 | 0.000 | 20715.000 | | 2784 | 0 | 2772 | 0 | 12 | 0 | GET | /api/chair/search | 287.663 | 0.103 | 0.012 | 1.084 | 0.000 | 20851.000 | | 7103 | 0 | 7075 | 0 | 28 | 0 | GET | /api/chair/\d+ | 237.831 | 0.033 | 0.004 | 0.820 | 0.000 | 659.000 | | 210 | 0 | 206 | 0 | 4 | 0 | POST | /api/estate/nazotte | 161.540 | 0.769 | 0.062 | 1.560 | 0.000 | 34291.000 | | 1022 | 0 | 1022 | 0 | 0 | 0 | GET | /api/estate/low_priced | 22.344 | 0.022 | 0.008 | 0.564 | 13323.000 | 13427.000 | | 710 | 0 | 707 | 0 | 3 | 0 | GET | /api/recommended_estate/\d+ | 20.386 | 0.029 | 0.004 | 0.684 | 0.000 | 13727.000 | | 910 | 0 | 910 | 0 | 0 | 0 | POST | /api/estate/req_doc/\d+ | 14.880 | 0.016 | 0.004 | 0.908 | 0.000 | 0.000 | | 1022 | 0 | 1022 | 0 | 0 | 0 | GET | /api/chair/low_priced | 14.548 | 0.014 | 0.004 | 0.264 | 12139.000 | 12186.000 | | 7 | 0 | 7 | 0 | 0 | 0 | POST | /api/estate | 11.976 | 1.711 | 0.464 | 2.352 | 0.000 | 0.000 | | 7 | 0 | 7 | 0 | 0 | 0 | POST | /api/chair | 11.736 | 1.677 | 0.484 | 2.768 | 0.000 | 0.000 | | 1 | 0 | 1 | 0 | 0 | 0 | POST | /initialize | 7.304 | 7.304 | 7.304 | 7.304 | 23.000 | 23.000 | | 351 | 0 | 351 | 0 | 0 | 0 | POST | /api/chair/buy/\d+ | 5.736 | 0.016 | 0.004 | 0.120 | 0.000 | 0.000 | | 458 | 0 | 458 | 0 | 0 | 0 | GET | /api/estate/search/condition | 0.620 | 0.001 | 0.004 | 0.020 | 2563.000 | 2563.000 | ... +-------+-----+-------+-----+-----+-----+--------+------------------------------+---------+-------+-------+-------+-----------+-----------+ | 26478 | 0 | 26377 | 0 | 101 | 0 | +-------+-----+-------+-----+-----+-----+--------+------------------------------+---------+-------+-------+-------+-----------+-----------+ # Rank Query ID Response time Calls R/Call V/M # ==== =================================== ============== ===== ====== === # 1 0x4E8EAE12D58B73C2F3EFAD4903F0402F 11.5774 5.1% 328 0.0353 0.02 SELECT chair # 2 0x4FA7F17A15BCD31A08C4C2F052598EB7 5.8728 2.6% 74 0.0794 0.02 SELECT chair # 3 0x929787B1FE641900E3DD23571CAC3AB6 5.5240 2.4% 72 0.0767 0.02 SELECT chair # 4 0x17813360728C84E63F19DC57445EC358 4.3238 1.9% 29 0.1491 0.10 SELECT chair # 5 0x9CCCD1D3E32D61BB18B4ECD908E723B4 4.1910 1.8% 59 0.0710 0.02 SELECT chair # 6 0xF6CBE5E7B4D4ECE4095626C611F2D411 3.8432 1.7% 47 0.0818 0.01 SELECT chair # 7 0x7A3943FC5D195AC5C0824B77FDBE8C4F 2.9514 1.3% 24 0.1230 0.01 SELECT chair # MISC 0xMISC 190.5975 83.3% 4891 0.0390 0.0 <567 ITEMS> # Rank Query ID Response time Calls R/Call V/M # ==== =================================== ============== ===== ====== === # 1 0xB718722664D79180DE3386CFE9C21BF6 135.2677 41.9% 207 0.6535 0.06 SELECT estate # 2 0xE010F89F59F07FE84177E58CAC7321CE 17.7821 5.5% 207 0.0859 0.01 SELECT estate # 3 0x3636444F1E726DFB63C508D1F648A860 9.3767 2.9% 129 0.0727 0.01 SELECT estate # 4 0x3A6102F5BB1888CE18692940986AC2AD 8.2232 2.5% 111 0.0741 0.00 SELECT estate # 5 0xAA809559207975DC00087902517AC50D 6.6264 2.1% 97 0.0683 0.01 SELECT estate # 6 0x9874FCB909778990D4BDA82D2EB9C996 6.5708 2.0% 90 0.0730 0.00 SELECT estate # 7 0x63EDCA18912C7FEE67A0CB124E70256F 5.7084 1.8% 74 0.0771 0.01 SELECT estate # MISC 0xMISC 133.2300 41.3% 4788 0.0278 0.0 <135 ITEMS>
ISUCON練習日記2021-03-07 ISUCON10予選
ISUCON10予選問題で練習した。色々忘れないようにメモ。
IP取得
wget -q -O - http://checkip.amazonaws.com/
ファイルサイズ
sudo ls -lh /var/log/mysql/mysql-slow.log |awk '{print $5}'
nazotteのN+1をなんとかしようとする
方針は複数ある
- POINT 型
- アプリ側で内外判定する
geo系sqlを簡易テスト
結局syntax errorを越えられずできなかった。
$ sudo mysql isuumo -e "SELECT ST_Contains(ST_PolygonFromText('POLYGON((1 1,1 2,2 2,2 1,3 3))'), ST_GeomFromText('POINT(1 1 )'))" ERROR 3037 (22023) at line 1: Invalid GIS data provided to function st_geometryfromtext.
MySQL Bugs: #76595: "Invalid GIS data provided" reported with valid geometries 記法ミスなのかバグなのかバージョン差異なのか不明
アプリログ出す
【systemd】StandardOutput=fileはログをファイルに出力できるけど追記されない | 純規の暇人趣味ブログ
journalctl -u isuumo.go.service でチラ見はできる、でも長いので実用性低い sudo vi /etc/systemd/system/isuumo.go.service [Service] StandardOutput=append:/tmp/test.log sudo systemctl daemon-reload sre $ sudo journalctl --version systemd 237 +PAM +AUDIT +SELINUX +IMA +APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD -IDN2 +IDN -PCRE2 default-hierarchy=hybrid
240未満だったので意味なかった。
sudo vi /etc/systemd/system/isuumo.go.service $ sudo systemctl daemon-reload && sre && sst ● isuumo.go.service - isuumo.go Loaded: loaded (/etc/systemd/system/isuumo.go.service; enabled; vendor preset: enabled) Active: activating (auto-restart) (Result: exit-code) since Sat 2021-03-06 15:16:46 UTC; 29ms ago Process: 11467 ExecStart=/bin/sh -c exec /home/isucon/isuumo/webapp/go/isuumo >> /var/log/isuapp.log (code=exited, status=2) Main PID: 11467 (code=exited, status=2) Mar 06 15:16:46 ix systemd[1]: isuumo.go.service: Main process exited, code=exited, status=2/INVALIDARGUMENT Mar 06 15:16:46 ix systemd[1]: isuumo.go.service: Failed with result 'exit-code'. sudo touch /var/log/isuapp.log sudo chmod 666 /var/log/isuapp.log sudo ls -l /var/log/isuapp.log -rw-rw-rw- 1 root root 0 Mar 6 15:17 /var/log/isuapp.log $ sudo systemctl daemon-reload && sre && sst ● isuumo.go.service - isuumo.go Loaded: loaded (/etc/systemd/system/isuumo.go.service; enabled; vendor preset: enabled) Active: active (running) since Sat 2021-03-06 15:17:25 UTC; 54ms ago Main PID: 11724 (isuumo) Tasks: 4 (limit: 2333) CGroup: /system.slice/isuumo.go.service └─11724 /home/isucon/isuumo/webapp/go/isuumo Mar 06 15:17:25 ix systemd[1]: Started isuumo.go.
ログファイルが存在しないときもINVALIDARGUMENTになる。ちょっとわかりにくい。
tail -f /var/log/isuapp.log
nazotte N+1 part0 ソースコード構造変化
読み解き(L1049くらいのestatesInPolygon := []Estate{}から15行くらい)
内容を整理するとこんな感じ
- IN: coordinates
- 長方形に絞ったestate群を得る
- for: estate(長方形に絞ったestate群)
- select: lat/lonとidを条件に内外判定し、内なら1件得る
- 結果があるならappend
- 数を制限する
- OUT: Estates
このSQLをforの外に出すことを考える
SQL文の代入箇所を変数名で埋めるとこうなる
SELECT * FROM estate WHERE id = estate.ID AND ST_Contains( ST_PolygonFromText( coordinates.coordinatesToText() ), ST_GeomFromText( 'POINT(estate.Latitude estate.Longitude)' ) )
条件部に代入値ではなくテーブルが持つ列を渡してしまえば一気に結果を得られる。
SELECT * FROM estate AND ST_Contains( ST_PolygonFromText( 'POLYGON((10.0 10.0,100.0 10.0,100.0 100.0,10.0 100.0))' ), ST_GeomFromText( 'POINT(latitude longitude)' ) )
このSQLが正しいか、どう試すのがもっとも早いか?
文法レベルはオンラインのシンタックスチェッカーが早いかも。
$ sudo mysql isuumo -e " > SELECT * FROM estate > WHERE > ST_Contains( > ST_PolygonFromText( > 'POLYGON((10.0 10.0,100.0 10.0,100.0 100.0,10.0 100.0))' > ), > ST_GeomFromText( > 'POINT(latitude longitude)' > ) > ) limit 1 > " ERROR 3037 (22023) at line 2: Invalid GIS data provided to function st_geometryfromtext.
st_geometryfromtext噛んでるから列名が読めるわけないか。 CONCAT('POINT(', latitude, ' ', longitude, ')'))とかにする必要がある。まあでもpoint型作るか・・・
POINT型を作る(次項)
nazotte N+1 part1 point型列の追加
vi 0_Schema.sql point POINT AS (POINT(latitude, longitude)) STORED NOT NULL, ./init.sh $ sudo mysql isuumo -e "describe estate" +-----------------+---------------+------+-----+---------+-------------------+ | Field | Type | Null | Key | Default | Extra | +-----------------+---------------+------+-----+---------+-------------------+ | id | int(11) | NO | PRI | NULL | | | name | varchar(64) | NO | | NULL | | | description | varchar(4096) | NO | | NULL | | | thumbnail | varchar(128) | NO | | NULL | | | address | varchar(128) | NO | | NULL | | | latitude | double | NO | | NULL | | | longitude | double | NO | | NULL | | | rent | int(11) | NO | MUL | NULL | | | door_height | int(11) | NO | | NULL | | | door_width | int(11) | NO | | NULL | | | features | varchar(64) | NO | | NULL | | | popularity | int(11) | NO | | NULL | | | popularity_desc | int(11) | NO | MUL | NULL | VIRTUAL GENERATED | +-----------------+---------------+------+-----+---------+-------------------+ エラーは出てないけど型にも追加されてない。 反映先DBが別サーバだったからだった。 $ sudo mysql isuumo -e "describe estate" | point | point | NO | | NULL | VIRTUAL GENERATED | $ sudo mysql isuumo -e "SELECT latitude, longitude,point, ST_X(point), ST_Y(POINT) from estate limit 1" +-------------------+-------------------+---------------------------+-------------------+-------------------+ | latitude | longitude | point | ST_X(point) | ST_Y(POINT) | +-------------------+-------------------+---------------------------+-------------------+-------------------+ | 37.71778813321466 | 140.2540394463388 | F{B@i=U!a@ | 37.71778813321466 | 140.2540394463388 | +-------------------+-------------------+---------------------------+-------------------+-------------------+ STOREDの意味は以下。 SPATIAL INDEX の有効化のため。 > Generated Columnには、「VIRTUAL」 or 「STORED」が指定できます。 > 「VIRTUAL」は実データを持たず、読み込むタイミングで計算します。 > 「STORED」は計算結果を記憶領域に保存し、通常の列情報のように読み取ります。 > 既定値は「VIRTUAL」です。 [https://www.dcom-web.co.jp/lab/database/mysql/generated_column:title]
nazotte N+1 part2 SQL変形
1.SQL変形 query2 := fmt.Sprintf(`/*[N1] */SELECT * FROM estate WHERE ST_Contains(ST_PolygonFromText(%s), point)`, coordinates.coordinatesToText()) 2.受け皿用意 estates2 := []Estate{} 3.SQL実行(getで複数取れる) err = db.Get(&estates2, query2) 4.ログ出してみる c.Echo().Logger.Debugf(" N1 length:%d", len(estates2)) $ go build && sre && curl localhost/api/stats key,count,sum,avg この時点でビルドは成功、アプリ起動成功はしてる。ただなぞってをやってみるとエラー出ている $ tail -f /var/log/isuapp.log | ./colorizer.sed {"time":"2021-03-07T01:45:22.06709935Z","level":"ERROR","prefix":"echo","file":"main.go","line":"1005","message":"Database execution error : missing destination name point in *[]main.Estate"} {"time":"2021-03-07T01:45:22.070117889Z","id":"","remote_ip":"127.0.0.1","host":"localhost:1323","method":"GET","uri":"/api/recommended_estate/10831","user_agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36","status":500,"error":"","latency":7294970,"latency_human":"7.29497ms","bytes_in":0,"bytes_out":0} missing destination name point つまりpointの詰め先がない、Estateに追加し忘れていた {"time":"2021-03-13T04:16:28.149906619Z","level":"ERROR","prefix":"echo","file":"main.go","line":"736","message":"Database Execution error : sql: Scan error on column index 12, name \"point\": converting driver.Value type []uint8 (\"\\x00\\x00\\x00\\x00\\x01\\x01\\x00\\x00\\x00\\x8a\\x1a\\xc49\\xe1/B@\\xc4\\xee\\xf6\\x15s_a@\") to a int64: invalid syntax"} intだと怒られた // err = db.Get(&estates2, query2) err = db.Select(&estates2, query2) 複数なのでselectにする必要がある {"pass":false,"score":0,"messages":[{"text":"POST /api/estate/nazotte: レスポンスが不正です","count":4}],"reason":"スコアが0点を下回りました","language":"go"}
ようやくN+1を解消できた スコアはむしろちょっと下がってしまったが、 main.searchEstateNazotteがavgが半分くらいになってcountが1.5倍くらいになった。
{"pass":true,"score":878,"messages":[{"text":"POST /api/estate/nazotte: リクエストに失敗しました (タイムアウトしました)","count":21}],"reason":"OK","language":"go"} key count sum avg main.searchEstateNazotte 64 151911 2373.61 main.searchEstateNazotte: part2 64 143798 2246.84 main.searchChairs 1755 130583 127.03 main.searchChairs: part2 1755 101552 98.79 main.searchEstates 2757 80959 78.75 main.searchEstates: part2 2757 57661 56.09 main.searchChairs: part3 1755 31096 30.25 main.getEstateDetail 4619 30148 29.33 main.getChairDetail 3813 29353 28.55 main.searchEstates: part3 2757 21818 21.22 main.searchRecommendedEstateWithChair 475 11247 23.68 main.getLowPricedChair 703 8763 12.47 main.searchEstateNazotte: part1 64 8065 126.02 main.getLowPricedEstate 703 7742 11.01 {"pass":true,"score":862,"messages":[],"reason":"OK","language":"go"} key count sum avg main.searchChairs 1618 145225 141.27 main.searchChairs: part2 1618 112470 109.41 main.searchEstateNazotte 92 90917 988.23 main.searchEstates 2706 81321 79.11 main.searchEstateNazotte: part2 92 79046 859.19 main.searchEstates: part2 2706 60499 58.85 main.getChairDetail 3515 37648 36.62 main.getEstateDetail 4358 33131 32.23 main.searchChairs: part3 1618 32321 31.44 main.searchEstates: part3 2706 23101 22.47 main.searchEstateNazotte: part1 92 11795 128.21 main.searchRecommendedEstateWithChair 437 11189 25.60 main.getLowPricedChair 706 9845 13.95 main.getLowPricedEstate 706 9203 13.04
ログを見やすくする
tail
https://github.com/shimodatkh/colorizer/blob/master/colorizer.sed
cd wget https://raw.githubusercontent.com/shimodatkh/colorizer/master/colorizer.sed chmod 777 colorizer.sed tail -f /var/log/isuapp.log | ~/colorizer.sed
less
sudo apt-get install source-highlight export LESS='-R' export LESSOPEN='| /usr/share/source-highlight/src-hilite-lesspipe.sh %s' less /var/log/isuapp.log
ISUCON練習日記2021-02-26 ISUCON10予選
ISUCON10予選問題で練習した。色々忘れないようにメモ。
generated columns追加
とりあえず入れてみる
popularity_desc INTEGER AS (-popularity) NOT NULL,
2021/02/22 19:35:29 bench.go:102: verify failed {"pass":false,"score":0,"messages":[{"text":"GET /api/estate/:id: レスポンスが不正です","count":5},{"text":"GET /api/estate/low_priced: レスポンスが不正です","count":1},{"text":"GET /api/estate/search: レスポンスが不正です","count":5},{"text":"GET /api/recommended_estate/:id: レスポンスが不正です","count":5},{"text":"POST /api/estate/nazotte: レスポンスが不正です","count":5},{"text":"登録済み物件の詳細取得に失敗しました","count":1}],"reason":"スコアが0点を下回りました","language":"go"}
単に入れただけだとダメ。アプリログにエラー出てる。
[19:52:02 isucon@ix ~]$ sudo systemctl status isuumo.go.service ● isuumo.go.service - isuumo.go Loaded: loaded (/etc/systemd/system/isuumo.go.service; enabled; vendor preset: enabled) Active: active (running) since Mon 2021-02-22 19:35:22 UTC; 16min ago Process: 25939 ExecStop=/bin/kill -s QUIT $MAINPID (code=exited, status=0/SUCCESS) Main PID: 25940 (isuumo) Tasks: 5 (limit: 2333) CGroup: /system.slice/isuumo.go.service └─25940 /home/isucon/isuumo/webapp/go/isuumo Feb 22 19:35:29 ix isuumo[25940]: {"time":"2021-02-22T19:35:29.141867316Z","level":"ERROR","prefix":"echo","file":"main.go","line":"733","message":"Database Execution error : missing destination name popularity_desc in *main.Estate"}
733行目見ると代入失敗っぽい。struct定義にPopularityDesc int64
db:"popularity_desc" json:"-"``を追加する。
var estate Estate err = db.Get(&estate, "SELECT * FROM estate WHERE id = ?", id) if err != nil { if err == sql.ErrNoRows { c.Echo().Logger.Infof("getEstateDetail estate id %v not found", id) return c.NoContent(http.StatusNotFound) } c.Echo().Logger.Errorf("Database Execution error : %v", err) return c.NoContent(http.StatusInternalServerError) }
SQLコメント
GoでSQLにトレーシングコメントを埋め込んで実行する | おそらくはそれさえも平凡な日々
これやってみたいなと思ったけど、sqlx使ってるコードに大してあまり書き換えずにやる方法あるのかな?分からなかった。記事はdatabase/sql、ISUCON10予選問題はgithub.com/jmoiron/sqlx。
generated columns使って5.7でも有効なインデックスを作成
インデックス追加
,INDEX popularity_desc_id(popularity_desc,id)
追加前後のexplain
これをやったあとは"score":607くらいになって、スロークエリの上位は椅子と不動産に条件色々くっつけるやつと位置情報の3種になっている。
]$ cat ~/slowq-state.log |sort /*[11] L1031 */SELECT * FROM estate WHERE latitude <= 36.53227509710664 AND latitude >= 35.58900608516611 AND longitude <= 137.92007832283616 AND longitude >= 137.34442150965003 ORDER BY popularity_desc ASC, id ASC\G /*[3] L586 */SELECT COUNT(*) FROM chair WHERE color = 'ピンク' AND stock > 0\G /*[3] L586 */SELECT COUNT(*) FROM chair WHERE depth >= 80 AND depth < 110 AND stock > 0\G /*[3] L586 */SELECT COUNT(*) FROM chair WHERE height < 80 AND stock > 0\G /*[3] L586 */SELECT COUNT(*) FROM chair WHERE height >= 110 AND height < 150 AND stock > 0\G /*[3] L586 */SELECT COUNT(*) FROM chair WHERE height >= 150 AND stock > 0\G /*[3] L586 */SELECT COUNT(*) FROM chair WHERE kind = 'エルゴノミクス' AND stock > 0\G /*[3] L586 */SELECT COUNT(*) FROM chair WHERE price < 3000 AND stock > 0\G /*[3] L586 */SELECT COUNT(*) FROM chair WHERE price >= 15000 AND stock > 0\G /*[3] L586 */SELECT COUNT(*) FROM chair WHERE price >= 9000 AND price < 12000 AND stock > 0\G /*[3] L586 */SELECT COUNT(*) FROM chair WHERE width >= 110 AND width < 150 AND stock > 0\G /*[7] L909 */SELECT COUNT(*) FROM estate WHERE door_height < 80\G /*[7] L909 */SELECT COUNT(*) FROM estate WHERE door_height >= 150\G /*[7] L909 */SELECT COUNT(*) FROM estate WHERE door_height >= 80 AND door_height < 110\G /*[7] L909 */SELECT COUNT(*) FROM estate WHERE door_width < 80\G /*[7] L909 */SELECT COUNT(*) FROM estate WHERE door_width >= 110 AND door_width < 150\G /*[7] L909 */SELECT COUNT(*) FROM estate WHERE door_width >= 150\G /*[7] L909 */SELECT COUNT(*) FROM estate WHERE rent >= 150000\G /*[7] L909 */SELECT COUNT(*) FROM estate WHERE rent >= 50000 AND rent < 100000\G
hub createコマンドが動かなくなった件
現在パスワード認証だとダメらしい。 Unable to authorize with my GitHub password (Unathorized/Not Found) · Issue #2655 · github/hub · GitHub
ISUCON練習日記2021-02-22 ISUCON10予選
ISUCON10予選問題で練習した。色々忘れないようにメモ。
流れ
- アプリ立てる
- ベンチ流す
- ベンチスクリプトで各データが自動で取れるようにしていく
- nginx
- app measure
- slow query
- netdata
他に自動化したい部分
- app log
- index
- explain
インスタンス複製
- スナップショット取得
- 同様のインスタンスを作成
- オプション:静的IP付与
これも自動化したい。
最新のGoインストール
最新版のGo言語をLinuxにインストールする手順をやった上で、パスが変わってなかったので以下をやる。
sudo rm /usr/bin/go export PATH=$PATH:/usr/local/go/bin go version
でもsnapを使うほうが楽かも
sudo snap install --channel=1.16/stable --classic go snap info go
slack通知でファイルを飛ばす
Slackのfiles.upload APIを使ってファイルを簡単に連携する - バナーナナブログ
OAuth & PermissionsでBot Token Scopesにfile:write権限を追加したけどうまく行かず、User Token Scopesの方に追加したらいけた。
curl -F file=@/home/isucon/pt.log -F channels=#notify_stats_result \ -H "Authorization: Bearer xoxp-hogehoge" https://slack.com/api/files.upload
MySQLWorkbenchで表示してみる
・クライアント上にツールインストール
・サーバ上で次のコマンド実行
sudo grep bind /etc/mysql/ -rni sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf bind_addressをコメントアウト sudo mysql -e "grant all privileges on isuumo.* to isucon@'%' identified by 'isucon' with grant option;" sudo systemctl restart mysql.service
インデックス追加
スロークエリで出てくる
SELECT * FROM chair WHERE stock > 0 ORDER BY price ASC, id ASC LIMIT 20
用に
INDEX stock_price_id (stock, price, id)
を貼った場合、さらにINDEX price_id (price, id)
を貼った場合の実行計画。
mysql> mysql> explain SELECT * FROM chair WHERE stock > 0 ORDER BY price ASC, id ASC LIMIT 20; +----+-------------+-------+------------+------+----------------+------+---------+------+-------+----------+-----------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+----------------+------+---------+------+-------+----------+-----------------------------+ | 1 | SIMPLE | chair | NULL | ALL | stock_price_id | NULL | NULL | NULL | 29281 | 50.00 | Using where; Using filesort | +----+-------------+-------+------------+------+----------------+------+---------+------+-------+----------+-----------------------------+ $ sudo mysql -e "use isuumo; explain SELECT * FROM chair WHERE stock > 0 ORDER BY price ASC, id ASC LIMIT 20;" +----+-------------+-------+------------+-------+----------------+----------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+-------+----------------+----------+---------+------+------+----------+-------------+ | 1 | SIMPLE | chair | NULL | index | stock_price_id | price_id | 8 | NULL | 40 | 50.00 | Using where | +----+-------------+-------+------------+-------+----------------+----------+---------+------+------+----------+-------------+
Using filesortはクイックソートのことらしい。 漢(オトコ)のコンピュータ道: Using filesort
ISUCON練習準備メモ
ISUCONの練習準備
チーム内部向けに、久しぶりにISUCON練習やるとき、諸々の操作を思い出すためのメモ。とりあえず上から順にやっていけば感覚が蘇る・・・はず。
クラウドコンソール
- インスタンス起動
ツール
- RLoginでログイン
- VSCodeでRemote Development接続
- Slack
よく使うaliasを思い出す
0 #ベンチ一式実行 br #vi bash profile so #source bash profile sli #サービスリスト sre #アプリ再起動
アプリ・ベンチ・ログ
- ブラウザでアプリにアクセス
- ベンチマークを実行、slackで結果確認
- ログ出てるか確認
- ログ分析結果が出てるか確認
メモ
スコアを追っていけるダッシュボード的なのが欲しい
ISUCONのススメの商業版・同人版の違い
サークルFrattyが技術書典9で頒布した「Webサービスチューニングコンテスト ISUCONのススメ」ですが、商業版の出版が決まりました。同人版から内容が増強されており、いくつか違いがあるため本記事にてまとめます。
同人版・商業版の差異は次の表の通りです。
同人版 | 商業版 | |
---|---|---|
販売プラットフォーム | 技術書典オンラインマーケット | 各種プラットフォーム |
媒体 | 電子版のみ | 電子版/印刷版 |
価格 | 500円(税込) | 電子版1,600円(税別) 印刷版 2,000円(税別) ※1 |
発売日 | 2020/09/12 | 2021/02/05 |
内容 | 詳細はこちら | 左記にリソースモニタリング、N+1問題・処理並列化・サーバ間リソース分散のトピックを追加 |
- ※1 それぞれのプラットフォームのセール等により価格が変化する場合があります。
(参考)目次の差分