sky’s 雑記

主にAndroidとサーバーサイドの技術について記事を書きます

なぜ正社員が難しいか

以前こういう記事を書いたが結構深掘りが進んだので忘れないうちにまとめておく。

今のところ社員をやることの最大のデメリットは会社に対して甘えが生じるということ、 会社目線だと自分がやっていること、やろうとしていることにメリットがないと分かっていても個人的な感情で自分を優先させてしまうことがある。 小さいことだと苦手だし面倒だから勤怠や目標設定や振り返りなどをサボるみたいなやつ、 こういった自分の行動も感知していないところで会社にもメリットはあるのもしれないが、 少なくとも自分はマネジメントコストが上がるだけでだるい奴と認識している。

分かっていながらなぜこういう行動をとるかというと冒頭に書いた通り社員だと甘えがあるから。 日本だと正社員の雇用は立場的に強いので多少ルールを守らないくらいではクビにならないとか、 嫌になったら別の会社に転職すればいいとか、 最悪クビになっても個人事業主をやればいいとか、 いくらでも言い訳ができることが要因だと今のところは分析している。

この状態開き直れればやりたいことをやらずに金をもらえる状態なので別に良いのだが、 自分の理想は金をもらっている限りは会社の理になる行動を取り続けることなので、 理想とは異なるムーブをやらざるを得ない状態が続くとひたすらストレスが溜まる。

なぜ非社員という立場だとマシなのかというと甘えがなくなるからで、 雇用関係にないとやはり金を払っているほうが圧倒的に強いという意識があり、 多少嫌なことがあっても個人的な感情ではなくクライアントにとっての理で動ける。 (勿論相対的に正社員のほうが自分の苦手な仕事が多いということもあると思う)

こう考えると雇用や契約が安定しないという事実が個人的な感情を押し殺してくれるのかもしれない、 今後会社員に戻りたいのなら安定した雇用を得ている状況でも個人の感情を押し殺して会社や組織のために働く自分の理想ムーブを実現する状況を作り出す必要がありそうです。

会社員向いてねぇよで済みますねこの話。\ ドッ /

正社員とフリーランスのpros/consと重要度

正社員を辞めて1ヶ月くらい経過しました、 喉元過ぎれば〜で悪いことも時が経つと美化されて後々誤った選択をしてしまうのでつらつら書いていきます。

正社員

pros

  • ★★★☆☆ ラベル

まじでくだらねぇと思いつつ、どこどこ株式会社です、というと「オー(棒読み)」ってなったりするし世間的には一定の信用になりそう。 ローンも組みやすいらしい。

フリーランスだと自分が何をしたかを説明する必要があって、そこのプレッシャーがないぶん社員は楽かなと思う。

  • ★★★★☆ やる気があれば大きい仕事に携われる

成果を出し評価をされれば、という前提で大きい仕事を経験できる、 こういう経験をしてると市場価値も上がるのでなんとなくキャリア的に安心できる。

将来的にも個人で仕事を受けられる状態になっていることに価値を置いているので、 正社員適正が低いのは分かりつつもこの点は魅力に感じる。

会社が健康保険料を持ってくれる、有給がある、企業型確定拠出年金がある、傷病手当がある等 ありがたいけど、今は健康に働けており、いうて大した額ではないので重要度は低い。

こういうのは実際にそういう状況になって初めてありがたみを感じるものだと思う、 今は現実味なし。

cons

  • ★★★★★ 自分のペースで仕事が出来ない

特に大きめの会社で評価制度がちゃんとしているときつい、 目標とか期待値を設定されて毎週1on1でそれを管理されるとかなり病む。

ただしこれは会社が社員に何を期待するかにもよると感じており、 組織やチームへの貢献のような人に働きかけて何かを成すタイプのものだと自分的には負担が大きい。

ひたすらコーディングしていいもの作れだったら耐えられる可能性はあるけど、 それは資本主義が許さないと思う。

  • ★★★☆☆ 勤務体系が柔軟でない

フルリモート、裁量労働の会社が増えていてその点に不満はないが、 週5必ず労働しないといけないシステムが厳しい。 無給でいいから制度上無限に休んで良いとかであれば大丈夫かもしれない。

