高并发下的图片上传问题处理

图片上传优化与7层负载均衡实践:解决高并发场景下的带宽瓶颈

写在前面

最近在做一个充电桩安装业务系统,安装师傅每天安装完充电桩后需要上传大量的现场图片(每单可能10-20张,每张2-5MB)。随着业务量增长,每天上传的图片量达到数万张,很快就遇到了两个严重问题:

  1. 服务器带宽占用过高:所有图片都先上传到应用服务器,再转发到OSS,导致服务器带宽被打满
  2. 请求超时:大文件上传占用连接时间长,导致其他正常业务请求超时

我们的技术栈是:阿里云OSS存储、ACK(容器服务Kubernetes)部署的微服务架构。这篇文章我会详细分析问题根源,介绍7层负载均衡的原理和应用场景,并给出完整的优化方案。

问题分析

当前架构的问题

让我们先看看当前的架构流程:

复制代码
安装师傅手机端
    ↓ (上传图片,每张2-5MB)
应用服务器(ACK Pod)
    ↓ (占用服务器带宽,转发图片)
阿里云OSS

问题1:带宽瓶颈

假设每天有1000个安装师傅,每人上传15张图片,每张平均3MB:

  • 每天总流量:1000 × 15 × 3MB = 45GB
  • 如果集中在8小时内上传:45GB ÷ 8小时 = 5.625GB/小时 ≈ 12.5Mbps
  • 但实际是并发上传,峰值可能达到100-200Mbps

如果应用服务器带宽只有100Mbps,很容易被打满,导致:

  • 图片上传慢,用户体验差
  • 其他业务请求被阻塞
  • 服务器响应超时

问题2:成本浪费

当前架构下,图片流量走了两次:

  1. 手机端 → 应用服务器(占用服务器带宽,产生费用)
  2. 应用服务器 → OSS(占用服务器带宽,产生费用)

实际上,图片可以直接上传到OSS,不需要经过应用服务器。

问题3:连接占用

大文件上传通常需要较长时间(几秒到几十秒),在这期间会占用服务器的连接资源。如果并发上传量大,可能导致:

  • 连接池耗尽
  • 新请求无法建立连接
  • 服务超时

解决方案:OSS直传 + CDN + 负载均衡

方案架构

优化后的架构应该是这样的:

复制代码
安装师傅手机端
    ↓ (获取上传凭证)
应用服务器(只返回签名,不处理文件)
    ↓ (直接上传,不走服务器带宽)
阿里云OSS
    ↓ (CDN加速)
CDN节点(就近访问)

核心优化点

1. OSS直传(PostObject)

原理:客户端直接上传到OSS,不经过应用服务器。

实现步骤

  1. 服务端生成签名(Java示例)
java 复制代码
@Service
public class OssService {
    
    @Value("${aliyun.oss.endpoint}")
    private String endpoint;
    
    @Value("${aliyun.oss.bucket}")
    private String bucket;
    
    @Value("${aliyun.oss.accessKeyId}")
    private String accessKeyId;
    
    @Value("${aliyun.oss.accessKeySecret}")
    private String accessKeySecret;
    
    /**
     * 生成OSS直传签名
     * @param fileName 文件名
     * @param contentType 文件类型
     * @return 上传凭证
     */
    public OssUploadToken generateUploadToken(String fileName, String contentType) {
        // 生成唯一文件名(避免覆盖)
        String objectKey = "install-images/" + 
            LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd")) + 
            "/" + UUID.randomUUID().toString() + 
            "_" + fileName;
        
        // 设置过期时间(1小时)
        Date expiration = new Date(System.currentTimeMillis() + 3600 * 1000);
        
        // 构建Policy
        JSONObject policy = new JSONObject();
        policy.put("expiration", new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
            .format(expiration));
        
        JSONArray conditions = new JSONArray();
        // 限制bucket
        JSONArray bucketCondition = new JSONArray();
        bucketCondition.add("eq");
        bucketCondition.add("$bucket");
        bucketCondition.add(bucket);
        conditions.add(bucketCondition);
        
        // 限制文件大小(最大10MB)
        JSONArray sizeCondition = new JSONArray();
        sizeCondition.add("content-length-range");
        sizeCondition.add(0);
        sizeCondition.add(10485760);
        conditions.add(sizeCondition);
        
        // 限制文件类型
        JSONArray contentTypeCondition = new JSONArray();
        contentTypeCondition.add("starts-with");
        contentTypeCondition.add("$content-type");
        contentTypeCondition.add("image/");
        conditions.add(contentTypeCondition);
        
        policy.put("conditions", conditions);
        
        // Base64编码Policy
        String policyBase64 = Base64.getEncoder()
            .encodeToString(policy.toJSONString().getBytes(StandardCharsets.UTF_8));
        
        // 生成签名
        Mac hmac = Mac.getInstance("HmacSHA1");
        SecretKeySpec secretKeySpec = new SecretKeySpec(
            accessKeySecret.getBytes(StandardCharsets.UTF_8), "HmacSHA1");
        hmac.init(secretKeySpec);
        byte[] signData = hmac.doFinal(policyBase64.getBytes(StandardCharsets.UTF_8));
        String signature = Base64.getEncoder().encodeToString(signData);
        
        OssUploadToken token = new OssUploadToken();
        token.setPolicy(policyBase64);
        token.setSignature(signature);
        token.setAccessKeyId(accessKeyId);
        token.setObjectKey(objectKey);
        token.setHost("https://" + bucket + "." + endpoint);
        token.setExpireTime(expiration.getTime());
        
        return token;
    }
}
  1. 客户端直接上传(前端示例)
javascript 复制代码
// 1. 获取上传凭证
async function getUploadToken(fileName, fileType) {
    const response = await fetch('/api/oss/upload-token', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({
            fileName: fileName,
            contentType: fileType
        })
    });
    return await response.json();
}

// 2. 直接上传到OSS
async function uploadToOss(file) {
    // 获取上传凭证
    const token = await getUploadToken(file.name, file.type);
    
    // 构建FormData
    const formData = new FormData();
    formData.append('key', token.objectKey);
    formData.append('policy', token.policy);
    formData.append('OSSAccessKeyId', token.accessKeyId);
    formData.append('signature', token.signature);
    formData.append('Content-Type', file.type);
    formData.append('file', file);
    
    // 直接上传到OSS(不走应用服务器)
    const response = await fetch(token.host, {
        method: 'POST',
        body: formData
    });
    
    if (response.ok) {
        // 上传成功,返回OSS文件URL
        return `${token.host}/${token.objectKey}`;
    } else {
        throw new Error('上传失败');
    }
}

