微服务网关从零搭建——(一)创建测试api以及api自动注入consul
本系列编写目的纯属个人开发记录 以下代码均为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的更多相关文章
- 微服务网关从零搭建——(三)Ocelot网关 + identity4
增加验证服务 1.创建名为AuthService 的core 空项目 2.修改startup文件 using System; using System.Collections.Generic; usi ...
- 微服务网关从零搭建——(二)搭建api网关(不带验证)
环境准备 创建空的core2.1 api项目 演示使用名称APIGateWay 过程参考上一篇 完成后在appsettings.json 添加节点 "Setting": { & ...
- 微服务网关从零搭建——(七)更改存储方式为oracle
资源准备: 下载开源项目 新建oracle表: -- ---------------------------- -- Table structure for OcelotGlobalConfigura ...
- 微服务网关从零搭建——(九)网关部署到linux服务器
环境准备 公司电脑已安装core环境所以此处略过core环境安装 可参看此处 consul安装 如果没有wget命令 执行以下命令 yum install wget 下载consul wget htt ...
- 微服务网关从零搭建——(八)Ocelot网关中加入skywalking APM
准备工作 一.下载skywalking 本例使用的是 注: 1.解压后执行完2,3步骤后运行\bin\startup.bat 2.默认后台端口为8080 如需修改则修改\webapp\webapp.y ...
- 微服务网关从零搭建——(六)ocelot配置追踪功能
butterfly 准备工作 首先下载buterfly release版本 解压并通过命令启动:dotnet Butterfly.Web.dll --EnableHttpCollector=true ...
- 小D课堂 - 新版本微服务springcloud+Docker教程_6-06 zuul微服务网关集群搭建
笔记 6.Zuul微服务网关集群搭建 简介:微服务网关Zull集群搭建 1.nginx+lvs+keepalive https://www.cnblogs.com/liuyisai/ ...
- 微服务之:从零搭建ocelot网关和consul集群
介绍 微服务中有关键的几项技术,其中网关和服务服务发现,服务注册相辅相成. 首先解释几个本次教程中需要的术语 网关 Gateway(API GW / API 网关),顾名思义,是企业 IT 在系统边界 ...
- Spring Cloud微服务安全实战_4-1_微服务网关安全_概述&微服务安全面临的挑战
第四章 网关安全 这一章从简单的API的场景过渡到复杂的微服务的场景 4.1 概述 微服务安全面临的挑战:介绍中小企业的一个微服务架构,相比第三章的单体应用的简单的API所面临的哪些挑战 OAu ...
随机推荐
- 阳性比例 mysql CASE UNION ALL
阳性比例 mysql CASE UNION ALL SELECT t.*,t.type_0/all_ FROM ( SELECT FROM_UNIXTIME(create_time,'%Y-%m-%d ...
- vim升级到8.0
1.卸载 sudo apt-get remove --purge vim 2.添加8.0的vim源并安装 sudo add-apt-repository ppa:jonathonf/vim sudo ...
- Opencv+Zbar二维码识别(一维码校正)
一维码由一组规则排列的黑色线条.白色线条以及对应的字符组成.对倾斜的(没有严重形变)一维码的角度校正,可以根据其黑白相间.排列规则的特点,计算傅里叶频谱,通过傅里叶频谱中直线的倾斜角度计算空间域图像一 ...
- 解决Error for wireless request "Set Mode" (8B06) 问题 (转载)
转自:http://blog.csdn.net/muge0913/article/details/17062871 在运行以下命令的时候,意外的出错,最后google了下,最终才确定了原因,因为在运行 ...
- bzoj 1093: [ZJOI2007]最大半连通子图【tarjan+拓扑排序+dp】
先tarjan缩成DAG,然后答案就变成了最长链,dp的同时计数即可 就是题面太唬人了,没反应过来 #include<iostream> #include<cstdio> #i ...
- 17年day2
/* 嗯,明天就出发了. 嗯,终于快要结束了. 考试日常挂T1 今天晚上老师们请我们吃水饺,还有一个大蛋糕. 虽然没怎么吃蛋糕23333 还好我的水饺是白菜馅的~~~ 晚上学哥学姐们发视频送祝福,谢谢 ...
- VBScript+SCR+NetApi+Accoreconsole 批处理dwg文件
继上次powershell运行accoreconsole(https://www.cnblogs.com/NanShengBlogs/p/10981687.html)的研究之后又觉得不是很合适,毕竟p ...
- SpringCloud(Finchley版本)中Zull过滤器ResponseBoby返回中文乱码解决方案
Spring Cloud带有"Cloud"的字样,但它并不是云计算解决方案,而是在Spring Boot基础上构建的,用于快速构建分布式系统的通用模式的工具集.使用Spring C ...
- navicat mysql报错误:2013 Lost connection to MySQL server during query
好像是MySQL的navicat UI界面跟数据的连接问题,如果直接用命令导入数据的话,或许能规避这个问题.
- EditText(7)EditText输入事件监听
EditText.addTextChangedListener(TextWatcher watcher); void initSearch(){ search = (EditText) findVie ...