模拟环境概述:
后端: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更新界面
↓
用户看到结果