优势

  • 图片不经过应用服务器,节省服务器带宽
  • 上传速度快(直接到OSS,减少一跳)
  • 降低服务器负载
  • 节省流量费用
2. CDN加速

原理:将OSS中的图片通过CDN分发,用户访问时从就近节点获取。

配置步骤

  1. OSS绑定CDN域名

    • 在OSS控制台,为Bucket绑定CDN加速域名
    • 配置HTTPS证书
    • 开启CDN缓存(图片建议缓存7-30天)
  2. CDN回源配置

    • 回源Host:OSS的Bucket域名
    • 回源协议:HTTPS
    • 缓存规则:根据文件类型和路径设置
  3. 访问URL

    • 原来:https://bucket.oss-cn-hangzhou.aliyuncs.com/image.jpg
    • 现在:https://cdn.example.com/image.jpg(通过CDN访问)

优势

  • 用户访问图片更快(就近节点)
  • 减少OSS的访问压力
  • CDN流量费用通常比OSS外网流量费用低
3. 图片压缩与格式优化

客户端压缩

javascript 复制代码
// 压缩图片(保持质量的同时减小体积)
function compressImage(file, maxWidth = 1920, quality = 0.8) {
    return new Promise((resolve) => {
        const reader = new FileReader();
        reader.onload = (e) => {
            const img = new Image();
            img.onload = () => {
                const canvas = document.createElement('canvas');
                let width = img.width;
                let height = img.height;
                
                // 按比例缩放
                if (width > maxWidth) {
                    height = (height * maxWidth) / width;
                    width = maxWidth;
                }
                
                canvas.width = width;
                canvas.height = height;
                
                const ctx = canvas.getContext('2d');
                ctx.drawImage(img, 0, 0, width, height);
                
                // 转换为Blob
                canvas.toBlob((blob) => {
                    resolve(blob);
                }, 'image/jpeg', quality);
            };
            img.src = e.target.result;
        };
        reader.readAsDataURL(file);
    });
}

// 使用
const compressedFile = await compressImage(originalFile);
await uploadToOss(compressedFile);

服务端处理(可选):

  • 使用OSS的图片处理服务(IMG)
  • 自动生成缩略图
  • 格式转换(WebP等)

7层负载均衡详解

什么是7层负载均衡?

负载均衡分为4层(L4)7层(L7)

  • 4层负载均衡:基于IP和端口进行转发(TCP/UDP层)
  • 7层负载均衡:基于HTTP/HTTPS协议内容进行转发(应用层)

OSI模型与负载均衡

复制代码
OSI 7层模型:
┌─────────────────────────────────────┐
│  7. 应用层 (Application)            │ ← 7层负载均衡(HTTP/HTTPS)
│  6. 表示层 (Presentation)           │
│  5. 会话层 (Session)                │
├─────────────────────────────────────┤
│  4. 传输层 (Transport) - TCP/UDP    │ ← 4层负载均衡
├─────────────────────────────────────┤
│  3. 网络层 (Network) - IP           │
│  2. 数据链路层 (Data Link)          │
│  1. 物理层 (Physical)               │
└─────────────────────────────────────┘

7层负载均衡的工作原理

7层负载均衡器(如Nginx、ALB)会:

  1. 解析HTTP请求:读取HTTP头部信息(Host、URL、Cookie等)

  2. 根据规则路由:基于请求内容决定转发到哪个后端服务器

  3. 建立新连接:与后端服务器建立新的TCP连接

  4. 转发请求:将完整的HTTP请求转发给后端

  5. 返回响应:将后端响应返回给客户端

    客户端请求

    7层负载均衡器(解析HTTP)
    ├─ 根据Host: api.example.com → 转发到API服务
    ├─ 根据URL: /static/ → 转发到静态资源服务
    └─ 根据Cookie: session_id → 转发到特定服务器(会话保持)

    后端服务器

7层负载均衡的核心功能

1. 基于域名的路由(Virtual Host)

场景:多个域名指向同一个负载均衡器,需要路由到不同的后端服务。

复制代码
请求:Host: api.example.com → 后端:API服务集群
请求:Host: admin.example.com → 后端:管理后台集群
请求:Host: static.example.com → 后端:静态资源服务

Nginx配置示例

nginx 复制代码
# API服务
server {
    listen 80;
    server_name api.example.com;
    
    location / {
        proxy_pass http://api_backend;
    }
}

# 管理后台
server {
    listen 80;
    server_name admin.example.com;
    
    location / {
        proxy_pass http://admin_backend;
    }
}
2. 基于URL路径的路由

场景:同一个域名下,不同路径路由到不同服务。

复制代码
请求:/api/user → 用户服务
请求:/api/order → 订单服务
请求:/api/payment → 支付服务
请求:/static/ → 静态资源(CDN或Nginx直接返回)

Nginx配置示例

nginx 复制代码
server {
    listen 80;
    server_name example.com;
    
    # 用户服务
    location /api/user {
        proxy_pass http://user_service;
    }
    
    # 订单服务
    location /api/order {
        proxy_pass http://order_service;
    }
    
    # 静态资源
    location /static/ {
        root /var/www/static;
        expires 30d;
    }
}
3. 基于HTTP头部的路由

场景:根据请求头(如User-Agent、Cookie)进行路由。

复制代码
移动端请求(User-Agent包含Mobile) → 移动端专用服务
PC端请求 → PC端服务

Nginx配置示例

nginx 复制代码
server {
    listen 80;
    
    # 移动端
    if ($http_user_agent ~* "mobile|android|iphone") {
        proxy_pass http://mobile_backend;
        break;
    }
    
    # PC端
    proxy_pass http://pc_backend;
}
4. 会话保持(Session Affinity)

场景:确保同一用户的请求总是转发到同一台服务器(用于有状态服务)。

实现方式

  • Cookie方式:负载均衡器插入Cookie,记录后端服务器信息
  • IP Hash:根据客户端IP的Hash值选择后端服务器

Nginx配置示例

nginx 复制代码
upstream backend {
    # IP Hash方式
    ip_hash;
    
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
}
5. 内容重写与重定向

