前后端分离项目部署完成后 前后端交互过程

模拟环境概述:

后端:Visual Studio 、 .Net 6 、 WebApi

前端:Visual Studio Code 、 Vue:"^2.6.14" 、 vue/cli-service: "^3.0.3"、

后端部署到IIS + 前端部署到Nginx

完整交互流程

阶段1:用户访问网站

用户在浏览器输入: https://www.myapp.com

发生的过程:

复制代码
1. DNS解析: www.myapp.com → 120.120.120.120 (你的服务器IP)
2. TCP连接: 浏览器与服务器建立SSL加密连接
3. HTTP请求: GET https://www.myapp.com/

阶段2:CDN和负载均衡处理

nginx

复制代码
# 负载均衡器 (如Nginx/HAProxy/F5)
upstream frontend_servers {
    server 192.168.1.10:80 weight=3;
    server 192.168.1.11:80 weight=2;
    server 192.168.1.12:80 weight=2;
}

server {
    listen 443 ssl;
    server_name www.myapp.com;
    
    # SSL证书处理
    ssl_certificate /path/to/cert.crt;
    ssl_certificate_key /path/to/private.key;
    
    location / {
        proxy_pass http://frontend_servers;
    }
}

CDN的工作:

  • 静态资源(JS/CSS/图片)从离用户最近的CDN节点返回

  • 动态请求(API调用)转发到源站

阶段3:前端服务器响应

Nginx接收到请求后:

nginx

复制代码
# 前端Nginx服务器配置
server {
    listen 80;
    server_name www.myapp.com;
    root /var/www/html;
    
    # 静态文件缓存
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|woff2)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        add_header Vary Accept-Encoding;
    }
    
    # API请求代理到后端
    location /api/ {
        proxy_pass http://backend_servers;
        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;
    }
    
    # SPA路由支持
    location / {
        try_files $uri $uri/ /index.html;
    }
}

前端服务器返回:

html

复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>我的应用</title>
    <!-- 这些资源可能来自CDN -->
    <link href="/css/app.a1b2c3d4.css" rel="stylesheet">
    <script src="/js/chunk-vendors.e5f6g7h8.js"></script>
</head>
<body>
    <div id="app"></div>
    <script src="/js/app.i9j0k1l2.js"></script>
</body>
</html>

阶段4:浏览器执行Vue应用

浏览器加载过程:

javascript

复制代码
// 1. 解析HTML,构建DOM树
// 2. 加载并执行Vue应用
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

// 3. Vue应用启动,调用初始化API

阶段5:Vue应用调用后端API(核心交互)

假设用户需要加载数据:

javascript

复制代码
// Vue组件中的代码
export default {
  data() {
    return {
      users: [],
      loading: false
    }
  },
  async mounted() {
    await this.loadUsers()
  },
  methods: {
    async loadUsers() {
      this.loading = true
      try {
        // 调用部署的后端API
        const response = await fetch('/api/users', {
          method: 'GET',
          headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer ' + this.$store.state.token
          }
        })
        
        if (!response.ok) throw new Error('API请求失败')
        
        this.users = await response.json()
      } catch (error) {
        console.error('加载用户失败:', error)
        this.$notify.error('数据加载失败')
      } finally {
        this.loading = false
      }
    }
  }
}

阶段6:请求到达后端基础设施

负载均衡到后端服务器:

nginx

复制代码
# 后端负载均衡配置
upstream backend_servers {
    server 192.168.10.10:5000 weight=2;
    server 192.168.10.11:5000 weight=2;
    server 192.168.10.12:5000 weight=1;
}

