erp.net网站开发图解步骤:3步搞定域名服务器不踩坑

erp.net网站开发图解步骤:3步搞定域名服务器不踩坑

域名解析报错,服务器连接超时,后台改个配置直接白屏。做 erp.net 网站开发 最让人头疼的不是写代码,而是环境搭建那一堆玄学问题。很多后端新手刚接需求,对着 erp.net 这种二级域名和 Nginx 配置头大,根本分不清哪一步是 DNS 的问题,哪一步是防火墙的锅。

别急,今天把这套 图解步骤 拆碎了讲。我们不讲虚的,直接拿一个真实的中型制造企业 ERP 重构项目为例。这个项目域名就是 erp.net 下的子域,业务涉及生产、库存、财务三大模块,日活用户约 2000 人。项目初期,因为域名解析混乱和服务器资源分配不当,导致系统响应慢、偶发 502 错误,差点被甲方投诉。

项目背景与需求:从混乱到清晰的梳理

1. 客户痛点:老旧系统的“烂摊子”

这家制造企业之前用的是五年前开发的单体架构 ERP,技术栈是 JSP + Oracle。随着业务扩张,数据量突破千万级,页面加载时间从 1 秒飙升到 5 秒以上。更致命的是,域名结构混乱,主站、测试环境、移动端混在一起,erp.net 下的子域解析经常失效,导致部分员工无法访问系统。

甲方提出的核心需求非常明确:

  1. 域名规范化:重新规划 erp.net 下的域名结构,确保解析稳定、HTTPS 全覆盖。
  2. 性能提升:页面加载时间控制在 2 秒内,数据库查询优化。
  3. 技术升级:从单体架构迁移到微服务架构,前后端分离。
  4. 合规性:满足等保二级要求,所有接口必须通过 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。

优化方案:

  1. 添加复合索引:
ALTER TABLE orders ADD INDEX idx_date_status (order_date, status);
  1. 覆盖索引:

如果只需要部分字段,可以使用覆盖索引,避免回表。

SELECT order_id, amount FROM orders 
WHERE order_date >= '2023-01-01' 
AND status = 'PAID' 
ORDER BY order_date DESC;
  1. 分页优化:

对于大偏移量分页,使用游标分页代替 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。

优化措施:

  1. Redis 缓存:将热点数据(如用户权限、字典表)缓存到 Redis,TTL 设置 5 分钟。
  2. 数据库连接池:HikariCP 参数调优,maximumPoolSize 设置为 CPU 核数 * 2 + 磁盘数。
  3. JVM 调优:根据内存大小调整堆内存,使用 G1 垃圾回收器,减少停顿时间。

2. 监控与告警

部署 Prometheus + Grafana 监控体系,实时监控系统指标。

关键监控指标:

  • JVM:堆内存使用率、GC 次数、GC 耗时。
  • 数据库:连接数、慢查询数、QPS。
  • 应用:接口响应时间、错误率、QPS。
  • 基础设施:CPU、内存、磁盘、网络。

告警规则示例:

  • 接口 P99 响应时间 > 1s,持续 5 分钟,触发告警。
  • 数据库慢查询数 > 10,持续 1 分钟,触发告警。
  • JVM 堆内存使用率 > 90%,触发告警。

3. 安全加固

  1. HTTPS 强制:所有接口必须通过 HTTPS 访问,HTTP 请求重定向到 HTTPS。
  2. CORS 配置:严格限制跨域来源,只允许 erp.erp.net 和 admin.erp.net。
  3. SQL 注入防护:使用 MyBatis-Plus 的参数化查询,避免拼接 SQL。
  4. 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 系统。

还有什么建站疑问?评论区留言挨个回。