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

    1.try-catch e.printStackTrace(); 会打印出方法的调用痕迹,如此例,会打印出异常开始于TestException的第16行,这样就便于定位和分析到底哪里出了异常 2.使用 ...

  2. Instrumentation(1)

    Instrumentation介绍: JavaInstrumentation指的是可以用独立于应用程序之外的代理(agent)程序来监测和协助运行在JVM上的应用程序.这种监测和协助包括但不限于获取J ...

  3. 【cogs 775】山海经 ——Segment Tree

    题目链接:      TP 题解:   我数据结构真心是弱啊= =. 线段树好厉害啊,一直不会区间最大连续和,今天刚学习了一下233. 维护前缀最大和后缀最大,越界最大(?),再维护一个区间最大,瞎搞 ...

  4. BZOJ_3669_[Noi2014]魔法森林_LCT

    BZOJ_3669_[Noi2014]魔法森林_LCT Description 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节 ...

  5. BZOJ_3747_[POI2015]Kinoman_线段树

    BZOJ_3747_[POI2015]Kinoman_线段树 Description 共有m部电影,编号为1~m,第i部电影的好看值为w[i]. 在n天之中(从1~n编号)每天会放映一部电影,第i天放 ...

  6. 【Unity游戏开发】AssetBundle杂记--AssetBundle的二三事

    一.简介 马三在公司大部分时间做的都是游戏业务逻辑和编辑器工具等相关工作,因此对Unity AssetBundle这块的知识点并不是很熟悉,自己也是有打算想了解并熟悉一下AssetBundle,掌握一 ...

  7. JS基础:常用API

    全局属性 typeof() 检测数据类型 parseInt() 从字符串解析一个整数 parseFloat() 从字符串解析一个小数 Number() 强制类型转换为数字 String() 强制类型转 ...

  8. 不使用SpringBoot如何将原生Feign集成到Spring中来简化http调用

    在微服务架构中,如果使用得是SpringCloud,那么只需要集成SpringFeign就可以了,SpringFeign可以很友好的帮我们进行服务请求,对象解析等工作. 然而SpingCloud是依赖 ...

  9. Spring 系列之Spring常用注解总结

    传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop.实物,这么做有两个缺点: 1.如果所有的内容都配置在.xml文件中,那么.xml文件将会十分庞大:如果按需求分开.xml文 ...

  10. Python从入门到放弃

    计算机基础 01 计算机基础之编程 02 计算机组成原理 03 计算机操作系统 04 编程语言分类 Python解释器 05 Python和Python解释器 06 执行Python程序的两种方式 0 ...