sunpengfei
2025-08-13 809cd3966929f4c4f190ed8aa604d137227fe641
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
using Azure;
using Consul;
using Furion;
using Furion.FriendlyException;
using Furion.HttpRemote;
using Microsoft.Extensions.Caching.Distributed;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace FlexJobApi.Core
{
    public class ResourceHttpUtils
    {
        private readonly IDistributedCache distributedCache;
        private readonly IHttpRemoteService httpRemoteService;
        private readonly IConsulClient consulClient;
 
        public ResourceHttpUtils(
            IDistributedCache distributedCache,
            IHttpRemoteService httpRemoteService,
            IConsulClient consulClient)
        {
            this.distributedCache = distributedCache;
            this.httpRemoteService = httpRemoteService;
            this.consulClient = consulClient;
        }
 
        /// <summary>
        /// 发送HTTP请求
        /// </summary>
        /// <typeparam name="TRequest"></typeparam>
        /// <typeparam name="TResponse"></typeparam>
        /// <param name="request"></param>
        /// <param name="provider"></param>
        /// <returns></returns>
        public async Task<TResponse> SendHttpAsync<TRequest, TResponse>(
            TRequest request,
            IResourceHttpProvider provider = null)
            where TRequest : class, new()
        {
            var requestTypeFullName = typeof(TRequest).FullName;
 
            var jsonResourceModels = await distributedCache.GetStringAsync($"ResourceModel|{requestTypeFullName}");
            var resource = jsonResourceModels.JsonTo<ResourceModel>();
            var url = await GetUrl(resource.ServiceName, resource.Route);
            var builder = HttpRequestBuilder.Create(resource.GetHttpMethod(), url);
            if (resource.Method == EnumResourceMethod.Get)
                builder = builder.WithQueryParameters(request);
            else
                builder = builder.SetJsonContent(request);
            provider = provider ?? new DefaultResourceHttpProvider();
            builder = provider.AddAuthentication(builder);
            var response = await provider.SendAsAsync<TResponse>(httpRemoteService, builder);
            return response;
        }
 
        public async Task<string> SendHttpAsync(Resource resource, string request, IResourceHttpProvider provider = null)
        {
            var url = await GetUrl(resource.ServiceName, resource.Route);
            var builder = HttpRequestBuilder.Create(resource.GetHttpMethod(), url);
            if (resource.Method == EnumResourceMethod.Get)
                builder = builder.WithQueryParameters(request);
            else
                builder = builder.SetJsonContent(request);
            provider = provider ?? new DefaultResourceHttpProvider();
            builder = provider.AddAuthentication(builder);
            var response = await provider.SendAsStringAsync(httpRemoteService, builder);
            return response;
        }
 
        public async Task<string> GetUrl(string serviceName, string route)
        {
            var domain = await GetHealthyServiceDomain(serviceName);
            return $"{domain}{route}";
        }
 
        /// <summary>
        /// 获取健康服务域名
        /// </summary>
        /// <param name="serviceName"></param>
        /// <returns></returns>
        public async Task<string> GetHealthyServiceDomain(string serviceName)
        {
            var queryResult = await consulClient.Health.Service(serviceName, null, true);
            if (queryResult.StatusCode != System.Net.HttpStatusCode.OK)
                throw Oops.Oh(EnumErrorCodeType.s404, $"微服务{serviceName}");
 
            var domains = queryResult.Response
                .Select(s => $"http://{s.Service.Address}:{s.Service.Port}")
                .ToList();
            if (domains.IsNull())
                throw Oops.Oh(EnumErrorCodeType.s404, $"微服务{serviceName}");
            // 轮询选择实例
            int randomIndex = new Random().Next(domains.Count);
            return domains[randomIndex];
        }
 
    }
}