在dotnet core下去中心化访问HTTP服务集群
一般应用服务都会部署到多台服务器之上,一、可以通过硬件得到更多的并发处理能力;二、可以避免单点太故障的出现,从而确保服务7X24有效运作。当访问这些HTTP服务的情况一般都是经过反向代理服务进行统一处理,这样的好处就访问透明化,统一管理和控制。但存在的问题就是服务处理延时加大,还有就是对小团或公司来说可能没有专门的技术人来规划和管理这些代理服务。接下一来讲一下在.net core下更轻更的一种处理方案,这种方案通过Client自身的功能实现集群化的HTTP服务访问,通过故障迁移和权重分配达到一个无中心化灵活的HTTP集群服务访问(通过它还能访问所有非.net core的HTTP服务)
场景定义
首先有以下一个asp.net core mvc服务
public class HomeController : Controller
{
[HttpPost]
public int EmployeeAdd([FromBody]List<Employee> items)
{
return items == null ? : items.Count;
} [HttpPost]
public Employee EmployeeEdit(int id, [FromBody]Employee emp)
{
Employee record = DataHelper.Employees.Find(e => e.EmployeeID == id);
if (record != null)
{
record.City = emp.City;
record.Address = emp.Address;
record.Title = emp.Title;
record.HomePhone = emp.HomePhone;
return record;
}
return null;
} public object EmployeesGetName()
{
return from e in DataHelper.Employees select new { ID = e.EmployeeID, Name = e.FirstName + " " + e.LastName };
} public object Customers(int count)
{
List<Customer> result = new List<Customer>();
if (count > DataHelper.Customers.Count)
count = DataHelper.Customers.Count;
for (int i = ; i < count; i++)
{
result.Add(DataHelper.Customers[i]);
}
return result;
} public object CustomersGetName()
{
return from c in DataHelper.Customers select new { ID = c.CustomerID, Name = c.CompanyName };
} }
代码简化了一下,正常API的服务都部署在多台服务器构建应用集群,一般情况都是通过nginx或其他反向代理服务器接管Client的请求,然后针对负载配置进行转发处理。但接下来需要讲解的是通过开源组件实现无中心化的集群负载调用。
引用组件
首先net core的http client组件并不具这一功能,所以需要引用第三方的一个开源组件BeetleX(组件暂只支持net core 2.1或更高版本) 
定义访问接口
组件支持通过接口的方式来描述HTTP接口服务,接口的访问方式对使用和维护都具有着极大的便利性,以下是针对以上服务描述的接口
[JsonFormater]
[Controller(BaseUrl = "Home")]
public interface IDataService
{
[Get]
Task<DateTime> GetTime();
[Get]
Task<string> Hello(string name);
[Get]
Task<bool> Login(string name, string pwd);
[Get]
Task<List<Employee>> Employees();
[Get]
Task<Employee> EmployeeGet(int id);
[Post]
Task<int> EmployeeAdd(params Employee[] items);
[Post]
Task<Employee> EmployeeEdit([CQuery]int id, Employee emp);
[Get]
Task<List<EmployeeName>> EmployeesGetName();
[Get]
Task<List<Customer>> Customers(int count);
[Get]
Task<List<CustomerName>> CustomersGetName();
[Get]
Task<List<Order>> Orders(int? employeeid, string customerid, int index, int size);
}
组件支持Task和非Task返回值的方法定义,由于基础网络访问是基于异步,所以最好还是定义Task返回值的方法。如果定义了非Task返回值访问组件内部会同步等待完成返回,在并发服务下这不利于线程资源的利用。
集群化访问定义
接口定义好之后,就可以通过接口来调用并把请求调用负载到不同服务器的服务上。这样做首先需要定义一个集群化服务访问对象:
private static HttpClusterApi HttpClusterApi = new HttpClusterApi();
HttpClusterApi对象是线程安全的,所以定义成静态即可;也可以根据服务分类来定义不同的HttpClusterApi(之于内部的工作原理这里就不详细解说了,可以到GitHub上过一步了解)。创建了集群接口对象之后就可以用它来创建接口实例。
private static IDataService DataService; DataService = HttpClusterApi.Create<IDataService>();
同样接口实例也是线程安的,只需要创建一个即可在不同线程和方法里同时调用。其实这样创建接口后还没能正常使用,因为没有定义相应服务地址,可以通过HttpClusterApi添加不同服务地址:
HttpClusterApi.AddHost("*", Host25, Host29);
以上是所有请求都负载到Host25和Host29,一般情况都不会直这样定义;*的优先级是最低的,只有没有匹配到其他url描述的情况才会匹配*
平均负载
平均负载是一种最常用的方式,主要是把并发请求平均到不同的服务器上;以下是针对employee相关请求的地址负载到5个服务上.
HttpClusterApi.AddHost("employee.*", Host26, Host27, Host28, Host29, Host30);
接下简单地测试一下
System.Threading.ThreadPool.QueueUserWorkItem(async (o) =>
{
while (true)
{
try
{
await DataService.EmployeeGet();
}
catch (Exception e_)
{
Console.WriteLine(e_.Message);
}
}
});
测试结果:

