本系列编写目的纯属个人开发记录  以下代码均为demo级 如有需要 请自行优化 代码完整包由于公司电脑加密 无法上传整包的demo文件

consul 开发环境简易处理

consul 下载地址 : https://www.consul.io/downloads.html

此处使用windows 64版本

为方便使用在创建一个bat文件 命令如下:

cd C:\Users\Lenovo\Desktop\    
consul.exe agent -dev

第一行为进入桌面

第二行为 执行consul开发模式

运行后可在 localhost:8500 地址处看到consul 后台服务管理页面

搭建测试API

由于 使用了consul 最新nuget包 所以 在创建的时候需要使用 .netcore 2.1

由于已经搭建了demo1 这里演示截图会是demo2 创建方式一样

创建一个core 2.1的API空项目

创建一个BaseController 用来保存配置信息

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options; namespace DemoApi_I.Controllers
{
public class BaseController : ControllerBase
{
public static Setting Config;
public BaseController(IOptions<Setting> setting)
{
Config = setting.Value;
}
}
}

BaseController

再添加一个健康检查的控制器

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options; namespace DemoApi_II.Controllers
{
[Route("api/[controller]")]
public class HealthController : BaseController
{
public HealthController(IOptions<Setting> setting) : base(setting)
{
} // GET api/values
[HttpGet]
public string Get()
{
return "ok";
}
}
}

HealthController.cs

为了统一显示 可以更改默认values控制器为

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options; namespace DemoApi_II.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ValuesController : BaseController
{
public ValuesController(IOptions<Setting> setting) : base(setting)
{
}
// GET api/values
[HttpGet]
public string Get()
{
var aaa = Config.ServiceName;
return "二号测试API";
}
}
}

ValuesController

接下来 增加 一个配置类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; namespace DemoApi_II
{
public class Setting
{
/// <summary>
/// 端口号
/// </summary>
public int Port { get; set; }
/// <summary>
/// 服务名称
/// </summary>
public string ServiceName { get; set; }
/// <summary>
/// 服务发现IP
/// </summary>
public string ConsulIP { get; set; }
/// <summary>
/// 服务发现端口号
/// </summary>
public int ConsulPort { get; set; } }
}

Setting.cs

在appsettings.json 内新增节点

测试地址中只需要改端口号和服务名称即可 会自动读取本机ip到注入到consul中

 "Setting": {
"Port": "",
"ServiceName": "demoAPi",
"ConsulIP": "localhost",
"ConsulPort": ""
}

新增部分

注意 需要修改为 始终复制或者较新复制

修改 Program.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging; namespace DemoApi_II
{
public class Program
{
public static string StartPort;
public static void Main(string[] args)
{
var config = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true)
.Build();
StartPort = config.GetSection("Setting")["Port"];
CreateWebHostBuilder(args).Build().Run();
} public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseUrls($"http://*:{StartPort}")
.UseStartup<Startup>();
}
}

Program.cs

修改startup.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ConsulRegisterHelper;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; namespace DemoApi_II
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
} public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<Setting>(Configuration.GetSection("Setting"));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
} // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime lifetime)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
app.RegisterConsul(lifetime, new ServiceEntity
{
IP = NetworkHelper.LocalIPAddress,
Port = Convert.ToInt32(Configuration.GetSection("Setting")["Port"]),
ServiceName = Configuration.GetSection("Setting")["ServiceName"],
ConsulIP = Configuration.GetSection("Setting")["ConsulIP"],
ConsulPort = Convert.ToInt32(Configuration.GetSection("Setting")["ConsulPort"])
});
}
}
}

Startup.cs

创建自动注入consul服务的类库

新建core2.1类库项目 取名ConsulRegisterHelper

将以下3个类创建即可

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets; namespace ConsulRegisterHelper
{
public class NetworkHelper
{
public static string LocalIPAddress
{
get
{
UnicastIPAddressInformation mostSuitableIp = null;
var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces(); foreach (var network in networkInterfaces)
{
if (network.OperationalStatus != OperationalStatus.Up)
continue;
var properties = network.GetIPProperties();
if (properties.GatewayAddresses.Count == )
continue; foreach (var address in properties.UnicastAddresses)
{
if (address.Address.AddressFamily != AddressFamily.InterNetwork)
continue;
if (IPAddress.IsLoopback(address.Address))
continue;
return address.Address.ToString();
}
} return mostSuitableIp != null
? mostSuitableIp.Address.ToString()
: "";
}
} public static int GetRandomAvaliablePort(int minPort = , int maxPort = )
{
Random rand = new Random();
while (true)
{
int port = rand.Next(minPort, maxPort);
if (!IsPortInUsed(port))
{
return port;
}
}
} private static bool IsPortInUsed(int port)
{
IPGlobalProperties ipGlobalProps = IPGlobalProperties.GetIPGlobalProperties();
IPEndPoint[] ipsTCP = ipGlobalProps.GetActiveTcpListeners(); if (ipsTCP.Any(p => p.Port == port))
{
return true;
} IPEndPoint[] ipsUDP = ipGlobalProps.GetActiveUdpListeners();
if (ipsUDP.Any(p => p.Port == port))
{
return true;
} TcpConnectionInformation[] tcpConnInfos = ipGlobalProps.GetActiveTcpConnections();
if (tcpConnInfos.Any(conn => conn.LocalEndPoint.Port == port))
{
return true;
} return false;
}
}
}

