一般应用服务都会部署到多台服务器之上,一、可以通过硬件得到更多的并发处理能力;二、可以避免单点太故障的出现,从而确保服务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服务集群的更多相关文章

  1. .net core下简单构建高可用服务集群

    一说到集群服务相信对普通开发者来说肯定想到很复杂的事情,如zeekeeper ,反向代理服务网关等一系列的搭建和配置等等:总得来说需要有一定经验和规划的团队才能应用起来.在这文章里你能看到在.net ...

  2. .net core 跨平台开发 微服务架构 基于Nginx反向代理 服务集群负载均衡

    1.概述 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客 ...

  3. Dapr + .NET Core实战(十一)单机Dapr集群

    如何单机部署Dapr集群 第十篇讲过了K8S集群下如何使用Dapr运行程序,但是很多人一直在问如何单机下进行Dapr的负载,这节课我们来聊聊如何单机进行Dapr的负载. 首先要说的是单机下,通过 da ...

  4. Dapr + .NET Core实战(十一)单机Dapr集群负载均衡

    如何单机部署Dapr集群 第十篇讲过了K8S集群下如何使用Dapr运行程序,但是很多人一直在问如何单机下进行Dapr的负载,这节课我们来聊聊如何单机进行Dapr的负载. 首先要说的是单机下,通过 da ...

  5. Dapr + .NET Core实战(十四)虚拟机集群部署 mDNS + Consul

    前面我们说了在单机模式下和K8S集群下的Dapr实战,这次我们来看看如何在不使用K8S的情况下,在一个传统的虚拟机集群里来部署Dapr. 1.环境准备 我们准备两台centos7虚拟机 Dapr1:1 ...

  6. 数据库选型之亿级数据量并发访问(MySQL集群)

    刘 勇  Email:lyssym@sina.com 简介 针对实际应用中并发访问MySQL的场景,本文采用多线程对MySQL进行并发读取访问,其中以返回用户所需的数据并显示在终端为测试结束节点,即将 ...

  7. Spring Cloud - Nacos注册中心入门单机模式及集群模式

    近几年微服务很火,Spring Cloud提供了为服务领域的一整套解决方案.其中Spring Cloud Alibaba是我们SpringCloud的一个子项目,是提供微服务开发的一站式解决方案. 包 ...

  8. SpringCloud(四):服务注册中心Eureka Eureka高可用集群搭建 Eureka自我保护机制

    第四章:服务注册中心 Eureka 4-1. Eureka 注册中心高可用集群概述在微服务架构的这种分布式系统中,我们要充分考虑各个微服务组件的高可用性 问题,不能有单点故障,由于注册中心 eurek ...

  9. 联想企业网盘:SaaS服务集群化持续交付实践

    1      前言 当代信息技术飞速发展,软件和系统的代码规模都变得越来越大,而且组件众多,依赖繁复,每次新版本的发布都仿佛是乘坐一次无座的绿皮车长途夜行,疲惫不堪.软件交付是一个复杂的工程,涉及到软 ...

随机推荐

  1. python生产环境部署

    Python部署web开发程序的几种方法 fastcgi ,通过flup模块来支持,在nginx里对应的配置指令是 fastcgi_pass http,nginx使用proxy_pass转发,这个要求 ...

  2. BZOJ_1500_[NOI2005]维修数列_splay

    BZOJ_1500_[NOI2005]维修数列_splay 题意: 分析: 节点维护从左开始的最大连续子段和,从右开始的最大连续子段和,区间的最大连续子段和 插入:重新建一棵树,把pos旋到根,把po ...

  3. Java IO--字符流--BufferedReader和BufferedWriter

    从昨天开始没事情干时,决定梳理梳理Java IO流,因为觉得太混乱这个东西,妈的,咋就这么多类型,想累死谁啊,这里并不是埋怨创造者,而是气自己看着看着老跑偏,实在看不进去,太多了,想睡觉,所以现在决定 ...

  4. POI读取excel文件。

    1) poi读取现成.xls文件,不需要自己建立.xls ====ReadExcel​类​==== package cust.com.excelToDataTest; import java.io.F ...

  5. MDK5使用Jlink下载显示 no cortex m sw divice 解决办法

    问题: (1)下面界面中找不到设备 (2)下载程序的时候提示" no cortex m sw divice " 然后是"target dll has been cance ...

  6. Ubuntu18.04(linux)安装MySQL

    安装 mysql sudo apt-get --purge remove mysql-server mysql-common mysql-client sudo apt-get install mys ...

  7. Asp.NETCore轻松学系列阅读指引目录

    前言 耗时两个多月,坚持写这个入门系列文章,就是想给后来者更好更快的上手体验,这个系列可以说是从入门到进阶,适合没有 .NETCore 编程经验到小白同学,也适合从 .NET Framework 迁移 ...

  8. 浅谈MySQL架构体系

    一  数据库和数据库实例 在MySQL的学习研究中,存在两个非常容易混淆的概念,即数据库和数据库实例.在MySQL中,数据库和数据库实例定义如下: 数据库:存储数据的集合: 数据库实例:操作数据库的集 ...

  9. .Net Core ORM选择之路,哪个才适合你

    因为老板的一句话公司项目需要迁移到.Net Core ,但是以前同事用的ORM不支持.Net Core 开发过程也遇到了各种坑,插入条数多了也特别的慢,导致系统体验比较差好多都改写Sql实现. 所以我 ...

  10. TCP的三次握手与四次挥手

    TCP的三次握手与四次挥手 一.TCP(Transmission Control Protocol 传输控制协议) TCP是面向对连接,可靠的进程到进程通信的协议 TCP是提供全双工服务,即数据可在同 ...