Nginx 负载均衡实战

有时候,为了提高程序负载、增加服务器处理能力,就需要负载均衡技术。该技术主要是把用户请求分发到不同的服务器上去处理,这样做有效的解决单台服务器处理慢,和单机故障问题,真是一举多得的办法。

nginx 实现负载均衡要依赖一个upstream模块和proxy_pass反向代理指令,这个模块通过一些简单的调度算法来实现请求分发从而达到负载均衡策略。下面看nginx.conf文件怎么

nginx负载均衡模块默认支持4种算法:

  1. 轮询:这是upstream模块默认支持的算法,该算法有几个附加属性 ① weight轮询权值 ② backup 备份服务器。
  2. ip_hash:这是按请求ip使用hash结果进行分配,如果采用这种算法有效解决了session问题。
  3. fair:这个是最智能的算法。因为该算法是根据后端服务器的响应时间来分配请求,响应时间短的优先分配。
  4. url_hash:这个算法和ip_hash类似,不同的是hash请求地址url的结果来分配请求。

使用轮询算法

upstream test{
    server 127.0.0.1:91 weight=1;  #weight 权值。值越大分配到的访问几率越高
    server 127.0.0.1:92 weight=2;
    server 127.0.0.1:93 backup;
}
server {
    listen 85 ;
    index index.php  index.html index.htm;
    location / {
        proxy_pass http://test;
    }
}

使用ip_hash算法

upstream test{
    ip_hash;
    server 127.0.0.1:91;
    server 127.0.0.1:92;
    #server 127.0.0.1:93 backup; 使用ip_hash算法时,不能使用backup状态
}
server {
    listen 85 ;
    index index.php  index.html index.htm;
    location / {
        proxy_pass http://test;
    }
}

其余两个算法需要额外的第三方模块支持,所以在这就不做演示啦,不过配置都是一样的。引入指令即可。

缓存一致性协议-mesi

背景

现代CPU几乎都是多核,每个核心也有自己独立的缓存(L1,L2,L3),当多个核心同时对一个数据(变量)更新时,假设核心1在核心2还未将更新的数据刷回内存之前读取了数据,并进行操作就会造成程序执行的结果不符合逾期。这对于我们程序来说,是不正确的。

字母解释

  • M:(modify)修改 -- 该缓存行有效,数据被修改了,和内存中的数据不一致,数据只存在于本缓存行中
  • E:(exclusive)独享、互斥 -- 该缓存行有效,数据和内存中的数据一致,数据只存在于本缓存行中
  • S:(shared)共享 -- 该缓存行有效,数据和内存中的数据一致,数据同时存在于其他缓存中
  • I:(invalid)无效 -- 该缓存行数据无效

优势

对于总线锁,总线锁是对整个内存进行加锁,在一个核心对一个数据进行修改的过程中,其他的核心也无法修改内存中的其他数据,这样会导致CPU处理性能严重下降。

什么情况下不可用

  1. CPU不支持缓存一致性协议
  2. 变量超过一个缓存行的大小,缓存一致性协议是针对单个缓存进行加锁。此时,缓存一致性协议无法再对该变量进行加锁,只能改用总线加锁方式。

wsl 使用实践

wsl 使用实践

wsl 是什么

wsl 全称 windows subsystem for linux,是一个可以运行在 windows 10 系统之上的,完整的 ubuntu 操作系统。

常用命令

  • wsl --list --online 列出可用的 linux 发行版

    NAME            FRIENDLY NAME
    Ubuntu          Ubuntu
    Debian          Debian GNU/Linux
    kali-linux      Kali Linux Rolling
    openSUSE-42     openSUSE Leap 42
    SLES-12         SUSE Linux Enterprise Server v12
    Ubuntu-16.04    Ubuntu 16.04 LTS
    Ubuntu-18.04    Ubuntu 18.04 LTS
    Ubuntu-20.04    Ubuntu 20.04 LTS

通过 unsafe.Pointer 验证切片是引用类型

看过很多文章,都说切片(slice)是引用类型, 但是实际操作中很难通过结果来证明是引用类型,特别是使用 append 函数时,打印切片结果还是没有变化。 现在我们来使用 unsafe.Pointer 来修改切换的 len 属性来证明切片是引用类型。 废话不多说,上代码...

package main

import (
    "fmt"
    "reflect"
    "unsafe"
)

func main() {
    s := make([]int, 0, 5)
    // 初始化切片数据
    s = append(s, 1, 2, 3)

    // 调用appendSlice方法,给切片添加数据
    appendSlice(s)

    // 打印切片
    fmt.Println(s) // 输出:1 2 3 (说明增加的 100 没有在这儿体现出来)

    // 现在我们来使用黑科技,来证明切片是引用类型
    sh := (*reflect.SliceHeader)(unsafe.Pointer(&s))
    sh.Len = 4

    // 现在重新打印
    fmt.Println(s) // 输出: 1 2 3 100 (现在看到100, 是不是就是说明 appendSlice 方法的修改,已经影响到了外面的slice了,也就证实了slice是引用类型哦)
}

func appendSlice(s []int) {
    s = append(s, 100)
}

补充说明
注意,追加的切片数据不能超过容量哦,不然会引起切片底层数组指针指向新的数组地址,那就不能看出效果了。