Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

ファイルサイズが50MB程のCSVファイルのアップロードを失敗してしまう(Nginx, Next.js)

Q&A

Closed

[構成]
・Ubuntu 22.04
・Nginx 1.18.0-6
・Node.js v18.18.2
・Next.js v9.8.1でのAPI処理
・MySQL v8.0.35-0へのデータ取り込み

【ご質問】
以下のようにエラーの確認と対処を行ったのですが、まだエラーが残っています。
これは何を対処すれば良いでしょうか?

【補足】
ご回答頂ける際に、ランサーズでランサーをされている方は是非お知らせください。

(参考)ChatGPT4による回答

エラー3に関しては、Nginxとアップストリーム(この場合は127.0.0.1:5000)の間で通信の問題が発生している可能性があります。
このエラーはTCPリセット中、TCP接続のタイムアウトやアップストリームサーバの処理速度などが原因で起きることがあります。

このエラーの原因と対処は以下の通りです:

  • アップストリームサーバーのパフォーマンス問題:
    アップストリームサーバー(この場合は、http://127.0.0.1:5000 )が遅すぎてレスポンスを処理できない場合、
    Nginxからアップストリームサーバーへの要求がタイムアウトする可能性があります。
    この場合、アップストリームサーバのパフォーマンスを改善する必要があります。

  • ネットワーク接続の問題:Nginxとアップストリームサーバーとの間のネットワーク接続に問題がある場合にも
    同様のエラーが発生します。接続を確認して、その問題点を特定し、修正します。

  • Nginx設定の変更とチューニング:Nginxの設定を変更し、タイムアウトなどのパラメータを調整することで、
    この問題を解決することができる場合があります。
    たとえば、次のような設定を試すことができます:

/etc/nginx/nginx.conf:

http {
    fastcgi_buffers 8 16k;
    fastcgi_buffer_size 32k;
    proxy_buffers 8 16k;
    proxy_buffer_size 32k;
}

それぞれの値は環境によって調整が必要かもしれません。
これらの設定値の詳細について理解するためには、Nginxの公式ドキュメンテーションを参照することをオススメします。

最後に、Nginxの設定を変更したら systemctl restart nginx または相当のコマンドで
Nginxを再起動して変更内容を適用します。

※まだChatGPT4の回答内容は実施していません。(2023.11.17 19:56追記)

確認したエラーログの場所

/var/log/nginx/error.log

エラー内容と対処(1)

  • エラー(1)
    [error] 796#796: *356 client intended to send too large body: 51230246 bytes, client: 
    [IPアドレス], server: , request: "POST /api/upload HTTP/1.1", host: "[IPアドレス]", 
    referrer: "http://[IPアドレス]/"
    

  • 対処(1)
    参考にした資料:(Qiita)【Nginx】エラー「client intended to send too large body:」の対処法
    編集したファイル:/etc/nginx/sites-enabled/default
    server {
    client_max_body_size 100M;
    }
    

エラー内容と対処(2)

  • エラー(2)
    [error] 3127#3127: *1 upstream timed out (110: Unknown error) while sending request     to upstream, client: [IPアドレス], server: , request: "POST /api/upload HTTP/1.1", 
    upstream: "http://127.0.0.1:5000/api/upload", host: "[IPアドレス]",  referrer: 
    "http://[IPアドレス]/"
    

  • 対処(2)
    参考にした資料:(IT分からんわ~_~;様)nginxのタイムアウト時間を伸ばす
    編集したファイル:/etc/nginx/sites-enabled/default
    server {
    proxy_read_timeout 600;
    proxy_connect_timeout 600;
    proxy_send_timeout 600;
    }
    

エラー内容(3)→ 未解決

  • エラー(3)
    [error] 795#795: *123 readv() failed (104: Unknown error) while reading upstream, 
    client: [IPアドレス], server: , request: "POST /api/upload HTTP/1.1", upstream: 
    "http://127.0.0.1:5000/api/upload", host: "[IPアドレス]", referrer: "http://[IPアドレ 
    ス]/
    
0

2Answer

Comments

解決できました、ありがとうございました。

本件、ランサーズにて、pokemogu様 ご協力により改修できまして、発生していたエラーが解決し、50MB程のCSVファイルのアップロードや、ファイル容量は小さいがなぜか無応答で終わってしまう件が解決しアップロードが成功するようになりました。


【ご提案時の見解】

(過去)案件でnginx + Node.jsによるファイルアップロードシステムを構築した際に、同様なエラーが発生したことがあります。

この時はご対応されたnginxによるアップロード許容サイズの設定変更に加えて、Node.js側でも同様の変更が必要になっております。

さらにMySQLデータベースにアップロードしたファイル内容をSQLで書き込む際にも、SQL文のデータ制約によるエラーが発生しております。

【確認方法】

npm run devにてデバッグモードで起動し、エラー発生時にコンソール表示されるログを確認いただいた。

デバッグモードの起動
Next.js実行ディレクトリで、
npm run dev と実行するのみ。
※ただし事前に、起動しているNode.jsは手動停止する必要があります。

sudo pkill node
sudo npm run dev

(確認されたNext.jsのデバッグログ)

[UPLOAD CSV] File updated successfully!
[CREATE INDEX] Index exists
Error: Error: ER_DATA_TOO_LONG: Data too long for column '[該当カラム名]' at row 8515
#以下略#

⇒こちら原因が分かりました。やはりMySQLのSQL文のデータサイズ制約に引っかかっています。
これからMySQLの設定修正を行ないます。

【修正箇所】

  • 修正ファイル(1)
    • ./src/common/helpers/query.ts

  • 修正内容
    • カラムサイズ不足を修正

(修正前)

export const columnsObject = {
〜略〜
[該当カラム名]: "VARCHAR(32)",
〜略〜
};


(修正後)

export const columnsObject = {
〜略〜
[該当カラム名]: "VARCHAR(256)",
〜略〜
};
  • 修正ファイル(2)
    • ./src/lib/parse-file.tsx

  • 修正内容
    • アップロードサイズ上限を修正

(修正前)

const form = formidable({
maxFiles: 10,
maxFileSize: 1024 * 1024 * 10, // 10mb
uploadDir,


(修正後)

const form = formidable({
maxFiles: 10,
maxFileSize: 1024 * 1024 * 60, // 60mb
uploadDir,

以上です。 ありがとうございました。

[補足] 仮想マシンのCPUコア数およびメモリのリソースも合わせる必要あり。
この検証サーバ環境から、本番の仮想マシンへ構築していましたら再びアップロードに失敗したのですが、本番の仮想マシンの(メモリは合わせていましたが)CPUコア数も合わせたらアップロードできました。

0Like

Your answer might help someone💌