您正在查看: Other-经验分享 分类下的文章

负载均衡Nginx、HAProxy和LVS

Nginx

Nginx优点:

1、工作在网络7层之上,可针对http应用做一些分流的策略,如针对域名、目录结构,它的正规规则比HAProxy更为强大和灵活,所以,目前为止广泛流行。

2、Nginx对网络稳定性的依赖非常小,理论上能ping通就能进行负载功能。

3、Nginx安装与配置比较简单,测试也比较方便,基本能把错误日志打印出来。

4、可以承担高负载压力且稳定,硬件不差的情况下一般能支撑几万次的并发量,负载度比LVS小。

5、Nginx可以通过端口检测到服务器内部的故障,如根据服务器处理网页返回的状态码、超时等,并会把返回错误的请求重新提交到另一个节点。

6、不仅仅是优秀的负载均衡器/反向代理软件,同时也是强大的Web应用服务器。LNMP也是近些年非常流行的Web架构,在高流量环境中稳定性也很好。

7、可作为中层反向代理使用。

8、可作为静态网页和图片服务器。

9、Nginx社区活跃,第三方模块非常多,相关的资料在网上比比皆是。

Nginx常规的和HTTP请求和相应流程图:

做负载均衡Nginx、HAProxy和LVS总有一个适合你

Nginx缺点:

1、适应范围较小,仅能支持http、https、Email协议。

2、对后端服务器的健康检查,只支持通过端口检测,不支持url来检测。比如用户正在上传一个文件,而处理该上传的节点刚好在上传过程中出现故障,Nginx会把上传切到另一台服务器重新处理,而LVS就直接断掉了,如果是上传一个很大的文件或者很重要的文件的话,用户可能会因此而不满。

LVS

LVS优点:

1、抗负载能力强、是工作在网络4层之上仅作分发之用,没有流量的产生,这个特点也决定了它在负载均衡软件里的性能最强的,对内存和cpu资源消耗比较低。

2、配置性比较低,这是一个缺点也是一个优点,因为没有可太多配置的东西,所以并不需要太多接触,大大减少了人为出错的几率。

3、工作稳定,因为其本身抗负载能力很强,自身有完整的双机热备方案,如LVS+Keepalived,不过我们在项目实施中用得最多的还是LVS/DR+Keepalived。

4、无流量,LVS只分发请求,而流量并不从它本身出去,这点保证了均衡器IO的性能不会收到大流量的影响。

5、应用范围比较广,因为LVS工作在4层,所以它几乎可以对所有应用做负载均衡,包括http、数据库、在线聊天室等等。

LVS DR(Direct Routing)模式的网络流程图:

做负载均衡Nginx、HAProxy和LVS总有一个适合你

LVS的缺点:

1、软件本身不支持正则表达式处理,不能做动静分离;而现在许多网站在这方面都有较强的需求,这个是Nginx/HAProxy+Keepalived的优势所在。

2、如果是网站应用比较庞大的话,LVS/DR+Keepalived实施起来就比较复杂了,特别后面有Windows Server的机器的话,如果实施及配置还有维护过程就比较复杂了,相对而言,Nginx/HAProxy+Keepalived就简单多了。

HAProxy

HAProxy优点:

1、HAProxy是支持虚拟主机的,可以工作在4、7层(支持多网段)

2、HAProxy的优点能够补充Nginx的一些缺点,比如支持Session的保持,Cookie的引导;同时支持通过获取指定的url来检测后端服务器的状态。

3、HAProxy跟LVS类似,本身就只是一款负载均衡软件;单纯从效率上来讲HAProxy会比Nginx有更出色的负载均衡速度,在并发处理上也是优于Nginx的。

4、HAProxy支持TCP协议的负载均衡转发,可以对MySQL读进行负载均衡,对后端的MySQL节点进行检测和负载均衡,大家可以用LVS+Keepalived对MySQL主从做负载均衡。

5、HAProxy负载均衡策略非常多,HAProxy的负载均衡算法现在具体有如下8种

① roundrobin

表示简单的轮询,每个服务器根据权重轮流使用,在服务器的处理时间平均分配的情况下这是最流畅和公平的算法。该算法是动态的,对于实例启动慢的服务器权重会在运行中调整。最大支持4095个后端主机;

② leastconn

连接数最少的服务器优先接收连接。leastconn建议用于长会话服务,例如LDAP、SQL、TSE等,而不适合短会话协议。如HTTP.该算法是动态的,对于实例启动慢的服务器权重会在运行中调整。

③ static-rr

每个服务器根据权重轮流使用,类似roundrobin,但它是静态的,意味着运行时修改权限是无效的。另外,它对服务器的数量没有限制。该算法一般不用;

④ source

