• 【无标题】


    微服务搭建流程,无任何技术含量,记作个人学习笔记。

    1.首先下载consul  

    Install | Consul | HashiCorp Developer

    解压下载consul得压缩包,解压,到consul得根目录,在consul得根目录运行cmd,执行consul agent -dev 启动consul

    打开consul得ui  localhost:8500

    2.创建项目,创建一个.net core web api项目和一个web mvc项目

    首先Api端服务实例启动时需到Consul中进行服务注册,Web Client直接与Consul进行连接,从Consul中拿到服务实例并配置策略及发送http请求等。

     

     Consul每隔一段时间就会调用一次注册的服务实例进行健康检查。

    在Api项目中新建一个IConfiguration的扩展方法:

    1. public static void ConsulExtend(this IConfiguration configuration)
    2. {
    3. ConsulClient client = new ConsulClient(m =>
    4. {
    5. m.Address = new Uri("http://localhost:8500/");
    6. m.Datacenter = "dc1";
    7. });
    8. //启动的时候在consul中注册实例服务
    9. //在consul中注册的ip,port
    10. string ip = configuration["ip"];
    11. int port = int.Parse(configuration["port"]);
    12. int weight = string.IsNullOrWhiteSpace(configuration["weight"]) ? 1 : int.Parse(configuration["weight"]);
    13. client.Agent.ServiceRegister(new AgentServiceRegistration()
    14. {
    15. ID = "service" + Guid.NewGuid(),//唯一的
    16. Name = "MicroserviceAttempt",//组(服务)名称
    17. Address = ip,
    18. Port = port,//不同的端口=>不同的实例
    19. Tags = new string[] { weight.ToString() },//标签
    20. Check = new AgentServiceCheck()//服务健康检查
    21. {
    22. Interval = TimeSpan.FromSeconds(12),//间隔12s一次 检查
    23. HTTP = $"http://{ip}:{port}/Api/Health/Index",
    24. Timeout = TimeSpan.FromSeconds(5),//检测等待时间
    25. DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(20)//失败后多久移除
    26. }
    27. });
    28. Console.WriteLine($"{ip}:{port}--weight:{weight}");
    29. }

     心跳接口

    1. [ApiController]
    2. [Route("api/[controller]/[action]")]
    3. public class HealthController : Controller
    4. {
    5. readonly IConfiguration _configuration;
    6. public HealthController(IConfiguration configuration)
    7. {
    8. _configuration = configuration;
    9. }
    10. [HttpGet]
    11. public IActionResult Index()
    12. {
    13. //心跳,consul会每隔几秒调一次
    14. Console.WriteLine($"{ _configuration["port"]} Invoke");
    15. return Ok();
    16. }
    17. }

    调用方法

     builder.Services.AddControllers();

     注册服务

    dotnet Service1.dll --urls="http://*:5726" --ip="127.0.0.1" --port=5726
    dotnet Service1.dll --urls="http://*:5727" --ip="127.0.0.1" --port=5727
    dotnet Service1.dll --urls="http://*:5728" --ip="127.0.0.1" --port=5728

     客户端调用

    1. public class UserController : Controller
    2. {
    3. HttpSender _httpSender;
    4. public UserController()
    5. {
    6. }
    7. //暂不考虑线程安全
    8. private static int index = 0;
    9. public async Task Index()
    10. {
    11. #region nginx版 只知道nginx地址就行了
    12. //var str = await _httpSender.InvokeApi("http://localhost:8088/api/User/GetCustomerUser");
    13. #endregion
    14. #region consul
    15. //new一个consul实例
    16. ConsulClient client = new ConsulClient(m =>
    17. {
    18. new Uri("http://localhost:8500/");
    19. m.Datacenter = "dc1";
    20. });
    21. //与consul进行通信(连接),得到consul中所有的服务实例
    22. var response = client.Agent.Services().Result.Response;
    23. string url = "http://MicroserviceAttempt/Api/Health/Index";
    24. Uri uri = new Uri(url);
    25. string groupName = uri.Host;
    26. AgentService agentService = null;//服务实例
    27. var serviceDictionary = response.Where(m => m.Value.Service.Equals(groupName, StringComparison.OrdinalIgnoreCase)).ToArray();//找到的全部服务实例
    28. //{
    29. // agentService = serviceDictionary[0].Value;
    30. //}
    31. {
    32. //轮询策略=>达到负载均衡的目的
    33. agentService = serviceDictionary[index++ % 3].Value;
    34. }
    35. {
    36. //平均策略(随机获取索引--相对平均)=>达到负载均衡的目的
    37. agentService = serviceDictionary[new Random(index++).Next(0, serviceDictionary.Length)].Value;
    38. }
    39. {
    40. //权重策略,给不同的实例分配不同的压力,注册时提供权重
    41. Liststring, AgentService>> keyValuePairs = new Liststring, AgentService>>();
    42. foreach (var item in keyValuePairs)
    43. {
    44. int count = int.Parse(item.Value.Tags?[0]);//在服务注册的时候给定权重数量
    45. for (int i = 0; i < count; i++)
    46. {
    47. keyValuePairs.Add(item);
    48. }
    49. }
    50. //agentService = keyValuePairs.ToArray()[0].Value;
    51. }
    52. url = $"{uri.Scheme}://{agentService.Address}:{agentService.Port}{uri.PathAndQuery}";
    53. _httpSender = new HttpSender();
    54. string content = await _httpSender.InvokeApi(url);
    55. #endregion
    56. return Ok(content);
    57. }
    58. }
    1. public async Task<string> InvokeApi(string url)
    2. {
    3. using (HttpClient client = new HttpClient())
    4. {
    5. HttpRequestMessage message = new HttpRequestMessage();
    6. message.Method = HttpMethod.Get;
    7. message.RequestUri = new Uri(url);
    8. var result = client.SendAsync(message).Result;
    9. string content = result.Content.ReadAsStringAsync().Result;
    10. return content;
    11. }
    12. }

     启动这个web项目,访问User /Index    就可以读取服务得结果了

    但是这样做不好,客户端都需要和Consul进行连接,拿到所有的服务实例,直接和服务实例进行交互,服务实例就暴露了--所以需要网关。

    网关将服务实例与客户端进行隔离,是所有Api请求的入口。因此可以统一鉴权。当然微服务网关的作用有很多,大家可自行百度了解。

    新建一个网关的项目,请求先到达网关,再由网关分发请求到不同的实例。如图:

     创建一个网关服务OceletDemo引用NuGet包:Ocelot、Ocelot.Provider.Consul

    1. private static void Main(string[] args)
    2. {
    3. var builder = WebApplication.CreateBuilder(args);
    4. builder.Host.ConfigureAppConfiguration(conf =>
    5. {
    6. conf.AddJsonFile("appsettings.json", optional: false,
    7. reloadOnChange: true);
    8. });
    9. // Add services to the container.
    10. // builder.Services.AddControllers();
    11. builder.Services.AddOcelot().AddConsul();
    12. // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
    13. // builder.Services.AddEndpointsApiExplorer();
    14. // builder.Services.AddSwaggerGen();
    15. var app = builder.Build();
    16. app.UseOcelot();
    17. app.Run();
    18. // Configure the HTTP request pipeline.
    19. // if (app.Environment.IsDevelopment())
    20. //{
    21. // app.UseSwagger();
    22. /// app.UseSwaggerUI();
    23. // }
    24. // app.UseAuthorization();
    25. // app.MapControllers();
    26. }

     

    1. {
    2. "Logging": {
    3. "LogLevel": {
    4. "Default": "Information",
    5. "Microsoft.AspNetCore": "Warning"
    6. }
    7. },
    8. "Routes": [
    9. {
    10. //GeteWay转发=>Downstream
    11. "DownstreamPathTemplate": "/api/{url}", //服务地址--url变量
    12. "DownstreamScheme": "http",
    13. //http://localhost:6299/T5/User/GetCustomerUser
    14. "UpstreamPathTemplate": "/T5/{url}", //网关地址--url变量 冲突的还可以加权重Priority
    15. "UpstreamHttpMethod": [ "Get", "Post" ],
    16. "UseServiceDiscovery": true, //使用服务发现
    17. "ServiceName": "MicroserviceAttempt", //Consul服务名称
    18. "LoadBalancerOptions": {
    19. "Type": "RoundRobin" //轮询 //"LeastConnection":最少连接数服务器 "NoloadBalance":不负载均衡 "CookieStickySession":会话粘滞
    20. }
    21. }
    22. ],
    23. "GlobalConfiguration": {
    24. "BaseUrl": "http://127.0.0.1:6299",
    25. "ServiceDiscoveryProvider": {
    26. "Host": "127.0.0.1",
    27. "Port": 8500,
    28. "Type": "Consul" //由Consul提供服务发现,每次请求去Consul
    29. }
    30. },
    31. "AllowedHosts": "*"
    32. }

    运行网关服务

    dotnet OceletDemo.dll --urls="http://*:6299" --ip="127.0.0.1" --port=6299

     调用:127.0.0.1:6299/T5/Health/Index

    到此微服务就算搭建好了,至于服务治理什么的,个人感觉这些东西需要实践,仅靠demo成不了事的

  • 相关阅读:
    程序员怎样才能学好算法,推荐好书送给大家
    基于CRC64的通用哈希表(HashMap)的实现(使用golang)
    总结git常用命令
    RxJS 实做: 自定义 operator - switchMapBy
    手写验证码(附代码)
    JS 之 常用内置类的使用
    RNA-seq——四、根据序列比对结果筛选差异基因
    图扑数字孪生智慧加油站,构建安全防护网
    怎么使用 Flink 向 Apache Doris 表中写 Bitmap 类型的数据
    怎么写好宣传稿件?纯干货
  • 原文地址:https://blog.csdn.net/qq_40098572/article/details/127554686