NetworkHelper.cs

using Consul;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using System; namespace ConsulRegisterHelper
{
public static class AppBuilderExtensions
{
public static IApplicationBuilder RegisterConsul(this IApplicationBuilder app, IApplicationLifetime lifetime, ServiceEntity serviceEntity)
{
var consulClient = new ConsulClient(x => x.Address = new Uri($"http://{serviceEntity.ConsulIP}:{serviceEntity.ConsulPort}"));//请求注册的 Consul 地址
var httpCheck = new AgentServiceCheck()
{
DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(),//服务启动多久后注册
Interval = TimeSpan.FromSeconds(),//健康检查时间间隔,或者称为心跳间隔
HTTP = $"http://{serviceEntity.IP}:{serviceEntity.Port}{serviceEntity.HealthUrl}",//健康检查地址
Timeout = TimeSpan.FromSeconds()
}; // Register service with consul
var registration = new AgentServiceRegistration()
{
Checks = new[] { httpCheck },
ID = Guid.NewGuid().ToString(),
Name = serviceEntity.ServiceName,
Address = serviceEntity.IP,
Port = serviceEntity.Port,
Tags = new[] { $"urlprefix-/{serviceEntity.ServiceName}" }//添加 urlprefix-/servicename 格式的 tag 标签,以便 Fabio 识别
}; consulClient.Agent.ServiceRegister(registration).Wait();//服务启动时注册,内部实现其实就是使用 Consul API 进行注册(HttpClient发起)
lifetime.ApplicationStopping.Register(() =>
{
consulClient.Agent.ServiceDeregister(registration.ID).Wait();//服务停止时取消注册
}); return app;
}
}
}

Register.cs

using System;
using System.Collections.Generic;
using System.Text; namespace ConsulRegisterHelper
{
public class ServiceEntity
{
public ServiceEntity()
{
HealthUrl = "/api/health";
}
/// <summary>
/// 服务IP
/// </summary>
public string IP { get; set; }
/// <summary>
/// 服务端口号
/// </summary>
public int Port { get; set; }
/// <summary>
/// 服务名称
/// </summary>
public string ServiceName { get; set; }
/// <summary>
/// 服务发现地址
/// </summary>
public string ConsulIP { get; set; }
/// <summary>
/// 服务发现端口号
/// </summary>
public int ConsulPort { get; set; }
/// <summary>
/// 健康检查地址默认为/api/health
/// </summary>
public string HealthUrl { get; set; }
}
}

ServiceEntity.cs

在需要注入的服务Startup.cs中通过如下代码注入:

创建bat文件方便测试使用

E:
cd E:\ServerApi\OcelotGetWay\DemoApi_II\bin\Debug\netcoreapp2.
dotnet DemoApi_II.dll

实例代码

到此 测试demoapi 准备完成

参考内容:

微服务系列文章

https://www.cnblogs.com/edisonchou/p/dotnetcore_microservice_foundation_blogs_index_final.html

ocelot配置特性介绍

https://blog.csdn.net/qin_yu_2010/article/details/82749414