从测试打印信息来看,基本上把请求平均到不同的服务器上,5台服务器的权重值都是10.
权重定义
现实中由于服务器配置不同,服务器运行的服务也有所差异,所以一般情况都不会平均化负载;这时候权重定义就起到一个非常重要的作用,针对不同地址的服务制定不同的重权值这样可以让服务资源得到更好地利用!接下来还是针对以上测试代码,针对不同的服务器设置不同的权重
HttpClusterApi.GetUrlNode("employee.*").Add(new string[] { Host26, Host27, Host28 }).Add(Host29,).Add(Host30,);
以上代码分别把Host29和Host30的权重设置为5其他均为10.

定义备份节点
所谓的备份节点,其实就是不参与负载处理,但所有可用点都故障的情况,备份节点就生效。其实在组件中没有所谓的备份节点,不过可以通过0权重这个值来实现。当存在其他重权的节点可用时,0权重的节点是不会存在于重权表中的,只有当所有节点不可用的情况下,0权重的节点才会移入到权重表;当有效节点恢复后0权重的节点也会被移出权重表。
故障迁移和恢复
组件会自动把存在N次连接错的服务地址在权重表中排除出去,所以当服务不可用的情况会短暂有部分请求会引发访问异常;接下来组件会每隔一段时间去检测有问题的服务地址,直到服务连接可用的情况才会把服务地址重新添加回重权表里接受负载轮循处理。
自定义集群信息源
如果在代码中把负载设置写死了,那到增加节点的时候就非常麻烦需要重新发布程序;组件为了解决这一问题制定了一个接口方便使用者制定自己的集群信息来源配置。通过实现INodeSourceHandler并设置到HttpClusterApi即可以动态更新节点信息便于更改和管理。以下是针对负载源实现的一个HTTP获取负载源信息实现
public class HTTPRemoteSourceHandler : INodeSourceHandler
{
private HttpClusterApi mHttpClusterApi = new HttpClusterApi(); private IHttpSourceApi mRemoteSourceApi; public HTTPRemoteSourceHandler(string name, params string[] hosts)
{
mHttpClusterApi.AddHost("*", hosts);
mRemoteSourceApi = mHttpClusterApi.Create<IHttpSourceApi>();
Name = name;
} public string Name { get; set; } public int UpdateTime { get; set; } = ; public Task<ApiClusterInfo> Load()
{
return mRemoteSourceApi._GetCluster(Name);
}
}
实现是每5秒钟检则一下信息源,集成到HttpClusterApi如下:
HTTPRemoteSourceHandler remoteSourceHandler = new HTTPRemoteSourceHandler("default", "http://localhost:8080");
HttpClusterApi.NodeSourceHandler = remoteSourceHandler;
var result = await HttpClusterApi.LoadNodeSource();
设置INodeSourceHandler后组件就会检配置信息,检测错误或版本没有变化的情况就不会更新配置。以下是针对测编写的一个HTTP配置服务:

