早就想学学.net的微服务相关东西,在网上找到一篇入门的,于是自己跟着敲了一遍,算是对微服务有个了解,做个学习记录,笔者水平是个菜鸡,只是按照自己的理解,有误的地放还请各位大佬指正。
我自己理解的微服务嘛,听名字就是服务比较小或者职责单一,然后一个微服务挂了不影响整个应用的使用,而且可以做到应用之间互相解耦,好处还是挺多的,至于坏处可能就是维护成本高,架构变得复杂等等...
文章参考自:https://www.cnblogs.com/xhznl/p/13259036.html
一、服务发现组件
服务发现组件用的是consul,之前还搞了下nacos,发现ocelot好像没法对nacos做服务发现,于是就改成使用consul了。
consul官网:Consul by HashiCorp
1、下载windows的consul包解压,我下载的是1.15.1,在解压后的目录打开cmd
2、执行consul agent -dev启动consul,-dev参数只用于学习,生产肯定不是这个
3、不出意外的话就启动好了,默认端口是8500,我用的都是本地环境,所以浏览器访问http://localhost:8500/就能看到consul的ui界面了
二、consul有了,现在就是要使用代码把我们的服务注册到consul中
1、新建一个asp.net core webapi项目
2、安装consul的nuget包,封装了操作consul的方法
直接在项目文件夹下的ItemGroup节点里加上也行
<PackageReference Include="Consul" Version="1.6.10.8" />
当然用程序包命令行安装也是一样的,装上了就行
3、修改appsettings.json,配置一下consul的配置
"consul": {
"Address": "http://localhost:8500",
"Datacenter": "test",
"ServiceAddr": "localhost",
"ServiceHealthCheck": "/HealthCheck"
}
Address:consul的地址
Datacenter:数据中心
ServiceAddr:需要注册进consul的服务地址,这里指的就是productservice
ServiceHealthCheck:服务健康检查地址
4、编写IApplicationBuilder扩展方法实现将我们的服务注册进consul中
public static class ConsulHelper
{
public static IApplicationBuilder RegisterConsul(
this IApplicationBuilder applicationBuilder
,IHostApplicationLifetime hostApplicationLifetime
,IConfiguration configuration)
{
ConsulClient consulClient = new ConsulClient(consul =>
{
consul.Address =new Uri(configuration.GetSection("consul")["Address"]);
consul.Datacenter = configuration.GetSection("consul")["Datacenter"];
});
//consulClient.Agent.ServiceDeregister("cdf7f896-7f1b-48e7-ad6d-a21d447d3cef");
Dictionary<string,string> serviceMetaData = new Dictionary<string,string>();//服务元数据
serviceMetaData.Add("zp", "zhangpeng");
string serviceAddr = configuration.GetSection("consul")["ServiceAddr"];//consul服务地址
AgentServiceRegistration agentServiceRegistration=new AgentServiceRegistration();
agentServiceRegistration.ID=Guid.NewGuid().ToString();
agentServiceRegistration.Address = configuration.GetSection("consul")["ServiceAddr"];//自定义服务的地址,直接写ip,不用加http,不然ocelot一直报错
agentServiceRegistration.Name = configuration["serviceName"] is null? "productservice": configuration["serviceName"];//这里读取命令行设置的名称
agentServiceRegistration.Port = configuration["serviceport"] is null? 5000:int.Parse(configuration["serviceport"]);//这里读取命令行设置的自定义服务的端口
agentServiceRegistration.Meta = serviceMetaData;
agentServiceRegistration.Check = new AgentServiceCheck()
{
HTTP = $"http://{serviceAddr}:{agentServiceRegistration.Port}{configuration.GetSection("consul")["ServiceHealthCheck"]}",//健康检查地址
Method = "GET",//请求方式
Timeout = TimeSpan.FromSeconds(5),//超时时间
Interval = TimeSpan.FromSeconds(10),//间隔时间
DeregisterCriticalServiceAfter= TimeSpan.FromSeconds(30)//多少秒后连不上则从consul中清除该服务
};
//Console.WriteLine(agentServiceRegistration.Check.HTTP);
consulClient.Agent.ServiceRegister(agentServiceRegistration).Wait();
//监听应用程序终止回调,把服务从consul移除
hostApplicationLifetime.ApplicationStopping.Register(() =>
{
consulClient.Agent.ServiceDeregister(agentServiceRegistration.ID).Wait();
});
hostApplicationLifetime.ApplicationStopped.Register(() =>
{
consulClient.Agent.ServiceDeregister(agentServiceRegistration.ID).Wait(); ;
});
return applicationBuilder;
}
}
注意:这里有个小坑就是注册的服务Address直接写ip,不用加http,不然ocelot一直报错,但是consul服务又注册进去了,应该是ocelot获取consul服务的方式不一样导致的
5、在配置中间件的时候调用一下RegisterConsul方法
5.1这个服务用的还是Program+startup那一种方式,所以可以直接注入IHostApplicationLifetime和ConsulServiceHelper,如果是.net6以上的话只有Program,可以通过ServiceProvider的GetRequiredService获取想要的服务实例
app.RegisterConsul(hostApplicationLifetime, Configuration);
到此,服务注册就成功了,这里我用dotnet run来启动,因为服务不会只有一个实例
6、右击项目生成一下,切换到项目所在目录
我的是在这里
在文件地址栏输入下cmd进入命令行界面
6.1输入:dotnet run --urls=http://localhost:8848 --serviceport=8848 serviceName=productservice
--urls就是指定我们的地址 官方自带的参数
--serviceport和--serviceName是我们自定义的参数,启动时会加载到Configuration中,然后来指定我们的服务名称和端口号(命名不规范,一会大写一会小写,见谅....)
6.2看到上面输出正常,打开consul查看是否注册进来了
可以看到服务已经注册到consul中了,