フリーランス

pros

  • ★★★☆☆ やりたくないことに折り合いをつけやすい

やりたくないことはやらないタイプだが、正社員でもフリーランスでも仕事をしている限りそんなことは言ってられない。 こういうときフリーランスだとお金払ってもらってるしクライアントのためにやるか、という具合に別のところにモチベーションを見出せるので頑張れる。

書いていて気づいたけど、一般的にこのケースは正社員の場合は出世するとか評価されるというのがモチベーションになる気がするけど自分はそういう欲がそもそも無さそう。

大きめの仕事はしたいけどそのためには評価されて出世する必要があるがその欲がない場合は別の方法を模索する必要がありそう。

  • ★★★★★ 自分のペースで仕事ができる

今の所コアタイムや稼働時間を設定していない仕事の割合が多いのが理由かもしれないけど好きなタイミングで働けるのでかなり助かっている。 (正社員で働くのが辛いので)無給でいいから週5労働したくない自分的には気が楽。

  • ★★★☆☆ キャリアに迷わない

実はAndroidの仕事に飽きている、 なのでモバイルアプリケーション開発の悪いところばかり注目しがちになってくるし、 正社員をしているとサーバーサイドでキャリアを積もうかなとか別の領域に手を出したいという欲求が出てくる、

いいか悪いかは微妙なところだけどフリーランスをしていると、 単価をめっちゃ上げられるかはわからないけど供給は少ないからしばらく食い扶持には困らなさそうという方向に考えがいくので、 Android一本でいくことに若干迷いがなくなる気がする。

cons

  • ★★★★☆ 仕事を獲得する努力が必要

要するに営業。

今の所知り合い伝で仕事をもらえているけど、もっと安定して売り上げを増やすと考えるとこういうことも必要になってくる。

安定と売り上げを捨てれば必要性はなくなるけど、今の所自分がどのくらい売り上げや安定に固執しているか不明なのでなんとも言い難い。

まだ体を壊してないからわからないけど、休職しても傷病手当とかは当然もらえないので辛そう。

  • ★☆☆☆☆ 契約や請求書周りが面倒

正社員のときから個人事業主をやっていたのでそこまで気にならないけど一般的にはそう。

まとめ

2023年2月現在、 こうやって書いてみるとラベルとか条件面よりは 市場価値を高めることや自分のペースで働くことの重要度が高いのかなという感じ。

OpenVPN on Raspberry Pi開通

2022年最後の投稿

1つ前の投稿の続き

OpenVPNが繋がらないとき/繋がったがインターネットに繋がらないときの確認事項 - sky’s 雑記


元々ubuntu desktop上で動かしていたんだけど、
マシンの移行が大変だったりしたのでdocker化してraspberry piで動かすようにしました。


主にubuntuで動かしていたことが理由でイメージのサイズが大きいです、
後日distrolessかalpineでイメージを作り直すかもしれません、
興味ある人は使ってみてください。
github.com

 

OpenVPNが繋がらないとき/繋がったがインターネットに繋がらないときの確認事項

自宅にVPNサーバーをOpenVPNで構築したのですが、 引っ越しやマシンの変更があると詰まりそうなので念の為まとめます。

環境

ubuntu 18.04
OpenVPN 2.4.4 x86_64-pc-linux-gnu
library versions: Open SSL 1.1.1

自宅のグローバルIP

ドメインでなくIPアドレス指定で繋いでいる場合IPアドレスが変わることがあるので確認

変わっている場合はクライアント側のovpnのremoteの設定を更新する

remote xxx.yyy.zzz.www pppp

ポートフォワード

VPNサーバーが稼働するマシンのIPとポートが指定されていることを確認する

証明書

TBD

IPマスカレード

IPマスカレードの設定ができていないとVPNには繋がるがインターネットに繋がらない状態になる

$ iptables -t nat -A POSTROUTING -o eth0 -s 10.8.0.0/24 -j MASQUERADE
$ iptables -L -n -t nat

マスカレードの設定ができていることが確認できたら以下をあわせて確認

ネットワークインターフェース

eth0のところに適切なネットワークインターフェースを指定しているか

