[5日目] 学校の食堂をIT化させる話　混雑度カメラのサーバー構成を考える（技術的に）

こんにちは、なりかくんと申します。
この記事はなりかくん Advent Calender 2023の5日目の記事です。

この話は、1日目から始めた学校の食堂をIT化させる話の続きとなります。前回は、混雑度カメラのサーバー構成を考える案をメモ程度に書きました。（時間が無くなって5日目に続きを書いてます。）

今回は、技術的に考えていこうと思います。

# 最初に思いついた構成案
今回、とにかくお金が無いんです！！なので、年6,000円程度で使えるレンタルサーバーを私は契約していたのでそれにドメインを追加して使ってやろうと考えました。
また、レンタルサーバーではデータベース（MySQL）が標準搭載されていたのでビックデータ化も非常に楽でいいなと思ったのもあります。

サーバー側の言語はPHPで、書きました。以下が実際に作ったプログラムの画像のアップロードとデータベース挿入のコードです。
なんと簡単なコードなのでしょうか(*´ω｀)
```php
$filename = $_FILES['image']['name'];
$uploaded_path = '../images/camera1.png';    
$result = move_uploaded_file($_FILES['image']['tmp_name'], $uploaded_path);
$count = $_POST["count"];
if ($result) {
    $stmt = $pdo->prepare('INSERT INTO camera1 (count) VALUES(:count)');
    $stmt->bindValue(':count', $count);
    $stmt->execute();
} else {
    # エラー処理
}
```

また、データベースの構成も非常に簡単で日時と人数データのみです。
| 名前 | タイプ | デフォルト値 |
|:-:|:-:|:-:|
| datetime  | datetime  | current_timestamp()  |
|  count |  int(11) |   |

データベースに蓄えたデータは増えていくと重くなっていくので定期的にcronで削除するようにしています。
このコードでは、1週間より前のデータを削除するコマンドです。
```shell
mysql --user=ユーザ名 --password=パスワード --database=データベース名 --execute="DELETE FROM camera1 WHERE (datetime < DATE_SUB(CURDATE(), INTERVAL 7 DAY))"
```

実際にこれで動かしてみると普通にいい感じに動きます。（データ取得部分には、4日目で話したCDNが入ってるので大量アクセスも多分大丈夫なはず。）

ですが、皆さん思うはずです。「レンタルサーバーは、共有サーバーなので負荷がかかるじゃないか！！」と。
そうです。かかります。ごめんなさい。

ということで、出来るだけ迷惑がかからないように考えます。

# VPS上で動かそう！！
よし、じゃあVPSで動かそうじゃないか。安いVPSを探すぞ～！という考えに至ります。
そして、VPSを探していくわけですね。安いVPSは見つかるのですが、すべて転送量の制限があるのです。

混雑度カメラは、画像を数秒ごとに受け取って数秒ごとに送信します。転送量やばくねぇか！？

ってことで、探していると私が大好きなConoHa VPSに至るわけです。最近ConoHaがリニューアルしてキャンペーンでVPSが安くなってました。

だがしかし、お金が無いので512MBで耐えてもらおう。ということで、512MBの12カ月を契約します。これで、3,852円なんです。レンタルサーバーより安いって何ですか。（メモリがクソ少ないのはサーバーに耐えてもらいます。）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549951/6aa026db-05b3-8201-2b52-16dd3b86e840.png)

転送量は、大丈夫なの？って思う方もいるかと思いますが、ConoHaは転送量がすべて無制限です。
また、異常な使い方（スピードテストサーバー建てたりとか。）をしない限りは過大な負荷やネットワークの負荷は許容範囲内だと思うので、気にせず使っていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549951/d6b59d07-6807-a57d-1c6e-94e4f592ba0b.png)
引用元：https://support.conoha.jp/common/faq/payment-q/billing-q/

というわけで、ConoHa VPSを使うということになりました。

# Node.jsで書く
今回、プログラムはNode.jsで書いていきます。とりあえずデータベース関係はすべて無視して（メモリの関係上）コードを作りました。
Webサーバーには、Expressを使って画像アップロードには、multerを使いました。

まあ、認証などのコードもあるのですがその辺のコードはすべて排除してアップロード部分のコードがこちらです。
```js
app.use(express.static(__dirname + '/uploads'));

const storage = multer.diskStorage({
    destination: (req, file, cb) => {
        const userId = req.userId;
        const uploadPath = `uploads/${userId}`;
        fs.mkdirSync(uploadPath, { recursive: true });
        cb(null, uploadPath);
    },
    filename: (req, file, cb) => {
        cb(null, `image.png`);
    },
});

const upload = multer({ storage: storage });

const uploadMiddleware = upload.single('image');

app.post('/upload', apiKeyMiddleware, uploadMiddleware, (req, res) => {
    const userId = req.userId;
    const timestamp = new Date().getTime();
    let body = req.body;
    body["timestamp"] = timestamp;

    const jsonPath = `uploads/${userId}/data.json`;
    fs.writeFileSync(jsonPath, JSON.stringify(body));

    res.json({ message: 'File uploaded successfully.', body });
});
```

画像ファイルとデータはExpressの静的ファイルのやつを使いました。
これで、`/upload`にPOSTした画像ファイルとbodyのデータが`image.png`と`data.json`に保存されます。

これにてプログラムの完成です。

# 最後に
まだまだ技術面ではセキュリティなどを話すことはありますが、いったん5日目はここまでで！
最後までお読みいただきありがとうございました。