微服务网关从零搭建——(一)创建测试api以及api自动注入consul的更多相关文章

  1. 微服务网关从零搭建——(三)Ocelot网关 + identity4

    增加验证服务 1.创建名为AuthService 的core 空项目 2.修改startup文件 using System; using System.Collections.Generic; usi ...

  2. 微服务网关从零搭建——(二)搭建api网关(不带验证)

    环境准备 创建空的core2.1 api项目  演示使用名称APIGateWay  过程参考上一篇 完成后在appsettings.json 添加节点 "Setting": { & ...

  3. 微服务网关从零搭建——(七)更改存储方式为oracle

    资源准备: 下载开源项目 新建oracle表: -- ---------------------------- -- Table structure for OcelotGlobalConfigura ...

  4. 微服务网关从零搭建——(九)网关部署到linux服务器

    环境准备 公司电脑已安装core环境所以此处略过core环境安装 可参看此处 consul安装 如果没有wget命令 执行以下命令 yum install wget 下载consul wget htt ...

  5. 微服务网关从零搭建——(八)Ocelot网关中加入skywalking APM

    准备工作 一.下载skywalking 本例使用的是 注: 1.解压后执行完2,3步骤后运行\bin\startup.bat 2.默认后台端口为8080 如需修改则修改\webapp\webapp.y ...

  6. 微服务网关从零搭建——(六)ocelot配置追踪功能

    butterfly 准备工作 首先下载buterfly release版本 解压并通过命令启动:dotnet Butterfly.Web.dll --EnableHttpCollector=true ...

  7. 小D课堂 - 新版本微服务springcloud+Docker教程_6-06 zuul微服务网关集群搭建

    笔记 6.Zuul微服务网关集群搭建     简介:微服务网关Zull集群搭建 1.nginx+lvs+keepalive      https://www.cnblogs.com/liuyisai/ ...

  8. 微服务之:从零搭建ocelot网关和consul集群

    介绍 微服务中有关键的几项技术,其中网关和服务服务发现,服务注册相辅相成. 首先解释几个本次教程中需要的术语 网关 Gateway(API GW / API 网关),顾名思义,是企业 IT 在系统边界 ...

  9. Spring Cloud微服务安全实战_4-1_微服务网关安全_概述&微服务安全面临的挑战

      第四章  网关安全 这一章从简单的API的场景过渡到复杂的微服务的场景 4.1 概述 微服务安全面临的挑战:介绍中小企业的一个微服务架构,相比第三章的单体应用的简单的API所面临的哪些挑战 OAu ...

随机推荐

  1. android短信拦截

    广播分2种,无序广播和有序广播.可以理解为散列和队列广播. 首先无序广播,不能中断,分发机制有点类似散列发送.这种广播的的发送为:context.sendBroadcast这种广播是不能中断的,请看A ...

  2. 4.8 Using Ambiguous Grammars

    4.8 Using Ambiguous Grammars It is a fact that every ambiguous grammar fails to be LR and thus is no ...

  3. 第八周 Leetcode 44. Wildcard Matching 水题 (HARD)

    Leetcode 44 实现一种类似正则表达式的字符串匹配功能. 复杂度要求不高, 调代码稍微费点劲.. 好像跟贪心也不太沾边, 总之 *把待匹配串分成若干个子串, 每一个子串尽量在模式串中靠前的部分 ...

  4. AIZU AOJ 2309 Vector Compression 最小树形图(朱—刘算法)

    题意简述:给定若干个相同维度的向量,寻找一种排序方法,使得所有向量的表示长度总和最低. 所谓表示长度为(Aj-r*Ai)^2,其中i<j  数据范围:向量总数和维度均小于100 思路:(1)首先 ...

  5. JeePlus:Maven 安装配置

    ylbtech-JeePlus:Maven 安装配置 1.返回顶部 1. Maven 安装配置 1 Maven 由于Maven依赖Java运行环境,因此使用Maven之前需要配置Java的运行环境.下 ...

  6. hdu4292 Food 最大流模板题

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4292 题意:水和饮料,建图跑最大流模板. 我用的是学长的模板,最然我还没有仔细理解,不过这都不重要直接 ...

  7. Linux C编程之一:Linux下c语言的开发环境

    ---恢复内容开始--- 今天开始根据Linux C编程相关视频的学习所做的笔记,希望能一直坚持下去... 1.开发环境的构成 编辑器:VI: 编译器:选择GNU  C/C++编译器gcc: 调试器: ...

  8. 士兵杀敌 三 --- O( 1 ) 的时间复杂度 .

    一看就是 十分简单的  题  ,   然后上去开始无脑程序 超时~~~      感觉时间复杂度 , 已经很低了  ,  但是并没有什么卵用 . #include<stdio.h> #in ...

  9. 多维DP UVA 11552 Fewest Flop

    题目传送门 /* 题意:将子符串分成k组,每组的字符顺序任意,问改变后的字符串最少有多少块 三维DP:可以知道,每一组的最少块是确定的,问题就在于组与组之间可能会合并块,总块数会-1. dp[i][j ...

  10. Android内存管理(15)SparseArray系列代替HashMap系列

    参考: https://liuzhichao.com/p/832.html http://www.2cto.com/kf/201311/255640.html 1,简介: SparseArray是an ...