-
REST API:使用HTTP协议和RESTful API进行通信,这是一种简单、灵活、易于实现的方式。
-
gRPC:使用Google开发的高性能、跨语言的RPC框架进行通信,支持多种语言和平台。
-
消息队列:使用消息队列进行异步通信,可以提高可靠性和可伸缩性。
-
Service Mesh:使用Service Mesh框架(例如Istio、Linkerd等)进行服务之间的通信和管理,可以提供流量控制、故障恢复、安全性等功能。
分析
- HTTP很容易理解.就是提供api接口供其他服务访问.
- gRPC 不怎么流行
这里着重研究一下消息队列
服务1使用消息队列发送一个请求消息到服务2,并等待响应消息。在发送请求消息时,生成一个唯一的标识符作为消息的一部分,并将这个标识符作为参数传递给ReceiveAsync方法。服务2在处理请求并返回响应消息时,将这个标识符作为响应消息的一部分返回。服务1在发送请求消息后,等待响应消息并返回响应消息的Body作为执行结果
// 服务1
public class Service1
{
private readonly IMessageQueue _messageQueue;
public Service1(IMessageQueue messageQueue)
{
_messageQueue = messageQueue;
}
public async Task<string> CallService2()
{
var correlationId = Guid.NewGuid();
var message = new Message("service2", "get_values", null, correlationId);
await _messageQueue.SendAsync(message);//向服务2 发送请求
var response = await _messageQueue.ReceiveAsync(correlationId);//避免获取到非本地调用的结果
return response.Body.ToString();
}
}
// 服务2
public class Service2 : IMessageHandler
{
public Task<Message> HandleMessageAsync(Message message)
{
if (message.Action == "get_values")
{
var values = new string[] { "value1", "value2" };
var response = new Message(null, null, values, message.CorrelationId);
return Task.FromResult(response);
}
else
{
throw new InvalidOperationException("Invalid action.");
}
}
}
// 控制器
[ApiController]
[Route("[controller]")]
public class MyController : ControllerBase
{
private readonly Service1 _service1;
public MyController(Service1 service1)
{
_service1 = service1;
}
[HttpGet]
public async Task<IActionResult> Get()
{
var result = await _service1.CallService2();
return Ok(result);
}
}
// 启动类
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddControllers();
services.AddSingleton<Service1>();
services.AddSingleton<Service2>();
services.AddSingleton<IMessageQueue>(new RabbitMQMessageQueue("amqp://guest:guest@localhost:5672"));
services.AddSingleton<IMessageHandlerRegistry>(provider =>
{
var registry = new MessageHandlerRegistry();
registry.Register("service2", provider.GetService<Service2>());
return registry;
});
services.AddHostedService<MessageQueueListener>();
});
public class MessageQueueListener : BackgroundService
{
private readonly IMessageQueue _messageQueue;
private readonly IMessageHandlerRegistry _messageHandlerRegistry;
private readonly Dictionary<Guid, TaskCompletionSource<Message>> _callbacks;
public MessageQueueListener(IMessageQueue messageQueue, IMessageHandlerRegistry messageHandlerRegistry)
{
_messageQueue = messageQueue;
_messageHandlerRegistry = messageHandlerRegistry;
_callbacks = new Dictionary<Guid, TaskCompletionSource<Message>>();
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
var message = await _messageQueue.ReceiveAsync();
if (message.CorrelationId != null)
{
if (_callbacks.TryGetValue(message.CorrelationId.Value, out var callback))
{
callback.SetResult(message);
}
}
else
{
var handler = _messageHandlerRegistry.GetHandler(message);
var response = await handler.HandleMessageAsync(message);
await _messageQueue.SendAsync(response);
}
}
}
public async Task<Message> SendAndReceiveAsync(Message message)
{
var correlationId = Guid.NewGuid();
var callback = new TaskCompletionSource<Message>();
_callbacks[correlationId] = callback;
message.CorrelationId = correlationId;
await _messageQueue.SendAsync(message);
var response = await callback.Task;
_callbacks.Remove(correlationId);
return response;
}
}
}