场景:URL重写、HTTPS重定向等。

nginx 复制代码
# HTTP重定向到HTTPS
server {
    listen 80;
    server_name example.com;
    return 301 https://$server_name$request_uri;
}

# URL重写
location /old-path {
    rewrite ^/old-path/(.*)$ /new-path/$1 permanent;
}
6. SSL终止(SSL Termination)

场景:在负载均衡器上处理SSL/TLS,减轻后端服务器压力。

复制代码
客户端 → [HTTPS] → 负载均衡器(SSL终止) → [HTTP] → 后端服务器

优势

  • 后端服务器不需要处理SSL,性能更好
  • 集中管理证书,更安全
  • 可以统一做SSL优化

7层负载均衡的应用场景

场景1:微服务网关

需求:多个微服务需要统一入口,根据路径路由到不同服务。

复制代码
客户端
    ↓
API网关(7层负载均衡)
    ├─ /user/* → 用户服务
    ├─ /order/* → 订单服务
    ├─ /payment/* → 支付服务
    └─ /install/* → 安装服务(你的场景)

阿里云ALB配置

  • 创建应用型负载均衡(ALB)
  • 配置监听规则:基于路径转发
  • 后端服务器组:指向ACK的Service
场景2:动静分离

需求:静态资源(图片、CSS、JS)和动态API分开处理。

复制代码
请求:/api/* → 应用服务器(动态内容)
请求:/static/* → CDN或Nginx(静态资源,直接返回,不走应用服务器)

优势

  • 静态资源不占用应用服务器资源
  • 可以单独对静态资源做CDN加速
  • 应用服务器专注处理业务逻辑
场景3:A/B测试与灰度发布

需求:根据用户特征(Cookie、Header)将流量分发到不同版本。

复制代码
新用户 → 新版本服务(10%流量)
老用户 → 旧版本服务(90%流量)

Nginx配置示例

nginx 复制代码
# 根据Cookie中的version字段路由
map $cookie_version $backend {
    default "v1_backend";
    "v2" "v2_backend";
}

server {
    location / {
        proxy_pass http://$backend;
    }
}
场景4:限流与防护

需求:在负载均衡层做限流,保护后端服务。

Nginx限流配置

nginx 复制代码
# 限制每个IP的请求速率
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;

server {
    location /api/ {
        limit_req zone=api_limit burst=20;
        proxy_pass http://backend;
    }
}
场景5:请求日志与分析

需求:在负载均衡层记录访问日志,用于分析。

Nginx日志配置

nginx 复制代码
log_format detailed '$remote_addr - $remote_user [$time_local] '
                   '"$request" $status $body_bytes_sent '
                   '"$http_referer" "$http_user_agent" '
                   'rt=$request_time uct="$upstream_connect_time" '
                   'uht="$upstream_header_time" urt="$upstream_response_time"';

access_log /var/log/nginx/access.log detailed;

4层 vs 7层负载均衡对比

特性 4层负载均衡(L4) 7层负载均衡(L7)
工作层级 TCP/UDP层 HTTP/HTTPS层
转发依据 IP + 端口 HTTP头部、URL、Cookie等
性能 更高(不需要解析HTTP) 相对较低(需要解析HTTP)
功能 简单转发 丰富的路由规则、内容处理
适用场景 高并发、简单转发 微服务网关、复杂路由
典型产品 阿里云SLB(4层)、F5 阿里云ALB、Nginx、HAProxy

阿里云负载均衡产品选择

1. 传统型负载均衡CLB(原SLB)
  • 支持4层和7层
  • 适用场景:传统应用、简单转发
  • 特点:功能基础,性能稳定
2. 应用型负载均衡ALB
  • 仅支持7层(HTTP/HTTPS)
  • 适用场景:微服务、API网关、复杂路由
  • 特点
    • 基于内容的路由(域名、路径、Header)
    • 支持Serverless后端(函数计算)
    • 自动弹性伸缩
    • 更丰富的监控指标
3. 网络型负载均衡NLB
  • 仅支持4层(TCP/UDP)
  • 适用场景:超高性能、低延迟场景
  • 特点
    • 超高性能(支持百万级并发)
    • 低延迟
    • 适用于游戏、金融等对性能要求极高的场景

针对我的场景的完整方案

架构设计

复制代码
安装师傅手机端
    ↓
    ├─ 1. 获取上传凭证(小请求,走应用服务器)
    │     /api/oss/upload-token
    │
    └─ 2. 直接上传图片到OSS(大文件,不走应用服务器)
          https://bucket.oss-cn-hangzhou.aliyuncs.com
          ↓
          OSS存储
          ↓
          CDN加速(可选)
          https://cdn.example.com/image.jpg

具体实施步骤

步骤1:实现OSS直传

后端服务(Spring Boot)

java 复制代码
@RestController
@RequestMapping("/api/oss")
public class OssController {
    
    @Autowired
    private OssService ossService;
    
    /**
     * 获取上传凭证
     */
    @PostMapping("/upload-token")
    public Result<OssUploadToken> getUploadToken(
            @RequestBody UploadTokenRequest request) {
        OssUploadToken token = ossService.generateUploadToken(
            request.getFileName(), 
            request.getContentType()
        );
        return Result.success(token);
    }
    
    /**
     * 上传完成回调(可选,用于记录上传记录)
     */
    @PostMapping("/upload-callback")
    public Result<String> uploadCallback(@RequestBody OssCallback callback) {
        // 验证OSS回调签名
        if (!ossService.verifyCallback(callback)) {
            return Result.error("签名验证失败");
        }
        
        // 记录上传信息到数据库
        installImageService.recordUpload(
            callback.getObjectKey(),
            callback.getSize(),
            callback.getUserId()
        );
        
        return Result.success("上传记录成功");
    }
}
步骤2:配置CDN加速(可选但推荐)
  1. 在OSS控制台绑定CDN域名

    • 进入OSS Bucket → 传输管理 → CDN加速
    • 绑定自定义域名(如:cdn.example.com
    • 配置HTTPS证书
  2. CDN缓存配置

    • 缓存时间:图片文件缓存30天
    • 回源协议:HTTPS
    • 开启Gzip压缩
  3. 修改上传后的URL

java 复制代码
@Service
public class OssService {
    
    @Value("${aliyun.cdn.domain:}")
    private String cdnDomain;
    
    public String getImageUrl(String objectKey) {
        if (StringUtils.isNotBlank(cdnDomain)) {
            // 使用CDN域名
            return "https://" + cdnDomain + "/" + objectKey;
        } else {
            // 使用OSS域名
            return "https://" + bucket + "." + endpoint + "/" + objectKey;
        }
    }
}
步骤3:配置7层负载均衡(ALB)- 完整实施流程

场景:如果你的应用有多个服务,需要统一入口,通过7层负载均衡实现灵活的请求路由。

3.1 准备工作

在开始配置之前,需要确认以下信息:

  1. ACK集群信息

    • 集群ID
    • VPC ID
    • 可用区(至少2个)
    • 子网ID
  2. 域名和证书

    • API域名(如:api.example.com
    • SSL证书(可在阿里云SSL证书服务申请,或上传自有证书)
  3. 服务信息

    • 各个微服务的Service名称
    • 服务的健康检查路径(如:/health、/actuator/health)
3.2 创建ALB实例

步骤1:进入负载均衡控制台

  1. 登录阿里云控制台
  2. 进入「产品与服务」→「网络」→「负载均衡SLB」
  3. 点击「创建负载均衡」

步骤2:选择负载均衡类型

  • 负载均衡类型:选择「应用型负载均衡(ALB)」
  • 地域:选择与ACK集群相同的地域(如:华东1-杭州)
  • 可用区:至少选择2个可用区(如:可用区H、可用区I),实现高可用

步骤3:配置基本信息

复制代码
实例名称:alb-api-gateway
付费类型:按量付费(或包年包月)
规格:标准型(根据业务量选择,支持弹性扩容)

步骤4:配置网络

复制代码
网络类型:专有网络(VPC)
VPC:选择ACK集群所在的VPC
交换机:在每个可用区选择至少一个交换机
    - 可用区H:选择交换机1(如:vsw-xxx1)
    - 可用区I:选择交换机2(如:vsw-xxx2)

重要提示

  • ALB必须与ACK集群在同一个VPC内
  • 交换机必须有足够的IP地址(建议至少预留10个IP)

步骤5:创建并获取ALB地址

创建完成后,记录ALB的IP地址(如:47.xxx.xxx.xxx),后续配置DNS会用到。

3.3 配置ACK Service(后端服务)

在配置ALB之前,需要确保ACK中的服务已经正确配置。

步骤1:检查现有Service

bash 复制代码
# 查看所有Service
kubectl get svc -n <namespace>

# 查看Service详情
kubectl describe svc <service-name> -n <namespace>

步骤2:创建或修改Service(如果需要)

假设你有以下微服务:

  • install-service:安装服务(处理安装相关API)
  • oss-service:OSS服务(处理上传凭证等)
  • user-service:用户服务

为每个服务创建Service:

yaml 复制代码
# install-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: install-service
  namespace: default
  labels:
    app: install-service
spec:
  type: ClusterIP  # 内部服务,不对外暴露
  ports:
    - port: 8080      # Service端口
      targetPort: 8080  # Pod端口
      protocol: TCP
  selector:
    app: install-service  # 选择器,匹配Pod标签
---
# oss-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: oss-service
  namespace: default
  labels:
    app: oss-service
spec:
  type: ClusterIP
  ports:
    - port: 8080
      targetPort: 8080
      protocol: TCP
  selector:
    app: oss-service

应用配置:

bash 复制代码
kubectl apply -f install-service.yaml
kubectl apply -f oss-service.yaml

步骤3:添加健康检查端点

确保每个服务都有健康检查接口:

java 复制代码
// Spring Boot示例
@RestController
public class HealthController {
    
    @GetMapping("/health")
    public Map<String, String> health() {
        Map<String, String> status = new HashMap<>();
        status.put("status", "UP");
        status.put("timestamp", Instant.now().toString());
        return status;
    }
    
    // 或者使用Spring Boot Actuator
    // 在application.yml中配置:
    // management:
    //   endpoints:
    //     web:
    //       exposure:
    //         include: health,info
}
3.4 配置ALB监听(HTTPS)

步骤1:添加监听

  1. 在ALB实例详情页,点击「监听」标签
  2. 点击「添加监听」
  3. 选择协议和端口:
    • 协议:HTTPS
    • 端口:443

步骤2:配置SSL证书

  1. 证书来源

    • 如果已有证书:选择「上传证书」,上传证书文件(.pem格式)和私钥(.key格式)
    • 如果没有证书:可以在「SSL证书」服务中申请免费证书(DV证书)
  2. 证书配置

    复制代码
    证书:选择或上传SSL证书
    TLS版本:TLSv1.2、TLSv1.3(建议都勾选)

步骤3:配置监听高级设置

复制代码
调度算法:加权轮询(WRR)或加权最小连接数(WLC)
    - WRR:按权重轮询,适合请求处理时间相近的场景
    - WLC:优先分配给连接数少的后端,适合请求处理时间差异大的场景

连接超时时间:60秒(根据实际情况调整)
请求超时时间:60秒

Gzip压缩:开启(可以压缩响应内容,节省带宽)
3.5 配置后端服务器组

步骤1:创建服务器组

  1. 在监听配置页面,点击「后端服务器组」
  2. 点击「创建服务器组」

步骤2:配置服务器组基本信息

复制代码
服务器组名称:backend-install-service
服务器组类型:IP类型 或 服务器类型
    - IP类型:直接指定Pod IP(不推荐,Pod重启IP会变)
    - 服务器类型:选择ACK集群的节点(需要安装ALB Ingress Controller)
    - 函数计算类型:如果使用Serverless后端

协议:HTTP(ALB到后端使用HTTP,SSL在ALB终止)
端口:8080(Service的端口)

重要 :对于ACK场景,推荐使用ALB Ingress Controller,这样可以直接关联Kubernetes Service。

步骤3:安装ALB Ingress Controller(推荐方式)

这是连接ALB和ACK的最佳实践:

bash 复制代码
# 1. 添加ALB Ingress Controller的Helm仓库
helm repo add alibaba https://aliacs-app-catalog.oss-cn-hangzhou.aliyuncs.com/charts-incubator/
helm repo update

# 2. 安装ALB Ingress Controller
helm install alibaba/alb-ingress-controller \
  --namespace kube-system \
  --set regionId=cn-hangzhou \
  --set clusterId=<你的ACK集群ID> \
  --set vpcId=<你的VPC ID> \
  --set albId=<你的ALB实例ID>

步骤4:使用Ingress配置路由(推荐)

创建Ingress资源,自动关联ALB:

yaml 复制代码
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api-ingress
  namespace: default
  annotations:
    # 指定使用ALB
    alb.ingress.kubernetes.io/load-balancer-id: <ALB实例ID>
    # 监听配置
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}]'
    # SSL证书
    alb.ingress.kubernetes.io/certificate-id: <证书ID>
    # 健康检查
    alb.ingress.kubernetes.io/healthcheck-path: /health
    alb.ingress.kubernetes.io/healthcheck-protocol: HTTP
    alb.ingress.kubernetes.io/healthcheck-interval-seconds: '5'
    alb.ingress.kubernetes.io/healthcheck-timeout-seconds: '3'
    alb.ingress.kubernetes.io/healthy-threshold-count: '2'
    alb.ingress.kubernetes.io/unhealthy-threshold-count: '3'
