トラブルシューティング
Blog Service 開発・運用時によくある問題と解決策をまとめています。
データベース関連
問題: MySQL接続エラー
症状
Error 1045 (28000): Access denied for user 'root'@'localhost'
原因と解決策
原因1: パスワードが間違っている
bash
# 正しいパスワードを確認
cat docker-compose.yaml | grep MYSQL_ROOT_PASSWORD
# 接続テスト
mysql -u root -p -h localhost -P 3306
原因2: MySQLコンテナが起動していない
bash
# コンテナ状態確認
docker compose ps
# コンテナ再起動
docker compose restart mysql
原因3: ポートが衝突している
bash
# ポート使用状況確認
lsof -i :3306
# 衝突している場合は該当プロセスを停止
# または docker-compose.yaml でポート変更
問題: マイグレーション失敗
症状
atlas migrate apply: executing statement: table 'articles' already exists
解決策
手動でマイグレーション状態をリセット
bash
# 現在の状態確認
make atlas-status-dev
# マイグレーション履歴テーブルを確認
mysql -u root -p -h localhost -D dev -e "SELECT * FROM atlas_schema_revisions;"
# 問題のあるマイグレーションをスキップ
atlas migrate set --dir "file://migrate/migrations" --url "mysql://root:password@localhost:3306/dev" <version>
データベースを初期化してやり直し
bash
# データベースをドロップして再作成
docker compose down -v
docker compose up -d
make atlas-apply-dev
問題: マイグレーション競合
症状
複数の開発者が同時にマイグレーションを作成し、競合が発生
解決策
bash
# 最新のmainブランチから更新
git checkout main
git pull origin main
# 新しいマイグレーション作成
git checkout feature-branch
git rebase main
make atlas-diff name=fix_migration_conflict
# 競合したマイグレーションファイルを手動修正
開発環境
問題: Goモジュールエラー
症状
go: module github.com/example/package@v1.0.0: reading module: module not found
解決策
bash
# モジュールキャッシュをクリア
go clean -modcache
# 依存関係を再取得
go mod tidy
go mod download
# Goのプロキシを無効化(企業環境の場合)
export GOPROXY=direct
export GOSUMDB=off
問題: Wire生成エラー
症状
wire: /path/to/file.go:10:1: inject undefined
解決策
bash
# Wireタグの確認
//go:build wireinject
// +build wireinject
# Wireの再インストール
go install github.com/google/wire/cmd/wire@latest
# 生成ファイルを削除して再生成
rm di/wire_gen.go
make wire-gen
問題: ent生成エラー
症状
entc: schema description failed: template: <...>: undefined function
解決策
bash
# entのバージョン確認
go list -m entgo.io/ent
# スキーマファイルの構文確認
make ent-describe
# 生成ファイルを削除して再生成
rm -rf internal/infrastructure/ent/generated
make ent-generate
API関連
問題: 認証エラー
症状
json
{
"apiVersion": "1.0.0",
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid token"
}
}
解決策
JWTトークンの確認
bash
# トークンの形式確認(3つの部分に分かれているか)
echo "eyJ0eXAiOiJKV1..." | cut -d'.' -f1,2,3
# トークンの有効期限確認
# https://jwt.io/ でデコード
認証サービスとの接続確認
bash
# 認証サービスのヘルスチェック
curl -X GET https://auth-service/health
# ネットワーク接続確認
ping auth-service-host
問題: バリデーションエラー
症状
json
{
"apiVersion": "1.0.0",
"error": {
"code": "VALIDATION_ERROR",
"message": "title is required"
}
}
解決策
リクエストボディの確認
bash
# 正しいJSONフォーマットか確認
echo '{"title":"test","content":"test"}' | jq .
# 必須フィールドが含まれているか確認
curl -X POST http://localhost:8080/blog-service/v1/articles \
-H "Content-Type: application/json" \
-d '{"title":"記事タイトル","content":"記事本文","tagIds":[],"category":"tech"}'
問題: タイムアウトエラー
症状
context deadline exceeded
解決策
データベースクエリの最適化
bash
# 遅いクエリログを確認
mysql -u root -p -e "SHOW VARIABLES LIKE 'slow_query_log';"
# インデックスの確認
mysql -u root -p -D dev -e "SHOW INDEX FROM articles;"
接続プールの調整
go
// 設定例
db.SetMaxOpenConns(25)
db.SetMaxIdleConns(25)
db.SetConnMaxLifetime(5 * time.Minute)
テスト関連
問題: テスト失敗
症状
FAIL: TestCreateArticle: expected status 201, got 500
解決策
詳細なログ出力
bash
# テストを詳細モードで実行
go test -v ./internal/usecase/article/
# 特定のテストのみ実行
go test -v -run TestCreateArticle ./internal/usecase/article/
テストデータベースの確認
bash
# テスト用DB接続確認
TEST_DB_URL="mysql://root:password@localhost:3307/test" \
mysql -u root -p -h localhost -P 3307 -e "SELECT 1;"
モックの問題
bash
# モックを再生成
make mock-gen
# モックの設定確認
grep -r "EXPECT" internal/domain/*/repository/mock/
問題: カバレッジが低い
解決策
bash
# 詳細なカバレッジレポート
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out
# パッケージ別カバレッジ
go test -cover ./internal/usecase/...
go test -cover ./internal/domain/...
パフォーマンス問題
問題: メモリリーク
症状
runtime: out of memory: cannot allocate xxx bytes
解決策
メモリプロファイリング
bash
# pprof でメモリ使用量確認
go tool pprof http://localhost:8080/debug/pprof/heap
# トップメモリ消費箇所の確認
(pprof) top10
(pprof) list function_name
ゴルーチンリーク確認
bash
# ゴルーチン数確認
go tool pprof http://localhost:8080/debug/pprof/goroutine
問題: 応答時間が遅い
解決策
CPUプロファイリング
bash
# CPU使用量プロファイル
go tool pprof http://localhost:8080/debug/pprof/profile?seconds=30
データベースクエリ最適化
sql
-- 遅いクエリの特定
SHOW PROCESSLIST;
-- クエリ実行計画の確認
EXPLAIN SELECT * FROM articles WHERE category = 'tech';
-- インデックス追加
CREATE INDEX idx_articles_category ON articles(category);
ログ・監視
問題: ログが出力されない
解決策
bash
# ログレベル確認
export LOG_LEVEL=debug
# ログファイルの権限確認
ls -la /var/log/blog-service/
# 標準出力にログ出力
export LOG_OUTPUT=stdout
問題: 構造化ログの問題
解決策
go
// 正しい構造化ログの例
logger.Info("article created",
zap.String("articleId", article.ID),
zap.String("userId", userID),
zap.Duration("duration", time.Since(start)),
)
本番環境
問題: サービス起動失敗
症状
panic: dial tcp: connection refused
解決策
環境変数の確認
bash
# 環境変数が正しく設定されているか
env | grep -E "(DB_|JWT_|LOG_)"
# 設定ファイルの存在確認
ls -la /etc/blog-service/config.yaml
ネットワーク接続確認
bash
# データベースサーバーへの接続確認
telnet db-server 3306
# DNS解決確認
nslookup db-server
問題: 高負荷時のエラー
解決策
接続数制限の調整
yaml
# nginx設定例
upstream blog-service {
server blog-service-1:8080 max_fails=3 fail_timeout=30s;
server blog-service-2:8080 max_fails=3 fail_timeout=30s;
keepalive 32;
}
データベース接続プール調整
go
// アプリケーション設定
config := mysql.Config{
MaxOpenConns: 100,
MaxIdleConns: 10,
ConnMaxLifetime: time.Hour,
ConnMaxIdleTime: time.Minute * 10,
}
よくある質問
Q: 新しい機能を追加する手順は?
- 新しいマイグレーション作成
- ent スキーマ更新
- ドメインエンティティ作成
- UseCase 実装
- HTTP ハンドラー追加
- OpenAPI 定義更新
- テスト作成
Q: 本番データベースのバックアップは?
bash
# mysqldump による定期バックアップ
mysqldump -u $DB_USER -p$DB_PASSWORD \
--single-transaction \
--routines \
--triggers \
$DB_NAME > backup_$(date +%Y%m%d_%H%M%S).sql
Q: ログの保持期間は?
- アプリケーションログ: 30日
- アクセスログ: 90日
- エラーログ: 1年
詳細な設定は運用チームに確認してください。
更なるサポート
問題が解決しない場合は以下にお問い合わせください:
- 開発チーム: #blog-service-dev
- 運用チーム: #blog-service-ops
- 緊急時: oncall@company.com