作为一名全栈开发人员,我最近在 .NET Core 项目中完成了从 Redis 过渡到内存缓存的过程。这种转变的驱动力是需要简化我们的架构并提高特定方案的性能。在本文中,我将指导你完成此迁移的步骤,提供编码做法,并演示在微服务体系结构中使用 .NET Core 后端和 TypeScript 前端的实际方案。
为什么要迁移到内存中缓存?
虽然 Redis 是一种强大的缓存解决方案,但内存中缓存在某些情况下可以提供优势,例如:
单纯: 通过消除对单独缓存服务器的需求,降低了基础架构的复杂性。
性能: 更快的访问时间,因为数据直接存储在应用程序的内存中。
成本: 通过消除维护和扩展 Redis 实例的需要来降低运营成本。
分步迁移
1. 调整架构
我们的架构基本保持不变,只是我们用内存缓存替换了 Redis:
用户服务: 处理与用户相关的操作。
功能服务: 管理新的缓存功能及其逻辑。
API网关: 将请求路由到相应的服务。
前端应用: 与后端服务交互。
内存中缓存: 充当缓存层。
2. 在 .NET Core 中设置内存中缓存
添加必要的软件包
请确保 .NET Core 项目中具有所需的包。
dotnet add package Microsoft.Extensions.Caching.Memory
配置 In-Memory 缓存
在文件中配置内存中缓存。Startup.cs
// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddMemoryCache();
services.AddScoped<IFeatureService, FeatureService>();
services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddControllers();
}
在服务中实现缓存
更新服务以使用内存中缓存。
// FeatureService.cs
public class FeatureService : IFeatureService
{
private readonly AppDbContext _context;
private readonly IMemoryCache _cache;
public FeatureService(AppDbContext context, IMemoryCache cache)
{
_context = context;
_cache = cache;
}
public async Task<FeatureResponse> ProcessFeatureAsync(FeatureRequest request)
{
var cacheKey = $"Feature-{request.Input}";
if (_cache.TryGetValue(cacheKey, out FeatureResponse cachedData))
{
return cachedData;
}
// Simulate processing
var result = new FeatureResponse
{
Success = true,
Message = "Feature processed successfully"
};
_cache.Set(cacheKey, result, new MemoryCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5)
});
return result;
}
}
设置控制器
// FeatureController.cs
[ApiController]
[Route("api/[controller]")]
public class FeatureController : ControllerBase
{
private readonly IFeatureService _featureService;
public FeatureController(IFeatureService featureService)
{
_featureService = featureService;
}
[HttpPost]
public async Task<IActionResult> ProcessFeature([FromBody] FeatureRequest request)
{
var response = await _featureService.ProcessFeatureAsync(request);
return Ok(response);
}
}
3. 开发前端
我们继续使用带有 TypeScript 的 React 作为前端应用程序。
设置 API 服务
// apiService.ts
import axios from 'axios';
export const processFeature = async (data: FeatureRequest) => {
try {
const response = await axios.post<FeatureResponse>('/api/feature', data);
return response.data;
} catch (error) {
throw new Error('Failed to process feature');
}
};
创建 React 组件
// FeatureComponent.tsx
import React, { useState } from 'react';
import { processFeature } from './apiService';
const FeatureComponent: React.FC = () => {
const [input, setInput] = useState('');
const [message, setMessage] = useState('');
const handleSubmit = async (event: React.FormEvent) => {
event.preventDefault();
try {
const response = await processFeature({ input });
setMessage(response.message);
} catch (error) {
setMessage('Error processing feature');
}
};
return (
<div>
<form onSubmit={handleSubmit}>
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
/>
<button type="submit">Submit</button>
</form>
{message && <p>{message}</p>}
</div>
);
};
export default FeatureComponent;
创建 React 组件
// FeatureComponent.tsx
import React, { useState } from 'react';
import { processFeature } from './apiService';
const FeatureComponent: React.FC = () => {
const [input, setInput] = useState('');
const [message, setMessage] = useState('');
const handleSubmit = async (event: React.FormEvent) => {
event.preventDefault();
try {
const response = await processFeature({ input });
setMessage(response.message);
} catch (error) {
setMessage('Error processing feature');
}
};
return (
<div>
<form onSubmit={handleSubmit}>
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
/>
<button type="submit">Submit</button>
</form>
{message && <p>{message}</p>}
</div>
);
};
export default FeatureComponent;
4. 测试和部署
在实现内存中缓存后,我们进行了彻底的测试:
单元测试: 确保各个组件按预期工作。
集成测试: 验证服务之间的交互。
性能测试: 衡量内存中缓存对响应时间的影响。
用户验收测试 (UAT): 让真实用户参与验证解决方案。
最后,我们分阶段部署了新的缓存机制,从有限的 beta 版本开始。
编码实践和真实世界场景
以下是一些基于我们的迁移经验的编码实践和示例:
在 .NET Core 中使用依赖项注入Using Dependency Injection in .NET Core
依赖关系注入 (DI) 有助于管理依赖关系并促进干净的架构。
public void ConfigureServices(IServiceCollection services)
{
services.AddMemoryCache();
services.AddScoped<IFeatureService, FeatureService>();
services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddControllers();
}
在 TypeScript 中处理 API 请求
使用 Axios 处理 API 请求提供了一种干净简单的方法来处理 HTTP 请求。
import axios from 'axios';
interface FeatureRequest {
input: string;
}
interface FeatureResponse {
success: boolean;
message: string;
}
export const processFeature = async (data: FeatureRequest): Promise<FeatureResponse> => {
try {
const response = await axios.post<FeatureResponse>('/api/feature', data);
return response.data;
} catch (error) {
throw new Error('Failed to process feature');
}
};
React 中的状态管理
使用钩子管理功能组件中的状态。
const FeatureComponent: React.FC = () => {
const [input, setInput] = useState('');
const [message, setMessage] = useState('');
const handleSubmit = async (event: React.FormEvent) => {
event.preventDefault();
try {
const response = await processFeature({ input });
setMessage(response.message);
} catch (error) {
setMessage('Error processing feature');
}
};
return (
<div>
<form onSubmit={handleSubmit}>
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
/>
<button type="submit">Submit</button>
</form>
{message && <p>{message}</p>}
</div>
);
};
在我们的 .NET Core 项目中从 Redis 迁移到内存中缓存简化了我们的架构,并提高了特定用例的性能。这一旅程强化了结构良好的开发方法和现代编码实践的重要性。通过将 .NET Core 用于后端,将 TypeScript 用于前端,我们创建了一个可靠且可缩放的解决方案,可有效满足用户的需求。
如果你喜欢我的文章,请给我一个赞!谢谢