于俊洋 — Java 后端 · 全栈开发 · 实时计算 · 线上运维
在自建服务器上并行运行 7 个站点,也在学怎么把它们跑得更稳。
大连职业技术学院 软件技术(大专),2024.09 – 2026.06,GPA 3.8 / 4.0,专业前 5%。所在地 辽宁 · 大连。GitHub grey7213。
线上服务
- 多租户 API 网关(villainy.top,部署运维):统一接入层 · 配额与限速。技术栈 Go、PostgreSQL 18、Redis 8、Docker Compose、Nginx。三容器编排,应用与数据层分离,各带健康检查;279 次数据库迁移零校验失败(升级前离线哈希比对);11 个路由分组,按组独立配额与限速。
- 全栈对话应用平台(patcher.villainy.top,自研):自研后端 + Web 端 + Android 客户端。技术栈 Python 标准库、SQLite、Alpine.js、Android、systemd。后端零第三方依赖,纯标准库 http.server 实现约 3450 行;30 张表的关系设计,含启动时自动迁移;同源 Web 端 + 独立签名的 Android 客户端。
- 独立上游中继(grok.villainy.top,部署运维):协议适配 · 独立数据库。技术栈 Docker、SQLite、Nginx。与主站零耦合,独立容器与独立数据库;出口链路经独立转发服务,不影响其他站点。
- 协议转换代理(cpa.villainy.top,部署运维):请求改写 · 配置热加载。技术栈 Docker、Nginx。仅绑定 127.0.0.1,经 Nginx 反代暴露;配置文件热加载,改配置不重启。
- 艺脉乡传(艺脉乡传.villainy.top,团队项目 · 工程实现与部署):多端智慧文旅平台 · Web + 小程序 + API。技术栈 React 19、Express、Sequelize、uni-app、esbuild。npm workspaces 5 个包,一套共享类型贯穿四端;45 个 API 端点,13 张表,13 例接口测试通过;后端 esbuild 打成单文件 1.5MB,systemd 托管仅绑 loopback。
- 辽境云游(liaojing.villainy.top,前端独立实现):文旅展示线 · 云展馆与导览。技术栈 React 19、TypeScript、Tailwind 4、Vite 6。11 条路由,11 个页面组件,3584 行;状态层单点收口,localStorage 版本化 key;接口调用 1.2s 超时自动降级为本地状态。
- 乡村非遗平台(feiyi.villainy.top,前端独立开发):零依赖前端原型 · 无构建步骤。技术栈 原生 ES Module、手写 Router、原生 CSS。零 npm 依赖,26 条路由,48 个页面模块;手写 80 行 Router,支持参数匹配与页面 cleanup;部署期 PNG→WebP:124MB → 11MB,带引用完整性门禁。
项目经历
全栈对话应用平台(自研)
2026.06 – 至今 · 全栈 · 独立负责 · 线上运维。纯标准库后端 + Web 端 + Android 客户端,线上运行中
一个自己从零写到上线的对话应用平台:后端不用任何 Web 框架,纯 Python 标准库 http.server 实现;前端是多页面 Web 应用;另有一个独立签名的 Android 客户端。目前在自建服务器上持续运行并迭代。
技术栈:Python 标准库、http.server、SQLite、Alpine.js、Android、Java、WebView、Nginx、systemd、Let's Encrypt、SMTP 中继
- 后端不引任何 Web 框架,用 ThreadingHTTPServer + BaseHTTPRequestHandler 手写路由与鉴权,因此完全清楚每个请求的生命周期,排查问题不需要翻框架源码
- 数据库演进用「单列 JSON + 启动时自动 ALTER」策略,避免每加一个字段就写一次迁移脚本
- Android 端的导航校验逻辑单独提取成可测函数(只接受同源且指定前缀的 URL),而不是留在 Activity 里——Activity 没法用纯 JUnit 测
- 用 Nginx access log 做黑盒断言验证客户端行为:点某个入口就该出现对应请求,9 个越权路径应产生 0 条请求
- 发布流程带包名 / versionCode / 证书指纹三重校验,防止误发调试包覆盖正式包
- 修过一个只在旧设备复现的 bug:某个 Web API 在旧版 WebView 上是 undefined,导致查询参数被静默丢弃。线上真机一直正常,只有低版本设备崩——用模拟器复现并验证
多租户 API 网关平台 — 生产化部署与运维
2026.06 – 至今 · 部署与运维(非原作者)。开源项目的生产环境落地、版本升级与灾备
应用本体为开源项目(Go 实现),我负责的是生产环境落地、版本升级、性能调优与灾备体系。
把一个开源的 API 网关项目落到自己的服务器上并长期运维:容器编排、反向代理、TLS、版本升级、数据库迁移校验、性能调优、备份与恢复。同一台机器上还并行跑着另外 7 个站点,所有变更都必须保证互不影响。
技术栈:Docker Compose、PostgreSQL、Redis、Nginx、Linux、systemd、Let's Encrypt、zstd、HTTP/2
- 跨版本升级前先离线校验迁移:下载目标版本源码,逐个哈希比对已执行的迁移记录,把「希望迁移能跑通」变成升级前就知道答案(279 次迁移零校验失败)
- 识别并拦下一次会静默改变计费口径的升级:某版本把一个开关的默认值改成开启,会导致长上下文请求按 2 倍输入价计费。升级前建快照表保存原值,逐组显式设回
- 开启 HTTP/2 把请求排队累计从 332s 降到 0.4s。因为它是监听套接字级参数、同机多站共用,改动前先把整个 /etc/nginx 拷到临时目录离线验证
- 发现并修掉两个既存配置 bug:Redis 的 command 块缺行继续符导致 AOF 持久化实际未生效;33 个调优环境变量在 compose 里没转发,容器一直在用内置默认值
- 备份走「服务端不停服快照 → 压缩算哈希 → 并发拉取 → 本地逐一比对 → 真解压验证」,全部通过才删服务端暂存。链路单流仅 0.85MB/s,所以压缩比是唯一杠杆
- 踩过一次生产事故:给资源加预加载导致 18 个模块全部初始化失败、加载恶化到 87.9s。根因是预加载不能跨重定向。4 分钟内回滚,之后定了「改线上前先在真实环境干跑」的规矩
艺脉乡传 — 乡村非遗智慧文旅平台
2026.06 – 2026.09 · 团队项目 · 我负责工程实现与部署。npm workspaces 多端单体:Web + 小程序 + 管理端 + API
团队参赛项目(智慧文旅创新创业竞赛 · 创新组)。策划与商业计划书为团队共同成果,我承担代码实现、构建流水线与服务器部署。
面向乡村非遗场景的多端智慧文旅平台,覆盖数字档案、课程学习、展陈导览、乡村资源、活动预约、社区互动与平台治理。npm workspaces 单体仓库,一套共享类型贯穿 Web / 小程序 / 管理端 / API 四端。
技术栈:React 19、TypeScript、Vite 6、Three.js、Express 4、Sequelize 6、MySQL、Zod、JWT、uni-app、Vue 3、Pinia、Vitest、Supertest、esbuild
- API 层用 Zod schema 放在 packages/shared,前后端共用同一份契约定义,接口改字段时四端一起报类型错,而不是等运行时才发现
- 后端用 esbuild 打成单个 1.5MB ESM 文件部署,sequelize / mysql2 全部 tree-shake 掉,服务器上不需要 npm install,回滚就是切一个软链
- 13 个 vitest + supertest 用例覆盖接口契约,用 seed 数据与 sandbox provider,不依赖真实 MySQL 就能在 CI 里跑
- 发布走「时间戳目录 + current 软链 + 保留 5 个版本」,回滚是一次 ln -sfn
- 做过一次首屏图片去重的浏览器实测:逐页断言图片路径唯一性(首页 18/18、课程 14/14、路线 8/8、匠人 6/6、市集 6/6、社区 12/12)
- 首屏 Three.js 场景的双层 clip-path 做过互补性验证:中点 47.472% / 52.528%,反向滚动收敛回 50% / 50%,避免两层在中间露缝
素质学分申报与审核系统
2025.05 – 2025.06 · 全栈 · 独立开发。基于 RuoYi-Vue 的二次开发,接学院真实学分库
学生素质学分的申报与审核流程原本靠人工核对材料。这个系统把申报、佐证材料上传、分级审核与统计做成线上流程:学生提交 → 待审核 / 通过 / 拒绝三态流转 → 按学期与活动类型出统计。基于 RuoYi-Vue 脚手架二次开发,把时间投在业务模型上而不是重写权限菜单。
技术栈:Java、Spring Boot 2.5、RuoYi-Vue 3.9、MyBatis、MySQL 5.7、Druid、Redis、Vue 2、Element UI、uni-app
- 活动类型建成 4 级自引用树而不是平铺枚举——素质学分体系本身就是「五大模块 → 子模块 → 具体考核项」的层级结构,平铺存不下这个语义
- 审核状态用字典表驱动(待审核 / 通过 / 拒绝 + 对应标签样式),而不是在前端写死 if-else,改文案不用改代码
- 学生端与审核端复用同一套 Service,靠 controller 层区分权限边界,避免两套逻辑各自演进后统计口径不一致
- 统计接口按学期与活动类型两个维度分别出数,因为学分认定是按学期结算的
- 同时做了 uni-app 移动端走同一套接口,验证了 REST 层的端无关性
气象数据实时计算大屏
2026.05 · 课程小组项目 · 实时计算链路。Kafka → Flink → Redis 实时链路 + ECharts 大屏
课程小组项目。技术栈按代码实况列出:实际使用 Flink + Kafka + Redis + MySQL,未引入 Hadoop / Spark / Hive。
省级气象数据的实时采集、聚合与大屏可视化。采集端定时拉取多个气象数据源写入 Kafka,Flink 作业做省级聚合后写 Redis,后端 API 读 Redis 供大屏轮询,整套用 Docker Compose 编排(ZooKeeper / Kafka / Redis / MySQL / JobManager / TaskManager)。
技术栈:Java 8、Apache Flink 1.17、Kafka 3.6、Redis 7、Spring Boot 2.7、MySQL 8、Jedis、Docker Compose、Vue 3、Vite、ECharts 5
- 用 KeyedProcessFunction + MapState 存「每城最新一条」,每来一条事件就重算省级快照——相比开窗聚合,这个写法能让大屏永远拿到当前全量状态而不是上一个窗口的结果
- 30s checkpoint + AT_LEAST_ONCE:气象快照是幂等覆盖写,重复消费不会算错,所以没必要为 EXACTLY_ONCE 付两阶段提交的代价
- 聚合逻辑单独提成静态类(min/max/avg 温度、湿度、风速、降水累计、天气与预警分布),与 Flink 运行时解耦,可以脱离集群单测
- 数据源做成可切换的三档(Mock / Open-Meteo / 和风),本地开发不消耗真实 API 配额
- 整套 Docker Compose 编排,flink run 提交作业,验证过 JobManager 上作业 RUNNING、Redis 里 cityCount=14
乡村非遗平台(零依赖前端原型)
2026.04 – 2026.05 · 前端 · 独立开发。手写 hash 路由 + Mock 数据层,无构建步骤
静态演示原型,数据来自浏览器内 Mock 层,不含生产后端。自身审计文档的结论是「可作为演示交付,但不是完整生产系统」——这条我照写。
非遗内容的发现、学习、体验、社群与展销闭环演示站。刻意不用任何框架与构建工具:一个 80 行的 Router 类做 hash 路由与参数匹配,动态 import 按需加载页面模块,带版本号做缓存击穿。
技术栈:原生 ES Module、手写 Router、Fetch API、AbortController、原生 CSS、高德地图 JS API、Nginx
- 不用框架不用构建:动态 import + 版本号查询串做缓存击穿,改一个页面只要传一个文件上服务器,不需要重新打包全站
- API 层设计成「真接口优先、Mock 兜底」的单一开关(window 上一个标志位),所以同一份前端代码既能连后端演示也能纯静态演示
- Router 支持每个页面注册 cleanup 回调,解决了 hash 路由切换时地图实例与定时器不释放导致的内存泄漏
- 部署脚本把 PNG 批量转 WebP:124MB → 11MB(约 90% 压缩),并加了资源引用完整性门禁——任何被引用但缺失的 .webp 直接中断部署
辽境云游 — 文旅展示线
2026.05 – 2026.09 · 前端 · 独立实现。React 19 + Tailwind 4,11 条路由
项目脚手架源自 Google AI Studio 模板,页面、状态层、管理端与部署流水线由我实现。当前线上为纯静态构建,数据落在 localStorage,未接生产后端。
博物馆与城市文化线路的智慧文旅展示线:云展馆、AR 导览、预约、票券、线路、后台。状态层用一个 712 行的模块统一收口,11 个类型定义描述全部业务实体,接口调用带 1.2s 超时并自动降级到本地状态。
技术栈:React 19、TypeScript、Vite 6、React Router 7、Tailwind CSS 4、Motion、Lucide、qrcode、Express
- 接口调用统一走一个带 1.2s AbortController 超时的封装,超时立刻落回本地状态——演示场景下网络不可控,宁可用本地数据也不能让页面转圈
- localStorage 的 key 带版本号(v2),数据结构变更时旧缓存自动失效而不是解析报错
- 11 个业务类型集中在一个模块里定义,页面只消费类型不各自定义,避免同一实体在 11 个页面里长出 11 种形状
- 素材全部走可溯源渠道并附来源清单,不用来源不明的图
- Tailwind 4 的 @theme 令牌集中管理配色与字号,227 行 CSS 覆盖全站
技术栈
- 编程语言:Java(熟练)、Python(熟练)、JavaScript(熟练)、TypeScript(掌握)、SQL(熟练)、Shell(掌握)、ArkTS(了解)
- 后端框架:Spring Boot(熟练)、MyBatis / MyBatis-Plus(掌握)、RuoYi-Vue(掌握)、Express(掌握)、Sequelize(掌握)、Python http.server(熟练)、RESTful API(熟练)、JWT 鉴权(掌握)、Zod 契约校验(掌握)
- 前端与移动端:Vue 3(熟练)、React 19(掌握)、HTML5 / CSS3(熟练)、ES Module / 原生 SPA(熟练)、Vite(掌握)、Element Plus / Element UI(熟练)、Tailwind CSS(掌握)、ECharts(掌握)、uni-app(掌握)、微信小程序(掌握)、Pinia(掌握)
- 实时计算与数据:Apache Flink(掌握)、Kafka(掌握)、Flink 状态与 Checkpoint(掌握)、Pandas(掌握)、Hadoop / HDFS(了解)、Hive(了解)、Spark(了解)、ClickHouse(了解)
- 数据库与中间件:MySQL(熟练)、SQLite(熟练)、PostgreSQL(掌握)、Redis(掌握)、数据库迁移与校验(掌握)、Druid 连接池(掌握)、MinIO(了解)
- 工程化与运维:Docker / Compose(熟练)、Nginx(熟练)、Linux(熟练)、systemd(掌握)、Git(熟练)、Maven(掌握)、Let's Encrypt / TLS(掌握)、HTTP/2 与缓存策略(掌握)、备份恢复与灰度回滚(掌握)、esbuild / 产物瘦身(掌握)、Postman / Apifox(熟练)
- 质量与安全:Vitest / Supertest(掌握)、JUnit(掌握)、接口越权排查(掌握)、限流与安全响应头(掌握)、日志断言式验证(掌握)、性能测量方法论(掌握)
- AI 与新技术:ChatGPT / Claude / Codex(熟练)、Prompt Engineering(熟练)、AI Agent 工作流(掌握)、HarmonyOS / ArkUI(了解)、RAG(了解)
荣誉与证书
- 世界职业技能大赛 大数据应用技术赛项 三等奖(2024)
- 辽宁省职业院校技能大赛 获奖(2024)
- 校级大数据技术大赛 获奖(2024)
- 一等奖学金(2024)
- 专业排名前 5%(2024)
- 校优秀学生干部(2024)
- HarmonyOS 应用开发相关证书
- 1+X Web 前端开发(中级)
- 1+X 大数据应用开发(中级)
- 全国计算机等级考试 二级 Java
- 全国计算机等级考试 网络技术
关于我
会独立把一个系统做完并交付
自研的对话应用平台从后端、Web 端、管理后台到 Android 客户端全部由我完成,后端不引任何 Web 框架、约 3450 行纯标准库实现,30 张表启动时自动迁移,目前在自建服务器上持续运行。独立负责的意思是没有人兜底——需求不清楚要自己想,线上出问题要自己排查。
真在运维生产环境,不只是写代码
自建服务器上并行运行 7 个站点,共用 Nginx 与 TLS,逐站独立证书与缓存策略。做过 HTTP/2 与缓存调优(请求排队累计 332s → 0.4s)、建过带哈希校验与真解压验证的备份体系。也搞出过一次生产事故并在 4 分钟内回滚——之后定了「改线上运行时前必须先在真实环境干跑」的规矩。
测量比猜测重要
优化那条高抖动链路时,同一份代码测出过 25s 也测出过 80s。所以后来的做法是:打桩替换线上 JS、复用登录态、交错跑 3 轮取中位数,结论优先看确定性指标(重定向数、请求数、排队累计)而不是墙钟时间。
写下来的东西要对得上代码
这个站上线前我把简历每一条都回去核了一遍代码:技术栈按实际 package.json 与 pom.xml 列,规模数字从路由与文件数里数出来,线上地址逐一 curl 过。有几条对不上的(比如某个项目实际只用了 Flink + Kafka 而不是整套 Hadoop 生态)就按代码实况改写,并在站上标注了边界。宁可内容少一点,也不写撑不过两轮追问的东西。
把 AI 当工程工具而不是玄学
日常用 ChatGPT / Claude / Codex 做需求拆解与问题排查,也知道它们在哪里不可靠——给出的库版本、API 签名、许可条款都要自己核。本站的字体许可就是我逐条读官方 LICENSE 确认的,没有一条来自模型记忆。也顺手写了个 CLI 排队保活工具解决自己的实际痛点。