海辺にて

備忘録

No.22

2/25にサーバーをイメージから書き換えた後に、ものすごくサーバー負荷が上がりTLが読み込めない・アクセスできないなどのエラーが発生していた。
その原因と修正方法についてメモ。

[症状]
https://minazukey.uk/notes/9q74lznca9m24...
>②①と直接の関連があるか不明だがその上でフォロー関係の有無に関わらず更に一部pleroma/akkoma系サーバーから大量のリクエストが飛んできてお互いの鯖の負荷が地獄になる
症状は夜坂さんのこの投稿にまとまっている。皆尽村が一時HTTP通信状態になったときの投稿が自サーバーにいくつか配送されており、そのときにデータベースに新しくリモートユーザーが作成された。こちらのデーターベース上は1つのアカウントに対して
①ID.アカウント名@ドメイン(HTTP通信以前に作成されていたユーザー) ②アカウント名@ドメイン(HTTP通信時に作成されたユーザー)」のデータが存在する状態になった。①のデータは2/18までの投稿が確認できたが、②のデータはHTTP通信時と思われる2/12分しかなかったことから「①ID.アカウント名@ドメイン」が正しいアカウントだと思う。

[原因]
症状発生時のPostgresqlのエラーは以下。
ERROR:  duplicate key value violates unique constraint "users_nickname_index"
DETAIL:  Key (nickname)=(***@domain.com) already exists.
ERROR:  current transaction is aborted, commands ignored until end of transaction block

ChatGPT先生に聞いたところ、ユーザーのニックネーム(***@domain.com)が重複しているためトランザクション内でエラーが発生し、ロールバックを行ったとのこと。このエラーが1秒間にエグイ数発生しており、相手先(皆尽村)にDDoS攻撃をしているようなものである…本当に申し訳ない。この重複したニックネームのアカウントがデータベース上に2つのユーザーデータがあったアカウントだったので、原因が「分裂したアカウントと自サーバーが何らかの通信を行うとき」ということが分かった。一時的な処置としてこのエラーを止めるにはAkkomaを止めて接続を遮断するしかなさそう。

重複ユーザーはAdmin-FEから目視で探した(もっといい方法があるかもしれないが…)。「①ID.アカウント名@ドメイン」というNameがあれば重複ユーザーだ。私のサーバーでは3人いた。
20240228132130-mizuiro.png
内部のデータベースを見たら以下のような構造になっていた。
20240228135723-mizuiro.png
①ID.アカウント名@ドメイン:名前の更新(updated_at)はされないがステータスの更新(last_status_at)はされる
②アカウント名@ドメイン:名前の更新(updated_at)はされるがステータスの更新(last_status_at)はされない
1つの投稿を取得するたびに2つのユーザーデータが更新されるのがエラーの原因のようだ。②のユーザーデータを消去しただけでは①のnicknameが書き換えられるものか分からないので、以下の手順で直接データを修正することを試みた。
(1)②のユーザーデータを消す
(2) ①のnicknameを元の「アカウント名@ドメイン」に書き換える

[修正]
3/2 追記
ユーザー削除だけだと不十分とのご指摘をいただきました。②アカウント名@ドメインに紐づいていたap_id(http://〜)のデータがactivitiesなどに残ってしまうため、そのあたりまで手を入れないと危なそうなようです。
https://pl.kpherox.dev/notice/AfR8ZLix9U...
https://pl.kpherox.dev/notice/AfR8gA1J48...

試してないのですが、こちらで書かれているnickname入れ替えの方がリスクが少なく、かつ手間もかからなくて良さそうです。
https://pl.kpherox.dev/notice/AfRA8InO8E...

!!データベースを操作するので必ずバックアップを取ってから行ってください!!
(1)Akkomaを止める
sudo service akkoma stop
(2)Postgresqlにログインし、正規ユーザーの内部IDを調べる
sudo -Hu postgres psql -d データベース名
select * from users where nickname='ID.アカウント名@ドメイン';
usersテーブル内のID.アカウント名@ドメインに紐づくデータを取得
idは「001,002...」のようなものではなくもっと複雑で長いです
※アカウント名@ドメインのidを調べるにはもっと良さげな条件式とかありそう
(3)userテーブルから重複ユーザー(アカウント名@ドメイン)を削除する
delete from users where nickname='アカウント名@ドメイン';
(4)正規ユーザーのnicknameを書き換える
update users set nickname='アカウント名@ドメイン' where id='(2)で取得したID';
usersテーブルのidが「(2)で取得したID」のデータのnicknameを「アカウント名@ドメイン」に更新します の意。(2)~(4)を重複したユーザー分行う。
(5)一応Postgresqlを再起動する
sudo systemctl restart postgresql.service
(6)Akkomaを起動する
sudo systemctl start akkoma.service
Admin-FEで該当ユーザーの②アカウント名@ドメインのデータが消えている、①ID.アカウント名@ドメインのNameがアカウント名@ドメインに変わっていればOK。この後、該当ユーザーの投稿の照会や投稿の配送がきちんとされ、自サーバーも皆尽村にもエラーが発生していないことを確認した。
このエラーに対していろいろとご対応していただいた夜坂さん、本当にありがとうございました!

ログを調べたら2/25のイメージ書き換え以前にもデータベースエラーによる大量アクセスが発生していたのだが、自サーバーでの動作には全く影響が出ていなかったので気づいていなかった。今回、いろいろなログの見方や調べ方が分かったのでこれからはこまめにチェックしようと思いました(初心者感)

参考:
データを更新する(UPDATE)
データを削除する(DELETE)
#akkoma