如果想得到更详细的代码可以访问 https://github.com/IKende/FastHttpApi
在dotnet core下去中心化访问HTTP服务集群的更多相关文章
- .net core下简单构建高可用服务集群
一说到集群服务相信对普通开发者来说肯定想到很复杂的事情,如zeekeeper ,反向代理服务网关等一系列的搭建和配置等等:总得来说需要有一定经验和规划的团队才能应用起来.在这文章里你能看到在.net ...
- .net core 跨平台开发 微服务架构 基于Nginx反向代理 服务集群负载均衡
1.概述 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客 ...
- Dapr + .NET Core实战(十一)单机Dapr集群
如何单机部署Dapr集群 第十篇讲过了K8S集群下如何使用Dapr运行程序,但是很多人一直在问如何单机下进行Dapr的负载,这节课我们来聊聊如何单机进行Dapr的负载. 首先要说的是单机下,通过 da ...
- Dapr + .NET Core实战(十一)单机Dapr集群负载均衡
如何单机部署Dapr集群 第十篇讲过了K8S集群下如何使用Dapr运行程序,但是很多人一直在问如何单机下进行Dapr的负载,这节课我们来聊聊如何单机进行Dapr的负载. 首先要说的是单机下,通过 da ...
- Dapr + .NET Core实战(十四)虚拟机集群部署 mDNS + Consul
前面我们说了在单机模式下和K8S集群下的Dapr实战,这次我们来看看如何在不使用K8S的情况下,在一个传统的虚拟机集群里来部署Dapr. 1.环境准备 我们准备两台centos7虚拟机 Dapr1:1 ...
- 数据库选型之亿级数据量并发访问(MySQL集群)
刘 勇 Email:lyssym@sina.com 简介 针对实际应用中并发访问MySQL的场景,本文采用多线程对MySQL进行并发读取访问,其中以返回用户所需的数据并显示在终端为测试结束节点,即将 ...
- Spring Cloud - Nacos注册中心入门单机模式及集群模式
近几年微服务很火,Spring Cloud提供了为服务领域的一整套解决方案.其中Spring Cloud Alibaba是我们SpringCloud的一个子项目,是提供微服务开发的一站式解决方案. 包 ...
- SpringCloud(四):服务注册中心Eureka Eureka高可用集群搭建 Eureka自我保护机制
第四章:服务注册中心 Eureka 4-1. Eureka 注册中心高可用集群概述在微服务架构的这种分布式系统中,我们要充分考虑各个微服务组件的高可用性 问题,不能有单点故障,由于注册中心 eurek ...
- 联想企业网盘:SaaS服务集群化持续交付实践
1 前言 当代信息技术飞速发展,软件和系统的代码规模都变得越来越大,而且组件众多,依赖繁复,每次新版本的发布都仿佛是乘坐一次无座的绿皮车长途夜行,疲惫不堪.软件交付是一个复杂的工程,涉及到软 ...
随机推荐
- syncer.go
package ) ) ) ].Key,)) )) }
- 协同过滤的R语言实现及改进
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 协同过滤算法是推荐系统最常用的算法之一,本文将介绍一种方法来使它可以在大型数据集上快速训练. 协同过滤算法(CF)是构建推荐系统时最常用的技 ...
- 我和Python的Py交易》》》》》》 浮点数的身世字谜
什么是浮点数? 在数据类型中写道,浮点数是带小数点的小数,这个概念是不准确的:浮点数是除了无限不循环小数之外的小数,也就是可以用分数表示的带小数点的数. 好了,浮点数就这些内容,讲完了,各回各家,各找 ...
- springboot mybatis 多数据源配置
首先导入mybatis等包,这里就不多说. 下面是配置多数据源和mybatis,每个数据源对应一套mybatis模板 数据源1: package com.aaaaaaa.config.datasour ...
- java quartz 计算近20次执行时间
/** * * @desc 计算表达式近20次时间 * @auth josnow * @date 2017年5月31日 下午12:16:25 * @param cron * @return */ pu ...
- Python多版本管理-pyenv
经常遇到这样的情况: 系统自带的Python是2.x,自己需要Python 3.x,此时需要在系统中安装多个Python,但又不能影响系统自带的Python,即需要实现Python的多版本共存,pye ...
- PwnAuth——一个可以揭露OAuth滥用的利器
一.简介 鱼叉式网络钓鱼攻击被视为企业最大的网络威胁之一.只需要一名员工输入自己的凭证或运行一些恶意软件,整个企业都会受到威胁.因此,公司投入大量资源来防止凭证收集和有效载荷驱动的社会工程攻击.然而, ...
- 发现了一个非常棒的pyqt5的例子集
发现了一个非常棒的pyqt5的例子集 https://github.com/892768447/PyQt 各种各样的PyQt测试和例子 [Python3.4.4 or Python3.5][PyQt5 ...
- TensorFlow之CNN:运用Batch Norm、Dropout和早停优化卷积神经网络
学卷积神经网络的理论的时候,我觉得自己看懂了,可是到了用代码来搭建一个卷积神经网络时,我发现自己有太多模糊的地方.这次还是基于MINIST数据集搭建一个卷积神经网络,首先给出一个基本的模型,然后再用B ...
- 干货!分享一款windows下的磁盘分析神器。
作为开发人员的你,肯定遇到过这样的情况,120G SSD系统盘居然满载了,到底是被哪些程序占用了,包含哪些大文件,这个时候脑袋里就开始回忆了.....这对平时没有养成规范化记录安装软件好习惯的同学而言 ...