$ ip -s link show
$ ip route get 142.250.207.36

sysctl.conf

ipv4,ipv6フォワーディングが有効になっているか

net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1

念の為再読み込み

$ sysctl -p

Amazon ECS Exec CLIのワンライナー実行

ECS ExecのときにServiceとTaskのARNが必要なんだけど、 もっと良い方法あるかな

$1にはClusterの名前が入ります。

aws ecs execute-command --cluster $1  \
  --task $(aws ecs list-tasks --cluster=$1 --service-name $(aws ecs list-services --cluster=$1 | jq -r '(.serviceArns[] | select(contains("foo")) | split("\/")) | .[2]') | jq -r '(.taskArns[])') \
  --container web \
  --interactive \
  --command "/bin/sh"

EXISTS と INNER JOIN のパフォーマンスについて

EXISTSをINNER JOINに置き換えるとパフォーマンスが上がるという主張をよく見かけますが、 ちょっと怪しい記事が多かったので調べました。

環境

他のDBでは確認していないのでMySQLに限定した話題です。

usersテーブルは複数のroom_usersを持ちます、レコード数は100万程度で試しています。

sh-4.4# mysql --version
mysql  Ver 8.0.30 for Linux on aarch64 (MySQL Community Server - GPL)
erDiagram

users {
  id integer PK
}

room_users {
  id integer PK
  user_id integer FK
}

