Ocelot+Consul 集群搭建实践
博客园已经有很多大神写过consul集群搭建了。大家都在玩,那我也不能托后退呢
不过自己研究下还是好的。毕竟每个人遇到的问题的不同
研究过才能说自己玩过consul,文章有部分名词解释是收集网络
Consul 官网:https://www.consul.io/
帮助文档:https://www.consul.io/docs/upgrading.html
Consul是一个服务网格(微服务间的 TCP/IP,负责服务之间的网络调用、限流、熔断和监控)解决方案,它是一个一个分布式的,高度可用的系统,
而且开发使用都很简便。它提供了一个功能齐全的控制平面,主要特点是:服务发现、健康检查、键值存储、安全服务通信、多数据中心。
具体的理论在网上都能找到,我这里就不描述了。主要写部署的实践过程
我看了网上大部分都是通过一台机器来模拟的集群,我打算通过多台服务器来进行集群搭建
这样才有实战效果,因为官方推荐用3台做server,所以用3台server只部署server,不部署其他程序
conusl集群通信中有很多端口:
:TCP # Server RPC :agent server 使用的,用于处理其他agent发来的请求
:TCP and UDP # Serf LAN: 所有的agent都要使用这个端口,用于处理LAN中的gossip,
:TCP and UDP # Serf WAN:agent Server使用的,处理WAN中的与其他server的gossip
:TCP # 所有agent都要使用的端口,用于处理从CLI来的RPC。
:TCP # 所有agent都要使用的端口,用于处理HTTP API。
:TCP and UDP # 用于处理 DNS 查询。
所以需要开通的端口有:8301/tcp 8301/udp 8302/tcp 8302/udp 8300/tcp 8500/tcp 8600/udp 如果我写漏了。自己补上
如果是阿里云服务,需要登陆阿里云配置本地安全组
一些相关命令:
firewall-cmd --list-ports #查看已开放的端口
firewall-cmd --reload # 重启防火墙,刚开通的端口才会生效
firewall-cmd --query-port=/tcp #查询80端口开通状态
firewall-cmd --add-port=/udp --permanent #开通80端口udp协议
名词概念
client:
CLIENT表示consul的client模式,就是客户端模式。是consul节点的一种模式,这种模式下,所有注册到当前节点的服务会被转发到SERVER,本身是不持久化这些信息。
server:
SERVER表示consul的server模式,表明这个consul是个server,这种模式下,功能和CLIENT都一样,唯一不同的是,它会把所有的信息持久化的本地,这样遇到故障,信息是可以被保留的。
server-leader:
中间那个SERVER下面有LEADER的字眼,表明这个SERVER是它们的老大,它和其它SERVER不一样的一点是,它需要负责同步注册的信息给其它的SERVER,同时也要负责各个节点的健康监测。
raft:
server节点之间的数据一致性保证,一致性协议使用的是raft,而zookeeper用的paxos,etcd采用的也是taft。
服务发现协议: consul采用http和dns协议,etcd只支持http
服务注册: consul支持两种方式实现服务注册,一种是通过consul的服务注册http API,由服务自己调用API实现注册,另一种方式是通过json个是的配置文件实现注册,将需要注册的服务以json格式的配置文件给出。consul官方建议使用第二种方式。
服务发现: consul支持两种方式实现服务发现,一种是通过http API来查询有哪些服务,另外一种是通过consul agent 自带的DNS(8600端口),域名是以NAME.service.consul的形式给出,NAME即在定义的服务配置文件中,服务的名称。DNS方式可以通过check的方式检查服务。
服务间的通信协议: Consul使用gossip协议管理成员关系、广播消息到整个集群,他有两个gossip pool(LAN pool和WAN pool),LAN pool是同一个数据中心内部通信的,WAN pool是多个数据中心通信的,LAN pool有多个,WAN pool只有一个。
LAN Gossip——它包含所有位于同一个局域网或者数据中心的所有节点。
WAN Gossip——它只包含Server。这些server主要分布在不同的数据中心并且通常通过因特网或者广域网通信。
RPC——远程过程调用。这是一个允许client请求server的请求/响应机制。
简单来说就是:client相当于我们平时说的LB,负责将请求转发到Server,Server中有一个leader,负责Server集群的同步和监测,
这个server-leader在不指定的情况下回随机推举出一个,当然也可以手动指定。这个在ACL配置的时候需要保证Server-leader是同一个。
参数解释
1、命令参数
-advertise:通知展现地址用来改变我们给集群中的其他节点展现的地址,默认情况下-bind地址就是展现地址,然而也存在一些路由地址是不能受约束的,这时候会激活一个不同的地址来供应,如果这个地址不能路由,这个路由将不能被加入集群 -bootstrap:用来控制一个server是否在bootstrap模式,在一个datacenter中只能有一个server处于bootstrap模式,当一个server处于bootstrap模式时,可以自己选举为raft leader,在一个节点的模式下这种方式很重要,否则在集群中的一致性不能保证,不推荐在集群中应用这个标识 -bootstrap-expect:在一个datacenter中期望提供的server节点数目,当该值提供的时候,consul一直等到达到指定sever数目的时候才会引导整个集群,该标记不能和bootstrap公用(推荐使用的方式) -bind:该地址用来在集群内部的通讯,集群内的所有节点到地址都必须是可达的,默认是0.0.0.,这意味着Consulo会使用第一个可用的私有IP地址,Consul可以使用TCP和UDP并且可以使用共同的端口,如果存在防火墙,这两者协议必须是允许的。 -client:consul绑定在哪个client地址上,这个地址提供HTTP、DNS、RPC等服务,默认是127.0.0.,只允许回路连接。RPC地址用于Consul命令,比如Consul members可以查询当前运行的Consul代理 -config-file:明确的指定要加载哪个配置文件,文件下的所有配置会合并在一起进行加载 -config-dir:配置文件目录,里面所有以.json结尾的文件都会被加载 -data-dir:提供一个目录用来存放agent的状态,所有的agent允许都需要该目录,该目录必须是稳定的,系统重启后都继续存在 -dc:该标记控制agent运行的datacenter的名称,默认是dc1 -encrypt:指定secret key,使consul在通讯时进行加密,key可以通过consul keygen生成,同一个集群中的节点必须使用相同的key -http-port:HTTP API侦听端口,默认端口8500,可以在环境变量中进行设置,非常有用,可以用于与Consul进行通讯 -join:加入一个已经启动的agent的ip地址,可以多次指定多个agent的地址。如果consul不能加入任何指定的地址中,则agent会启动失败,默认agent启动时不会加入任何节点。 -retry-join:和join类似,但是允许你在第一次失败后进行尝试。 -retry-interval:两次join之间的时间间隔,默认是30s -retry-max:尝试重复join的次数,默认是0,也就是无限次尝试 -log-level:consul agent启动后显示的日志信息级别。默认是info,可选:trace、debug、info、warn、err。跟踪 调试 详情 警告 错误,可以通过Consul monitor使用任何级别,也可以通过重启加载新的配置级别 -node:节点在集群中的名称,在一个集群中必须是唯一的,默认是该节点的主机名(代表一个机器) -pid-file:提供一个路径来存放pid文件,可以使用该文件进行SIGINT/SIGHUP(关闭/更新)agent -protocol:consul使用的协议版本 consul -v -rejoin:使consul忽略先前的离开,在再次启动后仍旧尝试加入集群中。 -server:定义agent运行在server模式还是Client模式,提供时即为Server端,每个集群至少有一个server并且每台机器上不要超过5个dataceter.所有服务器采用一致性算法Raft保证数据一致,确保在故障的情况下的可用性。 -syslog:开启系统日志功能,只在linux/osx上生效 -ui-dir:提供存放web ui资源的路径,该目录必须是可读的
2、配置参数
Consul配置信心可以填写在.json文件中,配置文件加载时会按照文件名字母排序的顺序读取,效果与命令行一致。 acl_datacenter:只用于server,指定的datacenter的权威ACL信息,所有的servers和datacenter必须同意ACL datacenter acl_default_policy:默认是allow acl_token:agent会使用这个token和consul server进行请求 acl_ttl:控制TTL的cache,默认是30s addresses:一个嵌套对象,可以设置以下key:dns、http、rpc advertise_addr:等同于-advertise bootstrap:等同于-bootstrap bootstrap_expect:等同于-bootstrap-expect bind_addr:等同于-bind ca_file:提供CA文件路径,用来检查客户端或者服务端的链接 cert_file:必须和key_file一起 check_update_interval: client_addr:等同于-client datacenter:等同于-dc data_dir:等同于-data-dir disable_anonymous_signature:在进行更新检查时禁止匿名签名 disable_remote_exec:禁止支持远程执行,设置为true,agent会忽视所有进入的远程执行请求 disable_update_check:禁止自动检查安全公告和新版本信息 dns_config:是一个嵌套对象,可以设置以下参数:allow_stale、max_stale、node_ttl 、service_ttl、enable_truncate domain:默认情况下consul在进行DNS查询时,查询的是consul域,可以通过该参数进行修改 enable_debug:开启debug模式 enable_syslog:等同于-syslog encrypt:等同于-encrypt key_file:提供私钥的路径 leave_on_terminate:默认是false,如果为true,当agent收到一个TERM信号的时候,它会发送leave信息到集群中的其他节点上。 log_level:等同于-log-level node_name:等同于-node ports:这是一个嵌套对象,可以设置以下key:dns(dns地址:)、http(http api地址:)、rpc(rpc:)、serf_lan(lan port:)、serf_wan(wan port:)、server(server rpc:) protocol:等同于-protocol rejoin_after_leave:等同于-rejoin retry_join:等同于-retry-join retry_interval:等同于-retry-interval server:等同于-server server_name:会覆盖TLS CA的node_name,可以用来确认CA name和hostname相匹配 skip_leave_on_interrupt:和leave_on_terminate比较类似,不过只影响当前句柄 start_join:一个字符数组提供的节点地址会在启动时被加入 syslog_facility:当enable_syslog被提供后,该参数控制哪个级别的信息被发送,默认Local0 ui_dir:等同于-ui-dir verify_incoming:默认false,如果为true,则所有进入链接都需要使用TLS,需要客户端使用ca_file提供ca文件,只用于consul server端,因为client从来没有进入的链接 verify_outgoing:默认false,如果为true,则所有出去链接都需要使用TLS,需要服务端使用ca_file提供ca文件,consul server和client都需要使用,因为两者都有出去的链接 watches:watch一个详细名单
摘自:https://www.cnblogs.com/qidakang/p/7837519.html
-bind:为该节点绑定一个地址
-enable-script-checks=true:设置检查服务为可用
-join:加入到已有的集群中
-server 表示当前使用的server模式
-node:指定当前节点在集群中的名称
-config-file - 要加载的配置文件
-config-dir:指定配置文件,定义服务的,默认所有以.json结尾的文件都会读
-datacenter: 数据中心没名称,不设置的话默认为dc
-client: 客户端模式
-ui: 使用consul自带的ui界面
-data-dir consul存储数据的目录
-bootstrap:用来控制一个server是否在bootstrap模式,在一个datacenter中只能有一个server处于bootstrap模式,当一个server处于bootstrap模式时,可以自己选举为raft leader。
-bootstrap-expect:在一个datacenter中期望提供的server节点数目,当该值提供的时候,consul一直等到达到指定sever数目的时候才会引导整个集群,该标记不能和bootstrap公用 这两个参数十分重要, 二选一,如果两个参数不使用的话,会出现就算你使用join将agent加入了集群仍然会报
[ERR] agent: failed to sync remote state: No cluster leader ui: 相当于-ui 命令行标志。
acl_token:agent会使用这个token和consul server进行请求
acl_ttl:控制TTL的cache,默认是30s
addresses:一个嵌套对象,可以设置以下key:dns、http、rpc
advertise_addr:等同于-advertise
bootstrap:等同于-bootstrap
bootstrap_expect:等同于-bootstrap-expect
bind_addr:等同于-bindca_file:提供CA文件路径,用来检查客户端或者服务端的链接
cert_file:必须和key_file一起
check_update_interval:
client_addr:等同于-client
datacenter:等同于-dc
data_dir:等同于-data-dir
disable_anonymous_signature:在进行更新检查时禁止匿名签名
enable_debug:开启debug模式
enable_syslog:等同于-syslog
encrypt:等同于-encrypt
key_file:提供私钥的路径
leave_on_terminate:默认是false,如果为true,当agent收到一个TERM信号的时候,它会发送leave信息到集群中的其他节点上。
log_level:等同于-log-level node_name:等同于-node
ports:这是一个嵌套对象,可以设置以下key:dns(dns地址:)、http(http api地址:)、rpc(rpc:)、serf_lan(lan port:)、serf_wan(wan port:)、server(server rpc:)
protocol:等同于-protocol
rejoin_after_leave:等同于-rejoin
retry_join:等同于-retry-join
retry_interval:等同于-retry-interval
server:等同于-server
syslog_facility:当enable_syslog被提供后,该参数控制哪个级别的信息被发送,默认Local0
ui_dir:等同于-ui-dir
现在手中资源有:4台linux和2台windows server
Linux:
43.243.49.55
43.243.49.60
103.250.12.20
39.105.144.51(阿里云)
windows:
43.243.49.57
129.28.195.120(腾讯云)
分配:
service服务器:(43.243.49.55,43.243.49.60,103.250.12.20)
client:(129.28.195.120)
api部署两个,用于测试负载:(43.243.49.57,39.105.144.51)
linux上我都是基于docker部署,毕竟docker方便
首先部署所有的server端
43.243.49.55上面执行:
docker run --name s1 -d --restart=always -p 8500:8500 -p 8300:8300 -p 8301:8301 -p 8302:8302 -p 8301:8301/udp -p 8302:8302/udp -p 8600:8600
consul agent -server -node s1 -bootstrap-expect 3 -advertise 43.243.49.55 --bind 0.0.0.0 -client=0.0.0.0 -ui -datacenter=dc-test
通过docker s1 logs 可以看到consul 已经运行成功,但提示没有leader,因为设置了,-bootstrap-expect 3
这个集群需要3台server,所以要等3台server加如集群后才会选举一个leader
现在可以尝试访问:http://43.243.49.55:8500 会出现异常,因为集群中没有3台server,没有leader
43.243.49.60上面执行:
docker run --name s1 -d --restart=always -p 8500:8500 -p 8300:8300 -p 8301:8301 -p 8302:8302 -p 8301:8301/udp -p 8302:8302/udp -p 8600:8600
consul agent -server -node s2 -bootstrap-expect 3 -advertise 43.243.49.60 --bind 0.0.0.0 -client=0.0.0.0 -join 43.243.49.55 -datacenter=dc-test
注意上面的-join 43.243.49.55,是加入集群,这里没有-ui ,因为我不想把60开通ui功能,具体根据自己需求来
如果执行命令的时候,没有join。也就是没有加入任何集群,如果想加入集群,可以手动加入: docker exec -t s1 consul join 43.243.49.55
103.250.12.20上面执行:
docker run --name s1 -d --restart=always -p : -p : -p : -p : -p :/udp -p :/udp
-p : consul agent -server -node s3 -bootstrap-expect -advertise 103.250.12.20 --bind 0.0.0.0 -client=0.0.0.0 -join 43.243.49.55 -datacenter=dc-test
这样3台server都已经部署完成,通过docker logs s1 (任意一台server都可以)可以看到已经选举了leader为s1节点,s2和s3为跟随节点Follower
通过命令: docker exec -t s1 consul members 可以查看集群节点信息,Status状态正常,Type为server
通过: docker exec -t s1 consul operator raft list-peers 查看集群信息,可以看到集群中的leader为note为s1的节点,ip为:43.243.49.55
还有很多命令比如: docker exec -t s1 consul members -detailed
因为3台server,只有43.243.49.55开通了ui,尝试访问,集群部署成功
3台节点也正常
接下来搭建client端
因为129.28.195.120是windows server,所以不能跑docker
首先下载consul是一个exe运行程序
打开cmd,切换到当前目录,执行命令:
consul agent -ui -advertise 129.28.195.120 -bind=0.0.0.0 -client=0.0.0.0
-data-dir C:\consul -config-dir=C:\consul\conf -node=c1 -join 43.243.49.55 -datacenter=dc-test
-data-dir是当前consul路径,
-config-dir是配置文件,也就是配置服务的,后面会说
执行成功了,再一次查看集群信息。多了一个client
因为 129.28.195.120开通了ui,所以同样可以访问
好了。接下来3个server和1个client的集群就搭建成功了,接下来就是服务的注册了
服务注册有2种方式:
1:直接配置文件的方式,也就是上面-config-dir的目录
2:通过代码http调用consul接口方式注册
-config-dir是上面部署widows的方式
如果是docker 跑client,需要挂载文件
--数据挂载方式
/consul/data:持久化数据存储
/consul/config:配置文件
可以这样:
docker run -d -p : --restart=always -v=/volume/consul/data:/consul/data -v=/volume/consul/config:/consul/config --name c2
consul agent -ui -bind=0.0.0.0 -client 0.0.0.0 -node=c2 -join 43.243.49.55 -datacenter=dc-test
那么写几个api试试,既然有2中方式注册服务,那么都试试,
还有,安装上面的计划,分别在43.243.49.57,39.105.144.51上部署,因为都是linux,我依然选择用docker方式
准备工作
待会为了测试在不同的服务器跑负载,我这里创建2个api,分别用不同方式注册,来比较
1:Order.Api(用配置文件的方式注册)
2:User.Api(用代码方式注册)
2个api分别添加检查检查方法,该方法返回ok。说明服务器没有挂掉
为了区分不同的服务器,2个api分别添加返回当前服务器ip地址的方法,仅仅是为了测试,不用过多纠结
User.Api添加配置文件:这里填写client地址,当然你填写任意一台server地址也是可以的
看到网上有人提问说,只有一个client,如果这个client挂了。那不就注册失败了吗?怎么解决,
我认为这担心是多余的。挂了肯定会注册失败,client挂了。修复即可,
就好比我们一个项目部署在服务器,如果服务器不挂,你也不会老是担心,如果服务器挂了怎么办吧,比如,机房断电。线路故障
这些也只能等待修复,如果硬是担心。那就只能部署多个client,然后轮询判断??
{
"ServiceDiscovery": {
"ServiceName": "UserService",
"Consul": {
"HttpEndpoint": "http://129.28.195.120:8500",
"DnsEndpoint": {
"Address": "129.28.195.120",
"Port":
}
}
}
}
然后配置对应的实体类,我这里就不写了
在User.Api 添加consul包
在ConfigureServicesz中配置如下:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); //services.AddOptions();
services.Configure<ServiceDiscoveryOptions>(Configuration.GetSection("ServiceDiscovery")); services.AddSingleton<IConsulClient>(p => new ConsulClient(cfg =>
{
var serviceConfiguration = p.GetRequiredService<IOptions<ServiceDiscoveryOptions>>().Value; if (!string.IsNullOrEmpty(serviceConfiguration.Consul.HttpEndpoint))
{
// if not configured, the client will use the default value "127.0.0.1:8500"
cfg.Address = new Uri(serviceConfiguration.Consul.HttpEndpoint);
}
})); }
Configure配置如下:
public void Configure(IApplicationBuilder app, IHostingEnvironment env,
IApplicationLifetime lifetime,
ILoggerFactory loggerFactory,
IOptions<ServiceDiscoveryOptions> serviceOptions,
IConsulClient consul)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
} //app.UseHttpsRedirection();
app.UseMvc(); //InitTable(app); lifetime.ApplicationStarted.Register(() =>
{
RegisterService(app, lifetime, serviceOptions, consul);
});
//lifetime.ApplicationStopped.Register(OnStoped);
}
然后是RegisterService注册方法:
private void RegisterService(IApplicationBuilder app, IApplicationLifetime appLife,
IOptions<ServiceDiscoveryOptions> serviceOptions,
IConsulClient consul)
{
var features = app.Properties["server.Features"] as FeatureCollection;
var addresses = features.Get<IServerAddressesFeature>()
.Addresses
.Select(p => new Uri(p)); foreach (var address in addresses)
{
var serviceId = $"{serviceOptions.Value.ServiceName}_{address.Host}:{address.Port}"; //健康检查
var httpCheck = new AgentServiceCheck()
{
DeregisterCriticalServiceAfter = TimeSpan.FromMinutes(),
Interval = TimeSpan.FromSeconds(),
HTTP = new Uri(address, "api/HealthCheck").OriginalString
}; //服务注册
var registration = new AgentServiceRegistration()
{
Checks = new[] { httpCheck },
/*
测试的时候用 的localhost
那么在DnsClient取值的时候
AddressList会为空,不过HostName有值
*/
Address = address.Host, // "127.0.0.1",
ID = serviceId,
Name = serviceOptions.Value.ServiceName,
Port = address.Port
}; consul.Agent.ServiceRegister(registration).GetAwaiter().GetResult(); appLife.ApplicationStopping.Register(() =>
{
consul.Agent.ServiceDeregister(serviceId).GetAwaiter().GetResult();
});
}
}
因为是边写边测试,所以先把User.Api 放到 服务器,43.243.49.57上试试效果,用Kestrel跑起来测试
执行命令: dotnet User.Api.dll --urls http://43.243.49.57:5001 当然5001端口得开通
运行成功后,可以看到服务注册成功
一切正常
直接访问试试
稍后把Order.Api直接用配置文件的方式注册,不过在这之前,讲讲服务的发现,
上面就是consul服务的注册,那么看看服务发现该怎么做。
上面出现了8500和8600端口,8500是ui界面的。8600是DNS其实就是一个是注册服务,一个是服务发现
创建一个Api:SD.Api (ServiceDiscovery简称)
服务发现需要依赖包:
ConfigureServices配置
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); services.Configure<ServiceDiscoveryOptions>(Configuration.GetSection("ServiceDiscovery"));
services.AddSingleton<IDnsQuery>(p =>
{
var serviceConfiguration = p.GetRequiredService<IOptions<ServiceDiscoveryOptions>>().Value;
var dnsEndpoint = serviceConfiguration.Consul.DnsEndpoint; //推荐
return new LookupClient(serviceConfiguration.Consul.DnsEndpoint.ToIPEndPoint());
//或者
//return new LookupClient(IPAddress.Parse(dnsEndpoint.Address), dnsEndpoint.Port);
//return new LookupClient(IPAddress.Parse("127.0.0.1"), 8600); }); //services.AddSingleton<IConsulClient>(p => new ConsulClient(cfg =>
//{
// var serviceConfiguration = p.GetRequiredService<IOptions<ServiceDiscoveryOptions>>().Value; // if (!string.IsNullOrEmpty(serviceConfiguration.Consul.HttpEndpoint))
// {
// // if not configured, the client will use the default value "127.0.0.1:8500"
// cfg.Address = new Uri(serviceConfiguration.Consul.HttpEndpoint);
// }
//})); services.AddSingleton<HttpClient>();
}
创建Userservice控制器
public class UserServiceController : ControllerBase
{
private HttpClient _httpClient;
//private readonly string _userServiceUrl = "http://localhost:5000";
private readonly string _userServiceUrl;
private readonly IDnsQuery _dns;
private readonly IOptions<ServiceDiscoveryOptions> _options;
public UserServiceController(HttpClient httpClient, IDnsQuery dns, IOptions<ServiceDiscoveryOptions> options)
{
_httpClient = httpClient;
_dns = dns ?? throw new ArgumentNullException(nameof(dns));
_options = options ?? throw new ArgumentNullException(nameof(options)); var result = _dns.ResolveService("service.consul", _options.Value.ServiceName);
/*
如果服务注册用的是localhost,那么AddressList为空,则取HostName
必须是ip地址,比如127.0.0.1
*/
var addressList = result.First().AddressList;
//var address = result.First().AddressList.FirstOrDefault(); var address = addressList.Any() ?
addressList.FirstOrDefault().ToString() :
result.First().HostName;
var port = result.First().Port; _userServiceUrl = $"http://{address}:{port}";
} [HttpGet]
public async Task<string> Get()
{
var service = await _dns.ResolveServiceAsync("service.consul", _options.Value.ServiceName);
var address = service.First().AddressList.FirstOrDefault();
var port = service.First().Port; var response = await _httpClient.GetAsync(_userServiceUrl + "/api/users");
if (response.StatusCode == HttpStatusCode.OK)
{
var result = await response.Content.ReadAsStringAsync();
return result;
}
return string.Empty;
}
}
运行执行成功
截至目前服务的注册和发现已经介绍完成了,那么最后来看看配置方式:
现在只有43.243.49.57这台服务器部署了User.Api
接下来的工作是
1:把Order.Api也部署在43.243.49.57上。用配置文件的方式注册服务
2:在39.105.144.51上用docker部署User.Api和Order.Api,用配置文件的方式注册服务
既然是docker。就必须要写dockerfile,既然是多个一起跑。就免不了docker-compose
这里就不放dockerfile了。后面源码会有,
直接放docker-compose
version: '' services:
order.api:
build:
context: Order.Api
dockerfile: dockerfile
container_name: 'orderapi'
restart: always
volumes:
- /volume/api/OrderApi/appsettings.json:/app/appsettings.json
ports:
- '6002:80'
user.api:
build:
context: User.Api
dockerfile: dockerfile
container_name: 'userapi'
restart: always
volumes:
- /volume/api/UserApi/appsettings.json:/app/appsettings.json
ports:
- '6001:80'
这里注意下:
数据挂载:appsettings.json 要提前创建,因为是映射的文件,如果当前不存在,会变成文件夹
平常我们一个项目打包的时候,一般都是docker-compose.yml和dockerfile在同一个目录的,
但这里是打包多个项目,要区分好路径,我这里的docker-compose.yml是在项目最外层的
dockerfile:是项目的dockerfile 路径
context:是上下文的路径 所以 dockerfile 必须在 User.Api下 即:User.Api/dockerfile 就是当前项目下 的路径
当我docker-compose up 的时候遇到了一个错误
大体意思就是地址无效,
如果大家是跟着上面来的。应该会记得,我在演示User.Api项目的时候是通过代码调用consul http api 注册服务的,
部署在了43.243.49.57上,我并没有把代码注释掉,当然,我数据挂载也是配置了文件的client注册地址的
既然遇到了,那么我们就一起来解决下,本来是想在39.105.144.51上的api都是通过配置注册的。
那就这样吧:39.105.144.51上的api,userapi通过http api注册,orderapi通过服务方式
因为在http api注册的时候,是通过获取程序运行的ip和端口注册的
我们在43.243.49.57 上跑userapi 是这样的,还记得吧 dotnet User.Api.dll --urls http://43.243.49.57:5001
当你没有指定程序运行的ip和端口肯定就是无效的,而抛出异常
这里要说明下:userapi只是注册失败,并不代表程序没跑起来
访问也是成功的
只是服务注册失败
尝试过几种方法都不行
比如:UseUrls("http://39.105.144.51:90")会提示 Cannot assign requested address,查了下资料好像是linux分配地址问题
当然这样就更不行了 UseUrls("http://*:6001")外网是可以访问,但注册是不行的
既然这样。那就不折腾了。都通过过配置的方式吧
用docker部署userapi和orderapi后,编写配置文件
{
"services":[
{
"ID":"UserService_39.105.144.51:6001",
"Name":"UserService",
"Tags":[
"UserApi",
"获取用户信息"
],
"Address":"39.105.144.51",
"Port":,
"Check":{
"HTTP":"http://39.105.144.51:6001/api/HealthCheck",
"Interval":"10s",
"DeregisterCriticalServiceAfter":"1m"
}
},
{
"id":"OrderService_39.105.144.51:6002",
"name":"OrderService",
"tags":[
"获取订单信息"
],
"Address":"39.105.144.51",
"Port":,
"Check":[
{
"HTTP":"http://39.105.144.51:6002/api/HealthCheck",
"Interval":"10s",
"DeregisterCriticalServiceAfter":"1m"
}
]
}
]
}
129.28.195.120是client,上面配置过
-config-dir=C:\consul\conf
那么就把这个json文件放到这个目录下,里面可以多个,
比如:order.json user.json 这样就可以根据名字来区分服务,修改起来也方便,consul启动的时候,会读取所有json文件
重启consul,查看webui页面
单击UserService进去,可以看到注册了2个服务,分别在不通的机器上
这样一个完整的consul集群就搭建好了
网关这一块 Gateway 用ocelot
添加nuget包:Ocelot.Provider.Consul
它包含了Consul,Ocelot,Ocelot.Provider.Consul
如果你是单独安装了Ocelot,那么就还得安装Ocelot.Provider.Consul
创建一个Ocelot.json,写入下面配置
测试下负载均衡,因为userapi有2台,所以配置2个
{
"ReRoutes": [
{
"DownstreamPathTemplate": "/api/users",
"DownstreamScheme": "http",
"LoadBalancerOptions": {
"Type": "LeastConnection"
},
"DownstreamHostAndPorts": [
{
"Host": "39.105.144.51",
"Port":
},
{
"Host": "43.243.49.57",
"Port":
}
],
"UpstreamPathTemplate": "/users",
"UpstreamHttpMethod": [ "Get" ]
//"AuthenticationOptions": {
// "AuthenticationProviderKey": "TestKey",
// "AllowedScopes": []
//}
}
],
"GlobalConfiguration": {
//这是暴露给外部的url
"BaseUrl": "http://localhost"
}
}
然后注册:
services.AddOcelot().AddConsul();
app.UseOcelot();
加载Ocelot.json配置,暴露81端口
运行测试,输入 http://localhost:81/users 多次刷新访问
会在2台电脑之前切换访问,达到了负载均衡的效果
源码:
https://github.com/byniqing/ConsulExample
Ocelot知识远不止这些,这里就不说了。具体自己看文档吧,
参考:
http://www.jessetalk.cn/2018/03/19/net-core-apigateway-ocelot-docs/
https://www.cnblogs.com/bossma/p/9756809.html
https://blog.csdn.net/weixin_33953249/article/details/88759709
https://www.cnblogs.com/RainingNight/p/servicediscovery-consul-in-asp-net-core.html
Ocelot+Consul 集群搭建实践的更多相关文章
- 8分钟学会Consul集群搭建及微服务概念
Consul介绍: Consul 是由 HashiCorp 公司推出的开源软件,用于实现分布式系统的服务发现与配置.与其他分布式服务注册与发现的方案,Consul 的方案更“一站式”,内置了服务注册与 ...
- Consul集群搭建 2Server+ 3Client
环境说明: 192.168.202.177 consul-server01 192.168.202.177 consul-server02192.168.202.174 mysql server no ...
- Consul集群搭建
一.集群搭建 准备三台机器 需要开启的端口,8300, 8301, 8500, 8600 机器1: 172.16.106.201 ./consul agent -server -bootstrap-e ...
- consul集群搭建以及ACL配置
由于时间匆忙,要是有什么地方没有写对的,请大佬指正,谢谢.文章有点水,大佬勿喷这篇博客不回去深度的讲解consul中的一些知识,主要分享的我在使用的时候的一些操作和遇见的问题以及解决办法.当然有些东西 ...
- Consul 集群搭建
搭建集群:.启动node1机器上的Consul (node1机器上执行) consul agent -data-dir /tmp/node1 -node=node1 -bind=192.168.0.1 ...
- consul集群搭建,配合nginx完成服务动态发现和健康检查
1.概述 1.1 介绍 consul是一个服务发现和配置共享的服务软件,结合nginx的主动健康检查模块nginx_upstream_check_module和服务发现模块nginx-upsync-m ...
- redis集群搭建实践
参考 第一个节点 第一个节点为本地的机器 IP:192.168.23.148 检查机器配置 $ uname -a Linux wangya-Lenovo-G480 4.8.0-52-generic # ...
- hadoop集群搭建实践
一.Linux配置1.设置hosts的ip(集群机器做同样操作)vi /etc/hosts192.168.91.129 master192.168.91.130 slave #互相ping通即可 pi ...
- 基于Docker的Consul服务发现集群搭建
在去年的.NET Core微服务系列文章中,初步学习了一下Consul服务发现,总结了两篇文章.本次基于Docker部署的方式,以一个Demo示例来搭建一个Consul的示例集群,最后给出一个HA的架 ...
随机推荐
- 多任务udp聊天器完整版
import socket import threading def send_msg(udp_socket,dest_ip,dest_port): while True: send_data = i ...
- [2019南昌邀请赛网络赛D][dp]
https://nanti.jisuanke.com/t/38223 Xiao Ming recently indulges in match stick game and he thinks he ...
- Linux命令的详解
cat /etc/passwd文件中的每个用户都有一个对应的记录行,记录着这个用户的一下基本属性.该文件对所有用户可读. /etc/shadow 文件正如他 ...
- WINDOWS 10下64位本地 ORACLE 11 G安装完整教程
URL:https://www.cnblogs.com/count-mjb/p/7655592.html wssbht = (DESCRIPTION = (ADDRESS_LIST = (ADDRES ...
- bzoj 4922: [Lydsy1706月赛]Karp-de-Chant Number 贪心+dp
题意:给定 $n$ 个括号序,让你从中选取一些括号序按照任意顺序拼接,最终生成一个合法的括号序列,求这个合法序列长度最大值. 题解:假设括号序列相对顺序固定,而我们要做的只是判断选还是不选的话可以转化 ...
- Ubuntu 18.04安装fcitx输入法
1.卸载ibus及所有组件 ----------------------------------------------------------------------------------- ro ...
- CF809E 【Surprise me!】
我们要求的柿子是张这样子的: \[\frac{1}{n * (n - 1)} * \sum_{i = 1}^n\sum_{j = 1}^{n}\phi(a_i*a_j)*dis(i, j)\] 其中\ ...
- 爬虫(十六):scrapy爬取知乎用户信息
一:爬取思路 首先我们应该找到一个账号,这个账号被关注的人和关注的人都相对比较多的,就是下图中金字塔顶端的人,然后通过爬取这个账号的信息后,再爬取他关注的人和被关注的人的账号信息,然后爬取被关注人的账 ...
- php 多维数组,根据某个特定字段过滤重复值
//假如 数据是这样的$arr=[ [ 'goods_name'=>'xxx', 'goods_id'=>111,],[ 'goods_name'=>'xxx', 'goods_id ...
- ROS中make_plan服务的使用
路径规划:从一个点到另一个点,规划出最优的路线.用到service :make_plan (nav_msgs/GetPlan) 服务名为move_base_node/make_plan nav_msg ...