对请求源IP地址进行哈希,用可用服务器的权重总数除以哈希值,根据结果进行分配。只要服务器正常,同一个客户端IP地址总是访问同一个服务器。如果哈希的结果随可用服务器数量而变化,那么客户端会定向到不同的服务器;该算法一般用于不能插入cookie的Tcp模式。它还可以用于广域网上为拒绝使用会话cookie的客户端提供最有效的粘连;该算法默认是静态的,所以运行时修改服务器的权重是无效的,但是算法会根据“hash-type”的变化做调整。

⑤ uri

表示根据请求的URI左端(问号之前)进行哈希,用可用服务器的权重总数除以哈希值,根据结果进行分配。只要服务器正常,同一个URI地址总是访问同一个服务器。一般用于代理缓存和反病毒代理,以最大限度的提高缓存的命中率。该算法只能用于HTTP后端;该算法一般用于后端是缓存服务器;该算法默认是静态的,所以运行时修改服务器的权重是无效的,但是算法会根据“hash-type”的变化做调整。

⑥ url_param

在HTTP GET请求的查询串中查找中指定的URL参数,基本上可以锁定使用特制的URL到特定的负载均衡器节点的要求;该算法一般用于将同一个用户的信息发送到同一个后端服务器;该算法默认是静态的,所以运行时修改服务器的权重是无效的,但是算法会根据“hash-type”的变化做调整。

⑦ hdr(name)

在每个HTTP请求中查找HTTP头,HTTP头将被看作在每个HTTP请求,并针对特定的节点;如果缺少头或者头没有任何值,则用roundrobin代替;该算法默认是静态的,所以运行时修改服务器的权重是无效的,但是算法会根据“hash-type”的变化做调整。

⑧ rdp-cookie(name)

为每个进来的TCP请求查询并哈希RDP cookie;该机制用于退化的持久模式,可以使同一个用户或者同一个会话ID总是发送给同一台服务器。如果没有cookie,则使用roundrobin算法代替;该算法默认是静态的,所以运行时修改服务器的权重是无效的,但是算法会根据“hash-type”的变化做调整。

haproxy的工作模型图:

做负载均衡Nginx、HAProxy和LVS总有一个适合你

HAPorxy缺点:

  1. 不支持POP/SMTP协议

  2. 不支持SPDY协议

  3. 不支持HTTP cache功能。现在不少开源的lb项目,都或多或少具备HTTP cache功能。

  4. 重载配置的功能需要重启进程,虽然也是soft restart,但没有Nginx的reaload更为平滑和友好。

  5. 多进程模式支持不够好
    原文链接:https://blog.csdn.net/qlj324513/article/details/81541282

Ubuntu18.04上源码安装Haproxy2.x

准备编译安装HAProxy的基础环境

sudo apt install make gcc build-essential libssl-dev zlib1g-dev libpcre3 libpcre3-dev libsystemd-dev libreadline-dev -y

编译安装lua

lua为HAProxy支持基于其实现功能扩展
注:HAProxy要求的lua最低版本为5.3

sudo wget -P /usr/local/src/ http://www.lua.org/ftp/lua-5.3.5.tar.gz
cd /usr/local/src/
sudo tar xf lua-5.3.5.tar.gz
cd lua-5.3.5/src/
sudo make linux

查看编译后的版本

surou@DESKTOP-CRS8RL6:/usr/local/src/lua-5.3.5/src$ ./lua -v
Lua 5.3.5  Copyright (C) 1994-2018 Lua.org, PUC-Rio

编译安装HAProxy

安装基础环境

sudo apt install iproute2 ntpdate tcpdump telnet traceroute nfs-kernel-server nfs-common lrzsz tree openssl libssl-dev libpcre3 libpcre3-dev zlib1g-dev  gcc openssh-server iotop unzip libreadline-dev libsystemd-dev

clone haproxy

git clone https://github.com/haproxy/haproxy.git
git checkout v2.3-dev5

编译源代码

make -j `lscpu |awk 'NR==4{print $2}'` ARCH=x86_64 TARGET=linux-glibc USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 USE_CPU_AFFINITY=1 USE_LUA=1 LUA_INC=/usr/local/src/lua-5.3.5/src/ LUA_LIB=/usr/local/src/lua-5.3.5/src/ PREFIX=/apps/haproxy && make install PREFIX=./dist/haproxy

编译完,查看当前目录

cd dist/haproxy/sbin

查看版本

./haproxy -v
surou@DESKTOP-CRS8RL6:~/dist/haproxy/sbin$ ./haproxy -v
HA-Proxy version 2.3-dev5-7faeea-1 2020/09/26 - https://haproxy.org/
Status: development branch - not safe for use in production.
Known bugs: https://github.com/haproxy/haproxy/issues?q=is:issue+is:open
Running on: Linux 4.4.0-18362-Microsoft #1049-Microsoft Thu Aug 14 12:01:00 PST 2020 x86_64

参考

https://www.cnblogs.com/molson/p/13341108.html

箭头函数 与 forEach

array.forEach(function(item,index){
}.bind(this));

等同于

