erp.net网站开发图解步骤:3步搞定域名服务器不踩坑
域名解析报错,服务器连接超时,后台改个配置直接白屏。做 erp.net 网站开发 最让人头疼的不是写代码,而是环境搭建那一堆玄学问题。很多后端新手刚接需求,对着 erp.net 这种二级域名和 Nginx 配置头大,根本分不清哪一步是 DNS 的问题,哪一步是防火墙的锅。
别急,今天把这套 图解步骤 拆碎了讲。我们不讲虚的,直接拿一个真实的中型制造企业 ERP 重构项目为例。这个项目域名就是 erp.net 下的子域,业务涉及生产、库存、财务三大模块,日活用户约 2000 人。项目初期,因为域名解析混乱和服务器资源分配不当,导致系统响应慢、偶发 502 错误,差点被甲方投诉。
项目背景与需求:从混乱到清晰的梳理
1. 客户痛点:老旧系统的“烂摊子”
这家制造企业之前用的是五年前开发的单体架构 ERP,技术栈是 JSP + Oracle。随着业务扩张,数据量突破千万级,页面加载时间从 1 秒飙升到 5 秒以上。更致命的是,域名结构混乱,主站、测试环境、移动端混在一起,erp.net 下的子域解析经常失效,导致部分员工无法访问系统。
甲方提出的核心需求非常明确:
- 域名规范化:重新规划
erp.net下的域名结构,确保解析稳定、HTTPS 全覆盖。 - 性能提升:页面加载时间控制在 2 秒内,数据库查询优化。
- 技术升级:从单体架构迁移到微服务架构,前后端分离。
- 合规性:满足等保二级要求,所有接口必须通过 HTTPS 传输。
2. 我们的应对策略
面对这种“既要又要”的需求,我们没有直接动手写代码,而是先花了一周时间做架构梳理和环境规划。
第一步:域名结构重新设计
原来的域名结构是:
erp.net(主站,指向旧系统)test.erp.net(测试环境,解析不稳定)app.erp.net(移动端,未启用 HTTPS)
新的规划如下:
erp.erp.net(生产环境,指向负载均衡)dev.erp.net(开发环境,仅内网可访问)api.erp.net(API 网关,对外提供服务)static.erp.net(静态资源 CDN)
第二步:服务器资源分配
原计划所有服务跑在一台 4 核 8G 的 ECS 上,这显然不够。我们调整为:
- Web 层:2 台 2 核 4G ECS,部署 Nginx 和前端静态资源。
- 应用层:3 台 4 核 8G ECS,部署 Spring Boot 微服务。
- 数据层:1 台 8 核 16G ECS,部署 MySQL 主从集群。
- 缓存层:1 台 4 核 16G ECS,部署 Redis 集群。
第三步:网络与安全规划
所有服务器划分到同一个 VPC 内,通过内网 IP 通信,降低延迟。外网流量统一通过 SLB(负载均衡)进入,SLB 后端挂载 Web 层 ECS。HTTPS 证书在 SLB 层卸载,减轻后端服务器压力。
技术选型:为什么选这套组合
1. 前端:Vue 3 + Vite
考虑到 ERP 系统后台页面多、交互复杂,Vue 3 的 Composition API 和更好的性能优化是关键。Vite 替代 Webpack,冷启动速度提升 10 倍,开发体验极佳。
选型理由:
- Vue 3:响应式系统更轻量,性能更好,适合复杂后台管理界面。
- Vite:开发环境毫秒级热更新,生产环境 Rollup 打包,代码分割更智能。
- Element Plus:成熟的组件库,减少重复造轮子。
2. 后端:Spring Cloud Alibaba
微服务架构是必然选择,但选型要务实。Spring Cloud Alibaba 提供了完整的微服务解决方案,包括服务注册发现(Nacos)、配置中心(Nacos)、网关(Gateway)、熔断限流(Sentinel)等。
选型理由:
- Nacos:同时支持服务注册和配置管理,减少组件数量,运维成本更低。
- Gateway:替代 Zuul,基于 WebFlux 非阻塞模型,性能提升 2-3 倍,支持动态路由。
- Sentinel:实时监控,保护服务免受流量洪峰冲击,避免雪崩效应。
3. 数据库:MySQL 8.0 + MyBatis-Plus
MySQL 8.0 支持 JSON 类型、窗口函数等特性,性能优化更好。MyBatis-Plus 简化 CRUD 操作,提高开发效率。
选型理由:
- MySQL 8.0:引入 CTE(公用表表达式),简化复杂查询;JSON 函数支持,方便存储半结构化数据。
- MyBatis-Plus:内置分页插件、代码生成器,减少 80% 的样板代码。
4. 部署:Docker + K8s
容器化是微服务部署的标准姿势。Docker 保证环境一致性,K8s 实现自动化编排、弹性伸缩。
选型理由:
- Docker:一键打包,避免“在我机器上能跑”的尴尬。
- K8s:自动故障恢复、滚动更新、资源隔离,提升系统稳定性。
核心实现:图解步骤与代码片段
1. 域名解析与 Nginx 配置
这是最容易出问题的环节。erp.net 是二级域名,其解析记录需要在域名服务商处配置。
DNS 配置示例(阿里云解析):
| 记录类型 | 主机记录 | 记录值 | TTL | 备注 |
|---|---|---|---|---|
| A | erp | 47.96.xx.xx | 600 | 指向 SLB 公网 IP |
| A | dev | 172.16.xx.xx | 600 | 指向内网开发服务器 |
| CNAME | api | alb-xxx.alb.aliyuncs.com | 600 | 指向 API 网关 |
| CNAME | static | cdn.xxx.com | 3600 | 指向 CDN 节点 |
Nginx 配置关键片段:
server {listen 80;server_name erp.erp.net;# 强制跳转 HTTPSreturn 301 https://$host$request_uri;
}server {listen 443 ssl;server_name erp.erp.net;# SSL 证书配置ssl_certificate /etc/nginx/ssl/erp.net.crt;ssl_certificate_key /etc/nginx/ssl/erp.net.key;# HSTS 头,强制浏览器使用 HTTPSadd_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;# 前端静态资源location / {root /usr/share/nginx/html;index index.html;try_files $uri $uri/ /index.html;}# 后端 API 代理location /api/ {proxy_pass http://backend-service:8080/;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;# 超时设置proxy_connect_timeout 60s;proxy_send_timeout 60s;proxy_read_timeout 60s;}
}
关键点:
try_files指令确保 SPA 应用的前端路由正常工作。proxy_set_header传递真实 IP,方便后端记录日志。- 超时设置要合理,避免长连接占用资源。
2. Spring Cloud Gateway 动态路由
网关是流量入口,需要实现动态路由和鉴权。
Gateway 配置(application.yml):
spring:cloud:gateway:routes:- id: user-serviceuri: lb://user-servicepredicates:- Path=/api/users/**filters:- StripPrefix=1- name: Retryargs:retries: 3statuses: BAD_GATEWAYmethods: GETbackoff:firstBackoff: 50msfactor: 2maxBackoff: 500ms- id: order-serviceuri: lb://order-servicepredicates:- Path=/api/orders/**filters:- StripPrefix=1- name: CircuitBreakerargs:name: orderCircuitBreakerfallbackUri: forward:/fallback/order
自定义全局过滤器(JWT 鉴权):
@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {@Autowiredprivate JwtUtils jwtUtils;@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request = exchange.getRequest();String path = request.getPath().value();// 白名单路径if (path.startsWith("/api/auth/login") || path.startsWith("/api/public/")) {return chain.filter(exchange);}String token = request.getHeaders().getFirst("Authorization");if (StringUtils.isBlank(token) || !token.startsWith("Bearer ")) {return unauthorized(exchange, "Token is missing or invalid");}token = token.substring(7);try {String username = jwtUtils.parseToken(token);// 将用户信息放入请求头,传递给后端服务ServerHttpRequest newRequest = request.mutate().header("X-User-Name", username).build();return chain.filter(exchange.mutate().request(newRequest).build());} catch (Exception e) {return unauthorized(exchange, "Token is expired or invalid");}}private Mono<Void> unauthorized(ServerWebExchange exchange, String message) {ServerHttpResponse response = exchange.getResponse();response.setStatusCode(HttpStatus.UNAUTHORIZED);response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");byte[] bits = ("{\"code\":401,\"msg\":\"" + message + "\"}").getBytes(StandardCharsets.UTF_8);DataBuffer buffer = response.bufferFactory().wrap(bits);return response.writeWith(Mono.just(buffer));}@Overridepublic int getOrder() {return -1;}
}
关键点:
lb://前缀表示负载均衡,从 Nacos 获取服务实例。StripPrefix=1去掉路径中的/api,简化后端服务处理。- 全局过滤器实现统一鉴权,避免每个服务重复开发。
3. 数据库优化:索引与查询
ERP 系统数据量大,查询性能是瓶颈。
慢查询示例:
SELECT * FROM orders
WHERE order_date >= '2023-01-01'
AND status = 'PAID'
ORDER BY order_date DESC;
问题分析:
- 全表扫描,未使用索引。
ORDER BY导致 filesort。
优化方案:
- 添加复合索引:
ALTER TABLE orders ADD INDEX idx_date_status (order_date, status);
- 覆盖索引:
如果只需要部分字段,可以使用覆盖索引,避免回表。
SELECT order_id, amount FROM orders
WHERE order_date >= '2023-01-01'
AND status = 'PAID'
ORDER BY order_date DESC;
- 分页优化:
对于大偏移量分页,使用游标分页代替 LIMIT offset, size。
-- 传统分页(慢)
SELECT * FROM orders ORDER BY id DESC LIMIT 1000000, 10;-- 游标分页(快)
SELECT * FROM orders WHERE id < 1000000 ORDER BY id DESC LIMIT 10;
关键点:
- 索引不是越多越好,要考虑写入性能。
- 覆盖索引可以减少回表次数,显著提升查询速度。
- 游标分页适合大偏移量场景,但前端需要传递上一页的最后一个 ID。
上线与优化:从测试到生产
1. 压测与性能调优
上线前必须做压测。我们使用 JMeter 模拟 2000 并发用户,测试关键接口。
压测结果:
- 未优化前:TPS 500,平均响应时间 1.2s,P99 响应时间 3.5s。
- 优化后:TPS 1500,平均响应时间 0.3s,P99 响应时间 0.8s。
优化措施:
- Redis 缓存:将热点数据(如用户权限、字典表)缓存到 Redis,TTL 设置 5 分钟。
- 数据库连接池:HikariCP 参数调优,
maximumPoolSize设置为 CPU 核数 * 2 + 磁盘数。 - JVM 调优:根据内存大小调整堆内存,使用 G1 垃圾回收器,减少停顿时间。
2. 监控与告警
部署 Prometheus + Grafana 监控体系,实时监控系统指标。
关键监控指标:
- JVM:堆内存使用率、GC 次数、GC 耗时。
- 数据库:连接数、慢查询数、QPS。
- 应用:接口响应时间、错误率、QPS。
- 基础设施:CPU、内存、磁盘、网络。
告警规则示例:
- 接口 P99 响应时间 > 1s,持续 5 分钟,触发告警。
- 数据库慢查询数 > 10,持续 1 分钟,触发告警。
- JVM 堆内存使用率 > 90%,触发告警。
3. 安全加固
- HTTPS 强制:所有接口必须通过 HTTPS 访问,HTTP 请求重定向到 HTTPS。
- CORS 配置:严格限制跨域来源,只允许
erp.erp.net和admin.erp.net。 - SQL 注入防护:使用 MyBatis-Plus 的参数化查询,避免拼接 SQL。
- XSS 防护:前端使用 Vue 的默认转义机制,后端使用 OWASP Java Encoder 库。
经验总结:避坑指南
1. 域名解析不要图省事
很多新手喜欢用泛解析 *.erp.net,这会导致解析混乱,难以排查问题。建议每个子域单独配置 A 记录或 CNAME 记录,便于管理和监控。
2. Nginx 配置要严谨
try_files 指令是 SPA 应用的关键,配置错误会导致前端路由 404。proxy_set_header 必须正确传递真实 IP,否则后端无法记录准确日志。
3. 微服务不要过度设计
初期用户量不大时,可以先用单体架构,等业务增长后再拆分。过度拆分会增加运维复杂度,得不偿失。
4. 性能优化要基于数据
不要凭感觉优化,要基于压测数据和监控指标。先定位瓶颈,再针对性优化,避免盲目调参。
5. 安全是底线
HTTPS、SQL 注入、XSS 防护必须到位。等保二级要求不是摆设,一旦出事,后果严重。
6. 文档要跟上
技术文档、运维文档、接口文档必须齐全。人员流动是常态,文档是知识传承的关键。
最后,分享一个真实案例中的教训:
在项目初期,我们为了图方便,将开发和测试环境混在同一个 K8s 命名空间里,导致测试数据污染生产数据,差点引发生产事故。后来我们严格隔离命名空间,通过 NetworkPolicy 限制跨命名空间访问,才彻底解决问题。环境隔离不是可选项,而是必选项。
erp.net 网站开发 看似简单,实则处处是坑。从域名解析到 Nginx 配置,从微服务架构到数据库优化,每一步都需要严谨的态度和扎实的技术功底。希望这篇 图解步骤 能帮你少走弯路,快速搭建稳定、高性能的 ERP 系统。
还有什么建站疑问?评论区留言挨个回。