server {
    listen 80;
    server_name api.myapp.com;
    
    location / {
        proxy_pass http://backend_servers;
        # 重要:传递原始客户端信息
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

阶段7:IIS接收并处理请求

IIS + ASP.NET Core架构:

复制代码
请求 → IIS (80端口) → AspNetCoreModule → Kestrel (5000端口) → 你的.NET应用

IIS的web.config配置:

xml

复制代码
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <handlers>
      <add name="aspNetCore" path="*" verb="*" 
           modules="AspNetCoreModuleV2" resourceType="Unspecified" />
    </handlers>
    <aspNetCore processPath="dotnet" 
                arguments=".\MyWebApi.dll" 
                stdoutLogEnabled="true"
                stdoutLogFile=".\logs\stdout"
                hostingModel="inprocess">
      <environmentVariables>
        <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Production" />
        <environmentVariable name="CONNECTION_STRINGS__DEFAULT" 
                             value="Server=db.myapp.com;Database=myapp;User Id=appuser;" />
      </environmentVariables>
    </aspNetCore>
  </system.webServer>
</configuration>

阶段8:.NET应用处理请求

你的Controller执行:

cs 复制代码
[ApiController]
[Route("api/[controller]")]
[Authorize]  // 生产环境需要认证
public class UsersController : ControllerBase
{
    private readonly IUserService _userService;
    private readonly ILogger<UsersController> _logger;

    public UsersController(IUserService userService, ILogger<UsersController> logger)
    {
        _userService = userService;
        _logger = logger;
    }

    [HttpGet]
    public async Task<IActionResult> GetUsers()
    {
        try
        {
            // 生产环境的日志记录
            _logger.LogInformation("开始获取用户列表");
            
            // 从数据库获取数据
            var users = await _userService.GetAllUsersAsync();
            
            // 生产环境可能包含缓存
            var cacheKey = "all_users";
            if (!_memoryCache.TryGetValue(cacheKey, out List<UserDto> cachedUsers))
            {
                cachedUsers = await _userService.GetAllUsersAsync();
                _memoryCache.Set(cacheKey, cachedUsers, 
                    TimeSpan.FromMinutes(30)); // 缓存30分钟
            }
            
            _logger.LogInformation("成功获取 {Count} 个用户", users.Count);
            
            return Ok(users);
        }
        catch (Exception ex)
        {
            // 生产环境的错误处理
            _logger.LogError(ex, "获取用户列表时发生错误");
            return StatusCode(500, new { 
                error = "服务器内部错误",
                requestId = HttpContext.TraceIdentifier 
            });
        }
    }
}

阶段9:数据库交互

Entity Framework Core执行:

cs 复制代码
public class UserService : IUserService
{
    private readonly ApplicationDbContext _context;

    public async Task<List<UserDto>> GetAllUsersAsync()
    {
        // 生产环境:使用异步、分页、性能优化
        return await _context.Users
            .AsNoTracking()  // 只读查询优化
            .Where(u => u.IsActive)
            .OrderBy(u => u.Name)
            .Select(u => new UserDto
            {
                Id = u.Id,
                Name = u.Name,
                Email = u.Email,
                CreatedAt = u.CreatedAt
            })
            .ToListAsync();
    }
}

阶段10:响应返回路径

数据返回流程:

复制代码
数据库 → Entity Framework → UserService → UsersController 
    → Kestrel → IIS → 负载均衡器 → 前端Nginx → 浏览器

HTTP响应示例:

http

复制代码
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 285
Cache-Control: no-cache
Server: Kestrel
Request-Id: |a1b2c3d4.
Date: Fri, 20 Oct 2023 08:00:00 GMT

{
  "data": [
    {
      "id": 1,
      "name": "张三",
      "email": "zhangsan@example.com",
      "createdAt": "2023-10-01T00:00:00Z"
    },
    {
      "id": 2, 
      "name": "李四",
      "email": "lisi@example.com",
      "createdAt": "2023-10-02T00:00:00Z"
    }
  ],
  "totalCount": 2,
  "page": 1,
  "pageSize": 20
}

阶段11:浏览器接收并更新界面

Vue应用处理响应:

javascript

复制代码
// 浏览器接收到响应后
response.json().then(users => {
    // 更新Vuex状态管理
    this.$store.commit('SET_USERS', users.data)
    
    // 更新组件数据
    this.users = users.data
    
    // 隐藏加载状态
    this.loading = false
    
    // 可能触发其他依赖用户数据的组件更新
})

生产环境的特殊考虑

1. 安全机制

cs 复制代码
// CORS配置(生产环境更严格)
services.AddCors(options =>
{
    options.AddPolicy("ProductionPolicy", policy =>
    {
        policy.WithOrigins("https://www.myapp.com") // 只允许生产域名
              .AllowAnyHeader()
              .AllowAnyMethod()
              .AllowCredentials();
    });
});

2. 性能优化

nginx

复制代码
# 后端API缓存
location /api/ {
    proxy_pass http://backend_servers;
    
    # API响应缓存
    proxy_cache api_cache;
    proxy_cache_valid 200 302 5m;  # 成功响应缓存5分钟
    proxy_cache_valid 404 1m;      # 404缓存1分钟
    add_header X-Cache-Status $upstream_cache_status;
}

3. 监控和日志

cs 复制代码
// 结构化日志
logger.LogInformation("API请求 {@RequestInfo}", new {
    Path = HttpContext.Request.Path,
    Method = HttpContext.Request.Method,
    UserAgent = HttpContext.Request.Headers["User-Agent"],
    ResponseTime = stopwatch.ElapsedMilliseconds
});

📊 完整流程总结

text

复制代码
用户操作
    ↓
浏览器发起请求
    ↓
CDN加速/负载均衡
    ↓
前端Nginx服务器
    ↓ 静态资源直接返回
    ↓ API请求转发
后端负载均衡器
    ↓
IIS服务器
    ↓
AspNetCoreModule
    ↓
Kestrel + .NET 6应用
    ↓
业务逻辑 + 数据库操作
    ↓
生成JSON响应
    ↓ 沿原路返回
浏览器接收数据
    ↓
Vue更新界面
    ↓
用户看到结果
相关推荐
LuckySusu5 小时前
【vue篇】Vue 自定义指令完全指南:从入门到高级实战
前端·vue.js
LuckySusu5 小时前
【vue篇】Vue 响应式核心:依赖收集机制深度解密
前端·vue.js
LuckySusu5 小时前
【vue篇】Vue.js 2025:为何全球开发者都在拥抱这个前端框架?
前端·vue.js
LuckySusu5 小时前
【vue篇】Vue 单向数据流铁律:子组件为何不能直接修改父组件数据?
前端·vue.js
LuckySusu5 小时前
【vue篇】React vs Vue:2025 前端双雄终极对比
前端·vue.js
玩代码6 小时前
vue项目安装chromedriver超时解决办法
前端·javascript·vue.js
计算机毕业设计木哥7 小时前
计算机毕业设计选题推荐:基于SpringBoot和Vue的快递物流仓库管理系统【源码+文档+调试】
java·vue.js·spring boot·后端·课程设计
Wx-bishekaifayuan8 小时前
基于微信小程序的社区图书共享平台设计与实现 计算机毕业设计源码44991
javascript·vue.js·windows·mysql·pycharm·tomcat·php
九十一10 小时前
vue3事件总线与emit
前端·vue.js