array.forEach((item,index) =>{
});

转载:https://www.cnblogs.com/guomengkai/p/11392958.html

compound-finance compound-protocol 存和借利率合约分析

计算每块供应率
(github)

 /**
     * @notice Returns the current per-block supply interest rate for this cToken
     * @return The supply interest rate per block, scaled by 1e18
     */
function supplyRatePerBlock() external view returns (uint) {
    return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, totalReserves, reserveFactorMantissa);
}

返回-每块的供应利率,按1e18缩放
跟一下关键参数

getCashPrior()

github

/**
     * @notice Gets balance of this contract in terms of the underlying
     * @dev This excludes the value of the current message, if any
     * @return The quantity of underlying tokens owned by this contract
     */
function getCashPrior() internal view returns (uint) {
    EIP20Interface token = EIP20Interface(underlying);
    return token.balanceOf(address(this));
}

代码逻辑为,获取当前合约地址拥有的基础代币余额数量

totalBorrows

借出的代币总数

totalReserves

存入的代币总数(储备金)

reserveFactorMantissa

市场的当前储备系数

getSupplyRate

(github)

 /**
     * @notice Calculates the current supply rate per block
     * @param cash The amount of cash in the market
     * @param borrows The amount of borrows in the market
     * @param reserves The amount of reserves in the market
     * @param reserveFactorMantissa The current reserve factor for the market
     * @return The supply rate percentage per block as a mantissa (scaled by 1e18)
     */
function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) public view returns (uint) {
    uint oneMinusReserveFactor = uint(1e18).sub(reserveFactorMantissa);        // 单量减去储备的系数
    uint borrowRate = getBorrowRate(cash, borrows, reserves);                  // 获取借出的利率
    uint rateToPool = borrowRate.mul(oneMinusReserveFactor).div(1e18);         // 将借出的利率缩小储备系数倍数
    return utilizationRate(cash, borrows, reserves).mul(rateToPool).div(1e18); // 市场利用率/缩小储备系数后的借出利率
}
附加

add sub mul div 来自SafeMath库,对等是加减乘除

utilizationRate 计算市场利用率

github

/**
     * @notice Calculates the utilization rate of the market: `borrows / (cash + borrows - reserves)`
     * @param cash The amount of cash in the market
     * @param borrows The amount of borrows in the market
     * @param reserves The amount of reserves in the market (currently unused)
     * @return The utilization rate as a mantissa between [0, 1e18]
     */
function utilizationRate(uint cash, uint borrows, uint reserves) public pure returns (uint) {
    // Utilization rate is 0 when there are no borrows
    if (borrows == 0) {
        return 0;
    }
    return borrows.mul(1e18).div(cash.add(borrows).sub(reserves)); // 借出/(账户剩余+借出-存入)
    // 借出,就是发币合约把代币转给其他的账户,当其他账户存币时,再转回发币合约账户
}

getBorrowRate 获取每个块的当前借入利率

 /**
     * @notice Calculates the current borrow rate per block, with the error code expected by the market
     * @param cash The amount of cash in the market
     * @param borrows The amount of borrows in the market
     * @param reserves The amount of reserves in the market
     * @return The borrow rate percentage per block as a mantissa (scaled by 1e18)
     */
function getBorrowRate(uint cash, uint borrows, uint reserves) public view returns (uint) {
    uint util = utilizationRate(cash, borrows, reserves); //计算市场利用率

    if (util <= kink) {
        return util.mul(multiplierPerBlock).div(1e18).add(baseRatePerBlock);
    } else {
        uint normalRate = kink.mul(multiplierPerBlock).div(1e18).add(baseRatePerBlock);
        uint excessUtil = util.sub(kink);
        return excessUtil.mul(jumpMultiplierPerBlock).div(1e18).add(normalRate);
    }
}
kink

应用跳转乘数的利用率点,当利用率小于这个配置值时,走相应逻辑

multiplierPerBlock

利用率乘数,得出利率的斜率

multiplierPerYear

利用率的利率增长率(按1e18缩放
multiplierPerBlock = multiplierPerYear.div(blocksPerYear);

jumpMultiplierPerBlock

jumpMultiplierPerBlock = jumpMultiplierPerYear.div(blocksPerYear);

baseRatePerYear

初始值,每年的基础利率

blocksPerYear

利率模型假设的每年大约的块数

baseRatePerBlock

基本利率是利用率为0时的y截距,
baseRatePerBlock = baseRatePerYear.div(blocksPerYear);

jumpMultiplierPerBlock

达到指定的利用率点后的multiplierPerBlock

总结

稍后补充

参考

https://www.jinse.com/blockchain/485426.html

chrome清除缓存、不使用缓存而刷新快捷键

Ctrl+Shift+Del 清除Google浏览器缓存的快捷键
Ctrl+Shift+R 重新加载当前网页而不使用缓存内容
Ctrl + F5 去除缓存+刷新快捷键