spec:
  ingressClassName: alb
  rules:
    # 安装服务路由
    - host: api.example.com
      http:
        paths:
          - path: /api/install
            pathType: Prefix
            backend:
              service:
                name: install-service
                port:
                  number: 8080
          # OSS服务路由
          - path: /api/oss
            pathType: Prefix
            backend:
              service:
                name: oss-service
                port:
                  number: 8080
          # 其他API路由
          - path: /api
            pathType: Prefix
            backend:
              service:
                name: api-gateway-service
                port:
                  number: 8080

应用Ingress配置:

bash 复制代码
kubectl apply -f ingress.yaml

步骤5:手动配置后端服务器组(如果不使用Ingress)

如果不想使用Ingress,可以手动配置:

  1. 创建服务器组

    • 服务器组名称:backend-install-service
    • 协议:HTTP
    • 端口:8080
  2. 添加后端服务器

    • 方式1:添加ECS实例(ACK节点)
      • 选择ACK集群的节点ECS
      • 端口:8080(Service的NodePort,如果使用NodePort类型)
    • 方式2:添加IP地址(Pod IP,不推荐)
  3. 配置健康检查

    复制代码
    检查协议:HTTP
    检查路径:/health
    检查端口:8080
    检查间隔:5秒
    超时时间:3秒
    健康阈值:2次(连续2次成功认为健康)
    不健康阈值:3次(连续3次失败认为不健康)
    HTTP状态码:200(健康检查成功的状态码)
  4. 配置权重

    • 如果后端服务器性能不同,可以设置不同权重
    • 权重越高,分配的流量越多