users ||--o{ room_users : has_many

事前調査

調べていくと冒頭の主張とは異なるものの確度が高そうな情報を見つけた。

DBサーバーの種類に言及はなかったがStack Overflow[1][2]とQuora[3]の質問の回答をまとめると

  • uniqueなカラムについてINNER JOINする場合はEXISTSとパフォーマンスは変わらない
  • DISTINCTが適用されるレコードに対してINNER JOINする場合はEXISTSのほうがパフォーマンスが良い

INNER JOINとEXISTSはパフォーマンスは変わらず、重複削除の必要があるDISTINCT + INNER JOINになるとパフォーマンスが悪くなるとのこと。

実行計画

EXISTS, INNER JOIN, DISTINCT + INNER JOINそれぞれについて実行計画を出力して比較する。

EXISTS

select `users`.* from `users` where `users`.`id` != 1 and exists (select * from `room_users` where `users`.`id` = `room_users`.`user_id` and `room_users`.`room_id` in (10,11,12,13,14)) order by `users`.`updated_at` desc limit 30;

INNER JOIN

select `users`.* from `users` inner join `room_users` on `room_users`.`user_id` = `users`.`id` and `room_users`.`room_id` in (10,11,12,13,14) where `users`.`id` != 1 order by `users`.`updated_at` desc limit 30;

DISTINCT + INNER JOIN

select distinct `users`.* from `users` inner join `room_users` on `room_users`.`user_id` = `users`.`id` and `room_users`.`room_id` in (10,11,12,13,14) where `users`.`id` != 1 order by `users`.`updated_at` desc limit 30;

Optimizer Trace

 SELECT * FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE\G

出力された join_preparation で最終的に展開されるクエリは以下のようになる、semi joinは重複を取り除いた結果を結合するというもので、結合後に重複を取り除くDISTINCT + INNER JOINよりも効率が良いとのこと[4]

長くなるので省略するが considered_execution_plans に表示されるEXISTSとINNER JOINの実行計画は同じものだった、EXISTSとINNER JOINのパフォーマンスの差は重複を取り除くタイミングによることになる。

EXISTS

 select `users`.`id` AS `id`... from `users` semi join (`room_users`) where ((`users`.`id` <> 1) and (`room_users`.`room_id` in (10,11,12,13,14)) and (`users`.`id` = `room_users`.`user_id`)) order by `users`.`updated_at` desc limit 30

INNER JOIN

select `users`.`id` AS `id`... from `users` join `room_users` where ((`users`.`id` <> 1) and (`room_users`.`user_id` = `users`.`id`) and (`room_users`.`room_id` in (10,11,12,13,14))) order by `users`.`updated_at` desc limit 30

DISTINCT + INNER JOIN

select distinct `users`.`id` AS `id`... from `users` join `room_users` where ((`users`.`id` <> 1) and (`room_users`.`user_id` = `users`.`id`) and (`room_users`.`room_id` in (10,11,12,13,14))) order by `users`.`updated_at` desc limit 30

オプティマイザトレースの読み方は[5]-[7]に詳しい。

まとめ

MySQL8.0.30では

  • レコードの重複の削除が必要ない場合EXISTSとINNER JOINのパフォーマンスは変わらない
  • レコードの重複の削除が必要な場合EXISTSに比べINNER JOINのパフォーマンスは悪い

参考

[1] sql - Can an INNER JOIN offer better performance than EXISTS - Stack Overflow

[2] IN vs. JOIN vs. EXISTS at EXPLAIN EXTENDED

[3] Does select distinct slow down a query? - Quora

[4] MySQL :: MySQL 5.7 Reference Manual :: 8.2.2.1 Optimizing Subqueries, Derived Tables, and View References with Semijoin Transformations

[5] The MySQL Query Optimizer Explained Through Optimizer Trace | Percona Live - Open Source Database Conference 2019

[6] 非公式MySQL 8.0オプティマイザガイド by yakst

[7] 漢(オトコ)のコンピュータ道: オプティマイザトレースによるちょっとディープな快適チューニング生活

MySQLコンテナのready for connectionsを保証する

マイグレーションなどアプリケーションからMySQLを操作する場合にMySQLの起動を保証する方法についてです。

概要

docker exec db mysql -u${DB_USER} -p${DB_PASSWORD}MySQLのready for connectionsを保証できます。

      - name: wait for connections ready
        env:
          DB_USER: ${{ secrets.DB_USER }}
          DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
        run: |
          while ! docker exec db mysql -u${DB_USER} -p${DB_PASSWORD}; do
            sleep 1s
          done
        shell: bash

背景

MySQLとアプリケーションを別々のコンテナで管理しておりMySQL起動後にアプリケーションからDBを操作するケースで、 以下のようにMySQL起動後にアプリケーションからDBを操作しようとすると SQLSTATE[HY000] [2002] Connection refused となり失敗する。

      - name: launch mysql
        run: docker run -d -p 3306:3306 --name=db mysql/mysql-server:8.0

      - name: setup db
        run: docker run db php artisan migrate

これはMysqlを起動して即時ready for connectionsにならないことが原因なので、上記の処理を行うためにはsetup dbの前段でMySQLがready for connectionsになっていることを保証する必要がある。

docker-composeを利用するのが一番手っ取り早そうだったが、Github-hostedなubuntuにdocker-composeコマンドが存在せずdockerコマンドのみインストールされていたのでdockerコマンドで実現することを考える。

方法

うまくいく方法

1. mysql -u${DB_USER} -p${DB_PASSWORD}

冒頭で記載した方法。 接続に成功する場合docker execの終了コードが0になるのでこの方法で判定できる。

うまくいかない方法

1. docker inspect -f {{.State.Running}} db

コンテナのステータスがRunningであればsetup dbを実行する方法。 コンテナの起動とMySQLのready for connectionsは関係がないのでうまくいかない。 コンテナのステータスがRunningになるほうが早くConnection refusedになる。

2. mysqladmin ping

mysqladminのpingコマンドを利用するネットで検索するとよく見つかる方法、healthcheckでこのコマンドを実行しているdocker-composeもあるが今回のユースケースではうまくいかない。 公式[1]に記載があるとおりAccess Deniedでも0が返却されるので実行結果のstatusを見るだけでは100%ready for connectionsを保証することはできない。

Check whether the server is available. The return status from mysqladmin is 0 if the server is running, 1 if it is not. This is 0 even in case of an error such as Access denied, because this means that the server is running but refused the connection, which is different from the server not running.

未確認な方法

1. 実行ログを確認する

Qiitaで投稿されていた方法[2]で未確認だが雰囲気うまくいきそう。

参照

[1] MySQL :: MySQL 8.0 Reference Manual :: 4.5.2 mysqladmin — A MySQL Server Administration Program

[2] docker-compose を CI で実行するとき, MySQL の起動完了まで確実に待つ - Qiita