# 7.3 Splash 负载均衡配置 

用 Splash 做页面抓取时，如果爬取的量非常大，任务非常多，用一个 Splash 服务来处理的话，未免压力太大了，此时可以考虑搭建一个负载均衡器来把压力分散到各个服务器上。这相当于多台机器多个服务共同参与任务的处理，可以减小单个 Splash 服务的压力。

### 1. 配置 Splash 服务

要搭建 Splash 负载均衡，首先要有多个 Splash 服务。假如这里在 4 台远程主机的 8050 端口上都开启了 Splash 服务，它们的服务地址分别为 41.159.27.223:8050、41.159.27.221:8050、41.159.27.9:8050 和 41.159.117.119:8050，这 4 个服务完全一致，都是通过 Docker 的 Splash 镜像开启的。访问其中任何一个服务时，都可以使用 Splash 服务。

### 2. 配置负载均衡

接下来，可以选用任意一台带有公网 IP 的主机来配置负载均衡。首先，在这台主机上装好 Nginx，然后修改 Nginx 的配置文件 nginx.conf，添加如下内容：

```python
http {
	upstream splash {
		least_conn;
		server 41.159.27.223:8050;
		server 41.159.27.221:8050;
		server 41.159.27.9:8050;
		server 41.159.117.119:8050;
	}
	server {
		listen 8050;
		location / {proxy_pass http://splash;}
	}
}
```


这样我们通过 upstream 字段定义了一个名字叫作 splash 的服务集群配置。其中 least_conn 代表最少链接负载均衡，它适合处理请求处理时间长短不一造成服务器过载的情况。

当然，我们也可以不指定配置，具体如下：

```python
upstream splash {
	server 41.159.27.223:8050;
	server 41.159.27.221:8050;
	server 41.159.27.9:8050;
	server 41.159.117.119:8050;
}
```

这样默认以轮询策略实现负载均衡，每个服务器的压力相同。此策略适合服务器配置相当、无状态且短平快的服务使用。

另外，我们还可以指定权重，配置如下：

```python
upstream splash {
	server 41.159.27.223:8050 weight=4;
	server 41.159.27.221:8050 weight=2;
	server 41.159.27.9:8050 weight=2;
	server 41.159.117.119:8050 weight=1;
}
```


这里 weight 参数指定各个服务的权重，权重越高，分配到处理的请求越多。假如不同的服务器配置差别比较大的话，可以使用此种配置。

最后，还有一种 IP 散列负载均衡，配置如下：

```python
upstream splash {
    ip_hash;
	server 41.159.27.223:8050;
	server 41.159.27.221:8050;
	server 41.159.27.9:8050;
	server 41.159.117.119:8050;
}
```

服务器根据请求客户端的 IP 地址进行散列计算，确保使用同一个服务器响应请求，这种策略适合有状态的服务，比如用户登录后访问某个页面的情形。对于 Splash 来说，不需要应用此设置。

我们可以根据不同的情形选用不同的配置，配置完成后重启一下 Nginx 服务：

```
sudo nginx -s reload
```

这样直接访问 Nginx 所在服务器的 8050 端口，即可实现负载均衡了。


### 3. 配置认证

现在 Splash 是可以公开访问的，如果不想让其公开访问，还可以配置认证，这仍然借助于 Nginx。可以在 server 的 location 字段中添加 auth_basic 和 auth_basic_user_file 字段，具体配置如下：

```python
http {
	upstream splash {
		least_conn;
		server 41.159.27.223:8050;
    	server 41.159.27.221:8050;
    	server 41.159.27.9:8050;
    	server 41.159.117.119:8050;
	}
	server {
		listen 8050;
		location / {
            proxy_pass http://splash;
            auth_basic "Restricted";
            auth_basic_user_file /etc/nginx/conf.d/.htpasswd;
        }
	}
}
```
这里使用的用户名和密码配置放置在 /etc/nginx/conf.d 目录下，我们需要使用 htpasswd 命令创建。例如，创建一个用户名为 admin 的文件，相关命令如下：
```
htpasswd -c .htpasswd admin
```
接下来就会提示我们输入密码，输入两次之后，就会生成密码文件，其内容如下：
```
cat .htpasswd 
admin:5ZBxQr0rCqwbc
```
配置完成之后我们重启一下 Nginx 服务，运行如下命令：
```
sudo nginx -s reload
```

这样访问认证就成功配置好了。

### 4. 测试

最后，我们可以用代码来测试一下负载均衡的配置，看看到底是不是每次请求会切换 IP。利用 [http://httpbin.org/get](http://httpbin.org/get) 测试即可，代码实现如下：

```python
import requests
from urllib.parse import quote
import re

lua = '''
function main(splash, args)
  local treat = require("treat")
  local response = splash:http_get("http://httpbin.org/get")
  return treat.as_string(response.body)
end
'''

url = 'http://splash:8050/execute?lua_source=' + quote(lua)
response = requests.get(url, auth=('admin', 'admin'))
ip = re.search('(\d+\.\d+\.\d+\.\d+)', response.text).group(1)
print(ip)
```

这里 URL 中的 splash 字符串请自行替换成自己的 Nginx 服务器 IP。这里我修改了 Hosts，设置了 splash 为 Nginx 服务器 IP。

多次运行代码之后，可以发现每次请求的 IP 都会变化，比如第一次的结果：

```
41.159.27.223
```

第二次的结果：

```
41.159.27.9
```

这就说明负载均衡已经成功实现了。


本节中，我们成功实现了负载均衡的配置。配置负载均衡后，可以多个 Splash 服务共同合作，减轻单个服务的负载，这还是比较有用的。