一、微服务架构为什么需要服务发现
想象一下,你管理着一个大型超市,里面有上百个货架(服务)。顾客(请求)需要快速找到商品(服务实例),如果每次都要问管理员(硬编码IP),效率会很低。这就是微服务架构面临的实际问题——服务发现。
在.NET Core微服务中,服务可能动态扩缩容,IP地址也会变化。我们需要一个"超市导购系统"来自动维护服务地址清单。常见方案有:
- 客户端直接查询服务注册中心(如Consul)
- 通过网关统一路由(如Ocelot)
- 服务间使用DNS轮询
// 示例技术栈:.NET Core + Consul
// 服务注册示例
public void Configure(IApplicationBuilder app)
{
var consulClient = new ConsulClient();
var registration = new AgentServiceRegistration()
{
ID = "OrderService-1", // 服务唯一标识
Name = "OrderService", // 服务组名称
Address = "localhost", // 服务实例地址
Port = 5000, // 服务端口
Check = new AgentCheckRegistration() // 健康检查
{
HTTP = "http://localhost:5000/health",
Interval = TimeSpan.FromSeconds(10)
}
};
consulClient.Agent.ServiceRegister(registration); // 注册到Consul
}
二、服务通信的三种经典模式
2.1 同步通信(HTTP/RPC)
就像打电话,必须等待对方接听。适合需要立即响应的场景:
// 使用HttpClient调用其他服务
[HttpGet]
public async Task<Order> GetOrder(int id)
{
// 从Consul发现用户服务地址
var serviceUrl = await _consulClient.GetServiceUrl("UserService");
// 发起同步调用
using var httpClient = new HttpClient();
var user = await httpClient.GetFromJsonAsync<User>($"{serviceUrl}/users/{order.UserId}");
return new Order { ..., User = user };
}
2.2 异步通信(消息队列)
类似发短信,发完就可以干别的事。适合耗时操作:
// 使用RabbitMQ发送订单创建事件
public void CreateOrder(Order order)
{
_orderRepository.Add(order);
// 不需要等待处理结果
_rabbitMQ.Publish("order.created", new {
OrderId = order.Id,
TotalAmount = order.Total
});
}
2.3 混合模式(gRPC流式)
像视频通话,可以持续双向通信。适合实时数据推送:
// gRPC协议定义
service OrderTracking {
rpc TrackOrders (stream TrackingRequest) returns (stream PositionUpdate);
}
三、实战中的五个避坑指南
3.1 超时控制
网络不可靠,必须设置超时:
// 配置HttpClient超时
var httpClient = new HttpClient
{
Timeout = TimeSpan.FromSeconds(3) // 超过3秒视为失败
};
3.2 熔断机制
当服务连续失败时,快速失败避免雪崩:
// 使用Polly实现熔断
var policy = Policy<HttpResponseMessage>
.Handle<HttpRequestException>()
.CircuitBreakerAsync(
exceptionsAllowedBeforeBreaking: 3,
durationOfBreak: TimeSpan.FromSeconds(30)
);
3.3 负载均衡
避免所有请求都打到同一个实例:
// 使用随机负载均衡策略
var instances = await _consulClient.GetServiceInstances("PaymentService");
var randomInstance = instances.OrderBy(x => Guid.NewGuid()).First();
3.4 版本兼容
服务升级时要考虑兼容性:
// API版本控制
[ApiVersion("1.0")]
[Route("v{version:apiVersion}/orders")]
public class OrdersController : ControllerBase
3.5 安全通信
内部服务也要加密:
// 配置HTTPS证书
services.AddHttpClient("secure-client")
.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
{
ClientCertificateOptions = ClientCertificateOption.Automatic
});
四、完整示例:电商订单流程
让我们用一个电商场景串联所有知识点:
// 订单服务完整示例
public class OrderService
{
private readonly IConsulClient _consul;
private readonly IMessageBus _bus;
public async Task ProcessOrder(Order order)
{
// 1. 验证用户(同步HTTP)
var userServiceUrl = await _consul.GetServiceUrl("UserService");
var user = await _httpClient.GetAsync<User>($"{userServiceUrl}/{order.UserId}");
if (!user.IsActive) throw new Exception("用户无效");
// 2. 扣减库存(异步消息)
_bus.Publish("inventory.lock", new {
OrderId = order.Id,
Items = order.Items
});
// 3. 支付处理(gRPC流式)
using var paymentChannel = GrpcChannel.ForAddress(
await _consul.GetServiceUrl("PaymentService"));
var paymentClient = new PaymentGateway.PaymentGatewayClient(paymentChannel);
using var call = paymentClient.ProcessPayment();
await call.RequestStream.WriteAsync(new PaymentRequest { ... });
await call.RequestStream.CompleteAsync();
// 4. 更新订单状态
await _dbContext.SaveChangesAsync();
}
}
五、技术选型建议
5.1 轻量级场景
- 服务发现:Consul/Eureka
- 通信:HTTP + JSON
5.2 高性能场景
- 服务发现:Kubernetes Service
- 通信:gRPC/protobuf
5.3 复杂系统
- 服务网格:Linkerd/Istio
- 通信:混合模式
六、总结
微服务通信就像城市交通系统:服务发现是GPS导航,同步通信是公交,异步通信是快递,而流式通信则是地铁。选择合适的方式需要考虑:
- 响应速度要求
- 系统容错能力
- 开发维护成本
- 团队技术储备
记住没有银弹,最适合的才是最好的解决方案。
评论