.net 微服务实现服务和服务直接的调用

  1. REST API:使用HTTP协议和RESTful API进行通信,这是一种简单、灵活、易于实现的方式。

  2. gRPC:使用Google开发的高性能、跨语言的RPC框架进行通信,支持多种语言和平台。

  3. 消息队列:使用消息队列进行异步通信,可以提高可靠性和可伸缩性。

  4. Service Mesh:使用Service Mesh框架(例如Istio、Linkerd等)进行服务之间的通信和管理,可以提供流量控制、故障恢复、安全性等功能。

分析

  1. HTTP很容易理解.就是提供api接口供其他服务访问.
  2. 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;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值