作为一个后端架构师,我们每天面对的是海量的代码、复杂的系统架构和永无止境的 Bug。偶尔,我们也需要停下脚步,记录生活中的美好瞬间,或者是一些技术上的灵感。但是,如果只是简单地使用文本文件或者云笔记,时间一长,就会发现难以管理和查找。因此,我将自己的生活小记做了一个简单的技术升级,使其更易于管理和检索。
需求分析与技术选型
首先,我们需要明确需求:
- 易于记录:可以快速记录文字、图片、链接等内容。
- 方便管理:能够按日期、标签等方式进行分类管理。
- 支持搜索:可以快速搜索到想要的内容。
- 数据安全:保证数据的安全性,防止丢失。
基于以上需求,我选择了以下技术方案:
- 存储:使用 MySQL 数据库存储数据。当然,你也可以选择 PostgreSQL 或者 SQLite,甚至 NoSQL 数据库,如 MongoDB。这里选择 MySQL 是因为我比较熟悉,而且对于小规模的数据来说,性能足够。
- 后端框架:使用 Python 的 Flask 框架。Flask 轻量级,易于上手,适合快速开发。
- 前端框架:使用 Vue.js。Vue.js 简单易用,可以快速构建用户界面。
- 服务器:使用 Nginx 作为反向代理服务器,并将 Gunicorn 作为 WSGI 服务器。
- 部署:使用 Docker 进行容器化部署。
数据库设计
我们设计一个简单的 notes 表:
CREATE TABLE notes (
id INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(255) NOT NULL,
content TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
tags VARCHAR(255) DEFAULT NULL -- 使用逗号分隔多个 tag
);
后端代码实现 (Flask)
from flask import Flask, request, jsonify
import mysql.connector
import os
app = Flask(__name__)
# 数据库配置,从环境变量读取
mysql_host = os.environ.get('MYSQL_HOST', 'localhost') # 默认值 localhost
mysql_user = os.environ.get('MYSQL_USER', 'root') # 默认值 root
mysql_password = os.environ.get('MYSQL_PASSWORD', 'password') # 默认值 password
mysql_db = os.environ.get('MYSQL_DB', 'mydb') # 默认值 mydb
mydb = mysql.connector.connect(
host=mysql_host,
user=mysql_user,
password=mysql_password,
database=mysql_db
)
@app.route('/notes', methods=['GET', 'POST'])
def notes():
if request.method == 'GET':
mycursor = mydb.cursor()
mycursor.execute("SELECT * FROM notes")
myresult = mycursor.fetchall()
notes = []
for row in myresult:
notes.append({
'id': row[0],
'title': row[1],
'content': row[2],
'created_at': row[3].isoformat(),
'tags': row[4]
})
return jsonify(notes)
elif request.method == 'POST':
data = request.get_json()
title = data['title']
content = data['content']
tags = data.get('tags', None) # tags 可选
mycursor = mydb.cursor()
sql = "INSERT INTO notes (title, content, tags) VALUES (%s, %s, %s)"
val = (title, content, tags)
mycursor.execute(sql, val)
mydb.commit()
return jsonify({'message': 'Note created successfully', 'id': mycursor.lastrowid}), 201
@app.route('/notes/<int:note_id>', methods=['GET', 'PUT', 'DELETE'])
def note(note_id):
if request.method == 'GET':
mycursor = mydb.cursor()
sql = "SELECT * FROM notes WHERE id = %s"
val = (note_id,)
mycursor.execute(sql, val)
myresult = mycursor.fetchone()
if myresult:
note = {
'id': myresult[0],
'title': myresult[1],
'content': myresult[2],
'created_at': myresult[3].isoformat(),
'tags': myresult[4]
}
return jsonify(note)
else:
return jsonify({'message': 'Note not found'}), 404
elif request.method == 'PUT':
data = request.get_json()
title = data['title']
content = data['content']
tags = data.get('tags', None)
mycursor = mydb.cursor()
sql = "UPDATE notes SET title = %s, content = %s, tags = %s WHERE id = %s"
val = (title, content, tags, note_id)
mycursor.execute(sql, val)
mydb.commit()
if mycursor.rowcount > 0:
return jsonify({'message': 'Note updated successfully'})
else:
return jsonify({'message': 'Note not found'}), 404
elif request.method == 'DELETE':
mycursor = mydb.cursor()
sql = "DELETE FROM notes WHERE id = %s"
val = (note_id,)
mycursor.execute(sql, val)
mydb.commit()
if mycursor.rowcount > 0:
return jsonify({'message': 'Note deleted successfully'})
else:
return jsonify({'message': 'Note not found'}), 404
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0') # 监听所有地址,方便 Docker 容器访问
前端代码实现 (Vue.js)
这里省略 Vue.js 的具体代码,主要实现以下功能:
- 显示所有笔记列表
- 创建新笔记
- 编辑笔记
- 删除笔记
可以使用 axios 或者 fetch API 与后端进行数据交互。
Nginx 配置
server {
listen 80;
server_name your_domain.com; # 替换成你的域名
location / {
proxy_pass http://127.0.0.1:5000; # Flask 应用的地址和端口
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# 静态资源 (例如 Vue.js 构建后的 dist 目录)
location /static/ {
root /path/to/your/vue/dist; # 替换成你的 Vue.js dist 目录
expires 30d; # 缓存静态资源 30 天
}
}
Dockerfile
FROM python:3.9-slim-buster
WORKDIR /app
COPY requirements.txt . # 先复制 requirements.txt,利用 Docker 缓存
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
ENV FLASK_APP=app.py # 指定 Flask 应用的入口文件
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "--workers", "3", "app:app"] # 使用 Gunicorn 启动 Flask 应用
实战避坑经验
- 数据库连接问题:确保 MySQL 服务已经启动,并且 Flask 应用能够正确连接到数据库。可以使用
try...except块捕获连接错误。 - Nginx 反向代理配置:需要正确配置
proxy_pass、proxy_set_header等参数,否则可能出现 400 Bad Request、502 Bad Gateway 等错误。特别是Host头,必须正确设置,否则 Flask 应用可能无法正确处理请求。 - Docker 镜像构建:先复制
requirements.txt,再复制其他文件,可以利用 Docker 缓存,加快构建速度。构建镜像时,尽量使用官方的基础镜像,例如python:3.9-slim-buster,减小镜像体积。 - Gunicorn 并发连接数:需要根据服务器的 CPU 核心数和内存大小,合理配置 Gunicorn 的 worker 数量。一般来说,worker 数量设置为 CPU 核心数的 2-4 倍即可。
- **代码版本控制:**生活小记也是代码,所以使用 Git 进行版本控制至关重要,可以方便地回滚和协作。
- **定期备份:**重要的数据需要定期备份,防止数据丢失。可以使用
mysqldump命令备份 MySQL 数据库。
通过以上技术方案,我们可以构建一个易于管理、方便搜索、数据安全的「生活小记」系统。当然,这只是一个简单的示例,你可以根据自己的需求进行扩展和优化。例如,可以增加用户认证功能,实现多人协作;可以集成全文搜索引擎,提高搜索效率;可以支持 Markdown 格式,方便编写技术文章。
希望这些对你的「生活小记」有所启发。
关于生活小记的持续迭代
技术是不断发展的,我们的「生活小记」也应该不断迭代。可以考虑引入新的技术,例如 GraphQL、WebSocket 等,提高系统的性能和用户体验。同时,也应该关注安全问题,例如 SQL 注入、XSS 攻击等,及时修复漏洞,保证数据的安全。在后续的开发中,可以考虑使用宝塔面板进行服务器的管理,降低运维成本。希望我的经验能帮助你更好地打造属于你的技术小窝。
冠军资讯
代码一只喵