FailOver的机制
package util
import (
"fmt"
"hash/crc32"
"math/rand"
"sort"
"time"
)
type HttpServer struct { //目标server类
Host string
Weight int
CWeight int //当前权重
Status string //健康检查
FailCount int //计数器,默认是0
SuccessCount int //检查到连续成功,当连续成功的次数达到这个值,把宕机的的机器的FailCount立刻重置为0,加快服务器启动速度
}
type HttpServers []*HttpServer
func (p HttpServers) Len() int { return len(p) }
func (p HttpServers) Less(i, j int) bool { return p[i].CWeight > p[j].CWeight }
func (p HttpServers) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func NewHttpServer(host string, weight int) *HttpServer {
return &HttpServer{Host: host, Weight: weight, CWeight: 0}
}
type LoadBalance struct { //负载均衡类
Servers HttpServers
CurIndex int //指向当前访问的服务器
}
func NewLoadBalance() *LoadBalance {
return &LoadBalance{Servers: make([]*HttpServer, 0)}
}
func (this *LoadBalance) AddServer(server *HttpServer) {
this.Servers = append(this.Servers, server)
}
func (this *LoadBalance) SelectForRand() *HttpServer {
rand.Seed(time.Now().UnixNano())
index := rand.Intn(len(this.Servers))
fmt.Println(index)
return this.Servers[index]
}
func (this *LoadBalance) SelectByIpHash(ip string) *HttpServer {
index := int(crc32.ChecksumIEEE([]byte(ip))) % len(this.Servers) //通过取余永远index都不会大于this.servers的长度
return this.Servers[index]
}
func (this *LoadBalance) SelectByWeight(ip string) *HttpServer { //加权随机算法
rand.Seed(time.Now().UnixNano())
index := rand.Intn(len(ServerIndices)) //这里因为权重表为15个1和5个0组成,所以产生0到19的随机数
fmt.Println(this.Servers[ServerIndices[index]])
return this.Servers[ServerIndices[index]] //通过随机数的索引获得服务器索引进而获得地址
}
func (this *LoadBalance) SelectByWeightBetter(ip string) *HttpServer {
rand.Seed(time.Now().UnixNano())
sumList := make([]int, len(this.Servers))
sum := 0
for i := 0; i < len(this.Servers); i++ {
sum += this.Servers[i].Weight
sumList[i] = sum
}
_rand := rand.Intn(sum)
for index, value := range sumList {
if _rand < value {
return this.Servers[index]
}
}
return this.Servers[0]
}
func (this *LoadBalance) RoundRobin() *HttpServer {
server := this.Servers[this.CurIndex]
//this.CurIndex ++
//if this.CurIndex >= len(this.Servers) {
// this.CurIndex = 0
//}
this.CurIndex = (this.CurIndex + 1) % len(this.Servers)
if server.Status == "Down" { //如果当前节点宕机了,则递归查找可以用的服务器
return this.RoundRobin()
}
return server
}
func (this *LoadBalance) RoundRobinByWeight() *HttpServer {
server := this.Servers[ServerIndices[this.CurIndex]]
this.CurIndex = (this.CurIndex + 1) % len(ServerIndices)
return server
}
func (this *LoadBalance) RoundRobinByWeight2() *HttpServer { //加权轮询 ,使用区间算法
server := this.Servers[0]
sum := 0
//3:1:1
for i := 0; i < len(this.Servers); i++ {
sum += this.Servers[i].Weight //第一次是3 [0,3) [3,4) [4,5)
if this.CurIndex < sum {
server = this.Servers[i]
if this.CurIndex == sum-1 && i != len(this.Servers)-1 {
this.CurIndex++
} else {
this.CurIndex = (this.CurIndex + 1) % sum //这里是重要的一步
}
fmt.Println(this.CurIndex)
break
}
}
return server
}
func (this *LoadBalance) RoundRobinByWeight3() *HttpServer { //平滑加权轮询
for _, s := range this.Servers {
s.CWeight = s.CWeight + s.Weight
}
sort.Sort(this.Servers)
max := this.Servers[0]
max.CWeight = max.CWeight - SumWeight
return max
}
var LB *LoadBalance
var ServerIndices []int
var SumWeight int
func checkServers(servers HttpServers) {
t:= time.NewTicker(time.Second*3)
check:=NewHtttpChecker(servers)
for {
select{
case <- t.C:
check.Check(time.Second*2)
for _,s:=range servers{
fmt.Println(s.Host,s.Status,s.FailCount)
}
fmt.Println("---------------------------------")
}
}
}
func init() {
LB = NewLoadBalance()
LB.AddServer(NewHttpServer("http://localhost:12346", 3)) //web1
LB.AddServer(NewHttpServer("http://localhost:12347", 1)) //web2
LB.AddServer(NewHttpServer("http://localhost:12348", 1)) //web2
for index, server := range LB.Servers {
if server.Weight > 0 {
for i := 0; i < server.Weight; i++ {
ServerIndices = append(ServerIndices, index)
}
}
SumWeight = SumWeight + server.Weight //计算加权总和
}
go checkServers(LB.Servers)
//fmt.Println(ServerIndices)
}
package util
import (
"net/http"
"time"
)
type HttpChecker struct {
Servers HttpServers
FailMax int
RecovCount int //连续成功到达这个值,就会被标识为UP
}
func NewHtttpChecker(servers HttpServers) *HttpChecker {
return &HttpChecker{Servers: servers, FailMax: 6, RecovCount: 3}
}
func (this *HttpChecker) Check(timeout time.Duration) {
client := http.Client{}
for _, server := range this.Servers {
res, err := client.Head(server.Host)
if res != nil {
defer res.Body.Close()
}
if err != nil { //宕机了
this.Fail(server)
continue
}
if res.StatusCode >= 200 && res.StatusCode < 400 {
this.Success(server)
} else {
this.Fail(server)
}
}
}
func (this *HttpChecker) Fail(server *HttpServer) {
if server.FailCount >= this.FailMax { //超过阈值
server.Status = "DOWN"
} else {
server.FailCount++
}
server.SuccessCount = 0
}
func (this *HttpChecker) Success(server *HttpServer) {
if server.FailCount > 0 {
server.FailCount--
server.SuccessCount++
if server.SuccessCount == this.RecovCount {
server.FailCount = 0
server.Status = "UP"
server.SuccessCount = 0
}
} else {
server.Status = "UP"
}
}
FailOver的机制的更多相关文章
- MySQL Proxy和 Amoeba 工作机制浅析
MySQL Proxy处于客户端应用程序和MySQL服务器之间,通过截断.改变并转发客户端和后端数据库之间的通信来实现其功能,这和WinGate 之类的网络代理服务器的基本思想是一样的.代理服务器是和 ...
- Hadoop学习笔记—15.HBase框架学习(基础知识篇)
HBase是Apache Hadoop的数据库,能够对大型数据提供随机.实时的读写访问.HBase的目标是存储并处理大型的数据.HBase是一个开源的,分布式的,多版本的,面向列的存储模型,它存储的是 ...
- Thrift 个人实战--Thrift 服务化 Client的改造
前言: Thrift作为Facebook开源的RPC框架, 通过IDL中间语言, 并借助代码生成引擎生成各种主流语言的rpc框架服务端/客户端代码. 不过Thrift的实现, 简单使用离实际生产环境还 ...
- HBase replication
Hbase Replication 介绍 现状 Hbase 的replication目前在业界使用并不多见,原因有很多方面,比如说HDFS目前已经有多份备份在某种程度上帮助HBASE底层数据的安全性, ...
- Apache-Flink深度解析-State
摘要: 实际问题 在流计算场景中,数据会源源不断的流入Apache Flink系统,每条数据进入Apache Flink系统都会触发计算.如果我们想进行一个Count聚合计算,那么每次触发计算是将历史 ...
- Mysql读写分离方案-Amoeba环境部署记录
Mysql的读写分离可以使用MySQL Proxy,也可以使用Amoeba.Amoeba(变形虫)项目是一个类似MySQL Proxy的分布式数据库中间代理层软件,是由陈思儒开发的一个开源的java项 ...
- Others-阿里专家强琦:流式计算的系统设计和实现
阿里专家强琦:流式计算的系统设计和实现 更多深度文章,请关注云计算频道:https://yq.aliyun.com/cloud 阿里云数据事业部强琦为大家带来题为“流式计算的系统设计与实现”的演讲,本 ...
- MongoDB 走马观花(全面解读篇)
目录 一.简介 二.基本模型 BSON 数据类型 分布式ID 三.操作语法 四.索引 索引特性 索引分类 索引评估.调优 五.集群 分片机制 副本集 六.事务与一致性 一致性 小结 一.简介 Mong ...
- 了解 MongoDB 看这一篇就够了【华为云技术分享】
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/devcloud/article/detai ...
随机推荐
- 二、SpringBoot基础配置
目录 2.1 @SpringBootApplication 2.3 服务器配置 2.4 修改启动banner 小结 2.1 @SpringBootApplication 从上篇文章中知道@Spring ...
- drf复习(一)--原生djangoCBV请求生命周期源码分析、drf自定义配置文件、drf请求生命周期dispatch源码分析
admin后台注册model 一.原生djangoCBV请求生命周期源码分析 原生view的源码路径(django/views/generic/base.py) 1.从urls.py中as_view ...
- String和Irreducible Polynomial(2019牛客暑期多校训练营(第七场))
示例: 输入: 4000010010111011110 输出: 00001001 0111 01111 0 题意:给出一个只含有0和1的字符串,找出一种分割方法,使得每个分割出的字符串都是在该字符串自 ...
- Linux忘记root密码操作方法
此方法为:进入单用户模式,直接修改新密码覆盖掉以前的root密码. 操作步骤: 1.进入单用户模式 2.修改root密码 1.进入单用户方法: 1)启动Linux时,通过按上下键(其他键也可以)让Li ...
- Golang 实现单例模式
目录 只适用于单线程环境 支持并发版本 优化并发版本 sync.Once版本 只适用于单线程环境 package main import "fmt" type Single str ...
- 3. Spark SQL解析
3.1 新的起始点SparkSession 在老的版本中,SparkSQL提供两种SQL查询起始点,一个叫SQLContext,用于Spark自己提供的SQL查询,一个叫HiveContext,用于连 ...
- L2R 三:常用工具包介绍之 XGBoost与LightGBM
L2R最常用的包就是XGBoost 和LightGBM,xgboost因为其性能及快速处理能力,在机器学习比赛中成为常用的开源工具包, 2016年微软开源了旗下的lightgbm(插句题外话:微软的人 ...
- ADO.NET 四(DataReader)
DataReader 类概述 DataReader 类对应MSSQLSERVER在 System.Data.SqlClient 命名空间中,对应的类是 SqlDataReader,主要用于读取表中的查 ...
- Asp.Net Core File的操作
FileOption 内置类(通过服务注入) 该操作类的功能是实现对文件的删除,修改查询功能,该类基本完成了对文件的操作,同样是用最简单的代码实现了文件操作功能.
- Django:母版、继承、组件、自定义标签
1.for循环应用 1.1for Variable Description forloop.counter 当前循环的索引值(从1开始) forloop.counter0 当前循环的索引值(从0开始) ...