3.6 配置转发规则

步骤1:添加转发规则

在监听配置页面,添加转发规则:

规则1:安装服务路由

复制代码
规则名称:rule-install-service
域名:api.example.com(或留空,匹配所有域名)
路径:/api/install/*
    - 匹配方式:前缀匹配
    - 说明:所有以 /api/install 开头的请求
转发至:backend-install-service(后端服务器组)
优先级:1(数字越小优先级越高)

规则2:OSS服务路由

复制代码
规则名称:rule-oss-service
域名:api.example.com
路径:/api/oss/*
转发至:backend-oss-service
优先级:2

规则3:默认路由

复制代码
规则名称:rule-default
域名:api.example.com
路径:/*
转发至:backend-default-service
优先级:100(最低优先级,作为默认规则)

规则匹配顺序

  1. 先匹配域名(如果配置了)
  2. 再匹配路径(按优先级从高到低)
  3. 匹配到第一个规则后停止

步骤2:配置高级路由规则(可选)

如果需要更复杂的路由,可以使用基于Header的路由:

复制代码
条件:HTTP Header
Header名称:X-Service-Version
Header值:v2
匹配方式:等于
转发至:backend-service-v2
3.7 配置DNS解析

步骤1:获取ALB的IP地址

在ALB实例详情页,记录「服务地址」(公网IP或内网IP)。

步骤2:配置DNS解析

  1. 进入「云解析DNS」控制台

  2. 找到你的域名(example.com

  3. 添加解析记录:

    记录类型:A记录
    主机记录:api(完整域名为 api.example.com
    记录值:ALB的服务地址(IP)
    TTL:600秒(10分钟)

步骤3:验证DNS解析

bash 复制代码
# 使用dig命令验证
dig api.example.com

# 或使用nslookup
nslookup api.example.com

# 应该返回ALB的IP地址
3.8 配置会话保持(如需要)

如果你的服务是有状态的,需要配置会话保持:

步骤1:在服务器组中配置

复制代码
会话保持:开启
会话保持方式:基于Cookie
    - 植入Cookie:ALB自动插入Cookie
    - 重写Cookie:重写应用返回的Cookie
Cookie名称:ALB_SESSION(可自定义)
Cookie超时时间:86400秒(24小时)

步骤2:在代码中处理(如果使用重写Cookie)

java 复制代码
// Spring Boot示例
@RestController
public class ApiController {
    
    @GetMapping("/api/test")
    public Result test(HttpServletResponse response) {
        // 如果使用重写Cookie方式,需要在响应中设置Cookie
        Cookie cookie = new Cookie("ALB_SESSION", sessionId);
        cookie.setPath("/");
        cookie.setMaxAge(86400);
        response.addCookie(cookie);
        
        return Result.success();
    }
}
3.9 配置访问控制(安全加固)

步骤1:配置访问控制列表(ACL)

  1. 在ALB实例中,进入「访问控制」

  2. 创建访问控制策略组

  3. 添加IP白名单或黑名单:

    策略组名称:api-whitelist
    类型:白名单(只允许列表中的IP访问)
    IP地址:
    - 192.168.1.0/24(内网段)
    - 10.0.0.0/8(VPC网段)

  4. 在监听中关联访问控制策略组

步骤2:配置WAF(Web应用防火墙)

如果需要更高级的安全防护:

  1. 在ALB监听中开启「WAF防护」
  2. 配置WAF规则:
    • 防SQL注入
    • 防XSS攻击
    • 防CC攻击
    • 自定义规则
3.10 测试验证

步骤1:测试健康检查

bash 复制代码
# 直接访问后端服务(通过Service)
kubectl port-forward svc/install-service 8080:8080 -n default

# 在另一个终端测试
curl http://localhost:8080/health

# 应该返回:
# {"status":"UP","timestamp":"2024-01-01T12:00:00Z"}

步骤2:测试ALB路由

bash 复制代码
# 测试安装服务路由
curl -H "Host: api.example.com" https://<ALB-IP>/api/install/health

# 测试OSS服务路由
curl -H "Host: api.example.com" https://<ALB-IP>/api/oss/upload-token

# 测试默认路由
curl -H "Host: api.example.com" https://<ALB-IP>/api/health

步骤3:测试HTTPS

bash 复制代码
# 测试HTTPS(忽略证书验证,仅测试连通性)
curl -k https://api.example.com/api/health

# 正常测试(验证证书)
curl https://api.example.com/api/health

步骤4:测试负载均衡

bash 复制代码
# 连续发送多个请求,观察是否分发到不同后端
for i in {1..10}; do
  curl https://api.example.com/api/health
  echo ""
done

# 查看后端服务器的访问日志,确认请求被分发
3.11 监控与告警配置

步骤1:查看监控指标

在ALB控制台,可以查看:

  • 请求数:QPS、总请求数
  • 流量:入流量、出流量
  • 延迟:平均响应时间、P99延迟
  • 错误率:4xx、5xx错误率
  • 后端健康:健康检查成功率

步骤2:配置告警

  1. 进入「云监控」控制台

  2. 创建告警规则:

    指标:ALB请求错误率
    阈值:> 5%(错误率超过5%告警)
    通知方式:邮件、短信、钉钉

    指标:ALB后端健康检查失败
    阈值:连续失败3次
    通知方式:邮件、短信

3.12 故障排查

问题1:502 Bad Gateway

可能原因

  • 后端服务不可用
  • 健康检查失败
  • 网络不通

排查步骤

bash 复制代码
# 1. 检查后端服务状态
kubectl get pods -n default
kubectl logs <pod-name> -n default

# 2. 检查Service
kubectl get svc -n default
kubectl describe svc <service-name> -n default

# 3. 检查健康检查端点
kubectl port-forward svc/<service-name> 8080:8080
curl http://localhost:8080/health

# 4. 检查ALB后端服务器组状态
# 在ALB控制台查看后端服务器健康状态

问题2:路由不生效

可能原因

  • 转发规则配置错误
  • 路径匹配不正确
  • 优先级设置错误

排查步骤

bash 复制代码
# 1. 检查Ingress配置
kubectl get ingress -n default
kubectl describe ingress <ingress-name> -n default

# 2. 检查ALB转发规则
# 在ALB控制台查看监听规则,确认路径和优先级

# 3. 测试不同路径
curl https://api.example.com/api/install/test
curl https://api.example.com/api/oss/test

问题3:SSL证书问题

可能原因

  • 证书过期
  • 证书域名不匹配
  • 证书格式错误

排查步骤

bash 复制代码
# 1. 检查证书有效期
openssl x509 -in certificate.pem -noout -dates

# 2. 检查证书域名
openssl x509 -in certificate.pem -noout -text | grep DNS

# 3. 测试SSL连接
openssl s_client -connect api.example.com:443 -servername api.example.com

问题4:DNS解析问题

排查步骤

bash 复制代码
# 1. 检查DNS解析
dig api.example.com
nslookup api.example.com

# 2. 检查本地DNS缓存
# Windows: ipconfig /flushdns
# Linux: systemd-resolve --flush-caches

# 3. 直接使用IP测试
curl -H "Host: api.example.com" https://<ALB-IP>/api/health
3.13 性能优化建议

1. 开启HTTP/2

在ALB监听中开启HTTP/2支持,可以提升性能:

复制代码
协议版本:HTTP/2(自动协商,支持HTTP/1.1和HTTP/2)

2. 配置连接复用

在应用代码中配置HTTP客户端连接池:

java 复制代码
// Spring Boot RestTemplate配置
@Configuration
public class RestTemplateConfig {
    
    @Bean
    public RestTemplate restTemplate() {
        HttpComponentsClientHttpRequestFactory factory = 
            new HttpComponentsClientHttpRequestFactory();
        factory.setConnectionRequestTimeout(5000);
        factory.setConnectTimeout(5000);
        factory.setReadTimeout(10000);
        
        // 配置连接池
        PoolingHttpClientConnectionManager connectionManager = 
            new PoolingHttpClientConnectionManager();
        connectionManager.setMaxTotal(200);
        connectionManager.setDefaultMaxPerRoute(50);
        
        CloseableHttpClient httpClient = HttpClients.custom()
            .setConnectionManager(connectionManager)
            .build();
        
        factory.setHttpClient(httpClient);
        return new RestTemplate(factory);
    }
}

3. 配置超时时间

根据业务需求合理设置超时:

复制代码
连接超时:5秒(建立连接的最大时间)
请求超时:30秒(处理请求的最大时间,根据接口响应时间调整)

4. 开启Gzip压缩

在ALB监听中开启Gzip压缩,可以减少传输数据量:

复制代码
Gzip压缩:开启
压缩类型:text/html, text/css, application/json, application/javascript
3.14 完整配置示例总结

架构图

复制代码
客户端
    ↓ HTTPS (api.example.com)
DNS解析
    ↓
ALB (47.xxx.xxx.xxx:443)
    ├─ 规则1: /api/install/* → backend-install-service
    ├─ 规则2: /api/oss/* → backend-oss-service
    └─ 规则3: /api/* → backend-default-service
    ↓ HTTP (内网)
ACK Service (ClusterIP)
    ↓
Pod (应用服务)

配置清单

  1. ✅ ALB实例创建(VPC、可用区、规格)
  2. ✅ SSL证书配置(HTTPS监听)
  3. ✅ ACK Service配置(ClusterIP类型)
  4. ✅ Ingress配置(自动关联ALB)或手动配置后端服务器组
  5. ✅ 转发规则配置(域名、路径、优先级)
  6. ✅ 健康检查配置(路径、间隔、阈值)
  7. ✅ DNS解析配置(A记录指向ALB)
  8. ✅ 监控告警配置(错误率、健康检查)
  9. ✅ 安全配置(ACL、WAF,可选)

验证清单

  • DNS解析正确(dig/nslookup)
  • HTTPS访问正常(curl测试)
  • 路由规则生效(不同路径访问不同服务)
  • 健康检查正常(后端服务健康状态为正常)
  • 负载均衡生效(请求分发到多个后端)
  • 监控指标正常(请求数、错误率等)
步骤4:客户端优化

图片压缩与上传

javascript 复制代码
class ImageUploader {
    constructor() {
        this.maxWidth = 1920;
        this.quality = 0.8;
    }
    
    // 压缩图片
    async compressImage(file) {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = (e) => {
                const img = new Image();
                img.onload = () => {
                    const canvas = document.createElement('canvas');
                    let { width, height } = img;
                    
                    if (width > this.maxWidth) {
                        height = (height * this.maxWidth) / width;
                        width = this.maxWidth;
                    }
                    
                    canvas.width = width;
                    canvas.height = height;
                    
                    const ctx = canvas.getContext('2d');
                    ctx.drawImage(img, 0, 0, width, height);
                    
                    canvas.toBlob(
                        (blob) => resolve(blob),
                        'image/jpeg',
                        this.quality
                    );
                };
                img.onerror = reject;
                img.src = e.target.result;
            };
            reader.onerror = reject;
            reader.readAsDataURL(file);
        });
    }
    
    // 上传到OSS
    async upload(file) {
        try {
            // 1. 压缩图片
            const compressedFile = await this.compressImage(file);
            
            // 2. 获取上传凭证(小请求)
            const token = await this.getUploadToken(
                file.name,
                compressedFile.type
            );
            
            // 3. 直接上传到OSS(大文件,不走服务器)
            const formData = new FormData();
            formData.append('key', token.objectKey);
            formData.append('policy', token.policy);
            formData.append('OSSAccessKeyId', token.accessKeyId);
            formData.append('signature', token.signature);
            formData.append('Content-Type', compressedFile.type);
            formData.append('file', compressedFile);
            
            const response = await fetch(token.host, {
                method: 'POST',
                body: formData
            });
            
            if (!response.ok) {
                throw new Error('上传失败');
            }
            
            // 4. 返回CDN URL(如果配置了CDN)
            return this.getImageUrl(token.objectKey);
            
        } catch (error) {
            console.error('上传失败:', error);
            throw error;
        }
    }
    
    async getUploadToken(fileName, contentType) {
        const response = await fetch('/api/oss/upload-token', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ fileName, contentType })
        });
        return await response.json();
    }
    
    getImageUrl(objectKey) {
        // 如果配置了CDN,返回CDN URL
        const cdnDomain = 'cdn.example.com';
        return `https://${cdnDomain}/${objectKey}`;
    }
}

// 使用
const uploader = new ImageUploader();
const imageUrl = await uploader.upload(file);

成本优化分析

优化前(当前方案)
复制代码
每天流量:45GB
- 手机端 → 应用服务器:45GB(服务器带宽费用)
- 应用服务器 → OSS:45GB(服务器带宽费用)
- 用户访问图片:假设50GB(OSS外网流量费用)

总成本:服务器带宽 + OSS流量费用
优化后(OSS直传 + CDN)
复制代码
每天流量:45GB
- 手机端 → OSS:45GB(OSS内网流量,如果同区域几乎免费)
- 用户访问图片:50GB(CDN流量,通常比OSS外网流量便宜30-50%)

节省:
1. 服务器带宽费用:45GB × 2 = 90GB(完全节省)
2. OSS外网流量费用:50GB(替换为更便宜的CDN流量)

预计节省成本:50-70%(取决于具体定价)

重要澄清:OSS流量费用详解

常见误解:通过SLB上传OSS,就不需要购买OSS流量资源包了?

答案 :❌ 不是的。SLB和OSS流量费用是两个不同的概念。

OSS流量费用构成

OSS的流量费用主要分为以下几种:

  1. 外网上行流量(上传)通常是免费的

    • 从客户端上传文件到OSS
    • 无论是否经过SLB,上传流量都是免费的
    • 例如:安装师傅上传图片到OSS,这部分流量免费
  2. 外网下行流量(下载)需要付费

    • 从OSS下载文件到客户端(用户查看图片)
    • 这是产生OSS流量费用的主要来源
    • 例如:用户访问、查看图片时产生的流量
  3. 内网流量几乎免费

    • 同地域内(如都在华东1-杭州)的流量
    • 如果OSS和应用服务器在同一地域,内网流量几乎免费
  4. 跨区域流量需要付费

    • 不同地域之间的流量传输
SLB的作用

重要理解 :SLB(负载均衡)不会减少OSS的流量费用

复制代码
错误理解:
客户端 → SLB → OSS(以为这样就不收OSS流量费了)

实际情况:
客户端 → OSS(直接上传,不走SLB)
客户端 ← OSS(直接下载,不走SLB)

SLB的真正作用

  • SLB用于API请求的负载均衡(如获取上传凭证的接口)
  • 不用于文件上传/下载的转发
  • 文件上传/下载是客户端直接与OSS通信
正确的架构理解
复制代码
场景1:获取上传凭证(小请求,走SLB)
客户端 → SLB → 应用服务器 → 返回签名
(这个请求很小,几KB,不涉及文件传输)

场景2:上传图片(大文件,直接到OSS)
客户端 → OSS(直接上传,不走SLB,不走应用服务器)
(上传流量免费)

场景3:查看图片(大文件,直接到OSS或CDN)
客户端 ← OSS/CDN(直接下载,不走SLB)
(下载流量收费,这是需要流量资源包的地方)
什么时候需要OSS流量资源包?

需要购买流量资源包的情况

  1. 用户访问图片量大

    • 每天有大量用户查看图片
    • 例如:每天50GB的图片访问量
    • 这种情况下,购买流量资源包比按量付费更便宜
  2. 外网下载流量

    • 用户通过外网访问OSS中的图片
    • 跨地域访问OSS

不需要购买流量资源包的情况

  1. 只有上传,没有下载

    • 如果图片只上传,用户不访问(很少见)
    • 上传流量本身是免费的
  2. 使用CDN加速

    • 如果图片通过CDN访问,流量走CDN,不走OSS外网
    • CDN流量费用通常比OSS外网流量便宜30-50%
成本优化策略

策略1:使用CDN替代OSS外网流量

复制代码
方案A(不推荐):
用户访问图片 → OSS外网 → 用户
流量费用:按OSS外网流量计费(较贵)

方案B(推荐):
用户访问图片 → CDN → OSS(回源)→ CDN → 用户
流量费用:按CDN流量计费(较便宜,通常便宜30-50%)

配置CDN后

  • 首次访问:CDN从OSS回源(产生OSS内网流量,几乎免费)
  • 后续访问:CDN直接返回(不产生OSS流量)
  • 用户流量:走CDN,按CDN流量计费

策略2:购买流量资源包(如果必须用OSS外网)

如果必须使用OSS外网流量(不使用CDN),可以:

  1. 预估流量:根据历史数据预估每月流量

  2. 购买资源包:在阿里云购买OSS流量资源包

  3. 成本对比

    复制代码
    按量付费:0.5元/GB(示例价格,实际以阿里云为准)
    资源包:100GB = 40元(0.4元/GB,更便宜)

策略3:内网访问(同地域)

如果应用服务器和OSS在同一地域:

复制代码
应用服务器(华东1) → OSS(华东1)→ 内网流量(几乎免费)
实际成本对比示例

假设场景:

  • 每天上传:45GB(免费)
  • 每天用户访问:50GB

方案对比

方案 上传流量费用 下载流量费用 总费用(月)
方案1:直接OSS外网 免费 50GB/天 × 30天 × 0.5元/GB = 750元 750元
方案2:OSS + CDN 免费 50GB/天 × 30天 × 0.3元/GB = 450元 450元
方案3:OSS流量资源包 免费 1500GB资源包 ≈ 600元 600元

推荐方案:方案2(OSS + CDN),既省钱又提升访问速度。

总结
  1. SLB不减少OSS流量费用

    • SLB用于API请求负载均衡
    • 文件上传/下载不走SLB
  2. 上传流量免费

    • 无论是否经过SLB,上传到OSS都是免费的
  3. 下载流量需要付费

    • 用户访问图片产生的下载流量需要付费
    • 这是需要流量资源包的地方
  4. 最佳实践

    • 使用CDN加速,降低流量成本
    • 如果必须用OSS外网,考虑购买流量资源包
    • 尽量使用内网访问(同地域)

性能优化建议

1. 批量上传优化

如果一次需要上传多张图片,可以:

javascript 复制代码
// 并发上传(但限制并发数,避免过载)
async function uploadMultiple(files, maxConcurrent = 3) {
    const results = [];
    const queue = [...files];
    
    while (queue.length > 0) {
        const batch = queue.splice(0, maxConcurrent);
        const batchResults = await Promise.all(
            batch.map(file => uploader.upload(file))
        );
        results.push(...batchResults);
    }
    
    return results;
}
2. 断点续传(大文件场景)

如果单张图片很大(>10MB),可以考虑断点续传:

  • 使用OSS的分片上传(Multipart Upload)
  • 前端记录上传进度
  • 失败后可以续传
3. 图片预处理
  • 服务端:使用OSS的图片处理服务自动生成缩略图
  • 客户端:上传前压缩,减少上传时间
4. 监控与告警
java 复制代码
// 添加上传监控
@Component
public class UploadMonitor {
    
    @Autowired
    private MeterRegistry meterRegistry;
    
    public void recordUpload(String userId, long size, long duration) {
        // 记录上传次数
        meterRegistry.counter("upload.count", "user", userId).increment();
        
        // 记录上传大小
        meterRegistry.summary("upload.size", "user", userId).record(size);
        
        // 记录上传耗时
        meterRegistry.timer("upload.duration", "user", userId)
            .record(duration, TimeUnit.MILLISECONDS);
    }
}

总结

核心优化点

  1. OSS直传:图片直接上传到OSS,不经过应用服务器,节省服务器带宽
  2. CDN加速:图片通过CDN分发,提升访问速度,降低流量成本
  3. 7层负载均衡:用于API网关,统一入口,灵活路由
  4. 客户端压缩:上传前压缩图片,减少上传时间和流量

7层负载均衡适用场景

  • ✅ 微服务网关(根据路径路由到不同服务)
  • ✅ 动静分离(静态资源直接返回,不走应用服务器)
  • ✅ 多域名统一入口(根据Host路由)
  • ✅ A/B测试、灰度发布(根据Header/Cookie路由)
  • ✅ SSL终止(在负载均衡层处理HTTPS)

不适用场景

  • ❌ 纯TCP/UDP协议(需要用4层负载均衡)
  • ❌ 超高性能、低延迟场景(4层性能更好)
  • ❌ 简单的IP+端口转发(4层更简单高效)

最终效果

  • 服务器带宽占用:从100-200Mbps降低到几乎为0(只有获取凭证的小请求)
  • 上传速度:提升30-50%(减少一跳,直接到OSS)
  • 成本:节省50-70%(服务器带宽费用 + CDN替代OSS外网流量)
  • 用户体验:上传更快,访问图片更快(CDN加速)
  • 系统稳定性:服务器不再被大文件上传阻塞,其他业务正常

希望这篇文章能帮你解决图片上传的带宽瓶颈问题。如果还有其他问题,欢迎继续讨论!

相关推荐
g***B7389 小时前
Java 工程复杂性的真正来源:从语言设计到现代架构的全链路解析
java·人工智能·架构
serendipity_hky14 小时前
【SpringCloud | 第4篇】Gateway网关统一入口
spring·spring cloud·微服务·gateway
西陵14 小时前
为什么说 AI 赋能前端开发,已经不是选择题,而是必然趋势?
前端·架构·ai编程
国科安芯14 小时前
AS32S601型MCU芯片电源管理(PMU)模块详解
单片机·嵌入式硬件·性能优化·架构·risc-v
Coder_Boy_14 小时前
业务导向型技术日志首日记录(业务中使用的技术栈)
java·驱动开发·微服务
六行神算API-天璇15 小时前
架构思考:大模型作为医疗科研的“智能中间件”
人工智能·中间件·架构·数据挖掘·ar
济南壹软网络科技有限公司16 小时前
企业级盲盒系统:Java高并发架构在多元化抽奖电商中的设计与实践
java·架构·开源源码·盲盒源码·盲盒h5·盲盒app
鹏说大数据17 小时前
数据治理项目实战系列6-数据治理架构设计实战,流程 + 工具双架构拆解
大数据·数据库·架构
一水鉴天17 小时前
整体设计 定稿 之26 重构和改造现有程序结构 之2 (codebuddy)
开发语言·人工智能·重构·架构