概述
这节其实是上一篇nginx教程的补充,因为有朋友看了之后对于反向代理那块还有点疑问.所以这边就举一个简单的例子(负载均衡).顺便加上了一些docker的知识。所以废话不说,进入正题吧~
nginx反向代理
上一篇文章提到了反向代理的概念.概念其实很简单,但是实际上有什么应用呢?
有个最简单也是很实用的例子,也就是负载均衡.作为反向代理的nginx在收到请求后按照一定规则再分发给下游的服务器.在这里对服务端而言客户端是明确的,并且通常配置的时候会带上realip.但是对于客户端来讲却不知道请求最后落到了哪台机器,这就是一个常见的反向代理的场景.这里并没有其他可以补充的知识,在nginx的官网上都是有相关介绍的.
这就着重以一个例子来实现.
这边会借助docker来实现这个例子.
最简单的一个例子就是两个服务容器一个nginx容器.
nginx容器就是直接使用官方镜像即可.
首先是server的代码,go语言编写
package main
import (
"fmt"
"log"
"net/http"
"os"
)
func main() {
http.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
log.Println(r)
hostName, _ := os.Hostname()
w.Write([]byte(fmt.Sprintf("server:%s\n", hostName)))
return
})
log.Println("start...")
log.Panic(http.ListenAndServe(":8081", nil))
}
本身没什么难度,主要是会输出自己的hostname,这个在后面帮助我们区分实际访问的服务器.
然后go build
编译即可,根据自己的实际需求选择编译条件.这里我提供了现成的docker镜像,地址为(https://cloud.docker.com/u/evanshao/repository/docker/evanshao/lbserver),
就不多赘述了.
然后是Dockerfile
FROM debian
MAINTAINER evan
COPY server /
ENTRYPOINT ["./server"]
这个也很简单,就是借助debian基础镜像运行编译好的server.
然后是nginx配置(已经提供了镜像,地址是:https://cloud.docker.com/u/evanshao/repository/docker/evanshao/lbnginx).
这里可以参考上一篇文章的基础配置:
#user nobody;
worker_processes 4; # 按照机器情况定
events {
worker_connections 10240; # 按照机器情况定
}
http{
include mime.types;
default_type application/json; # 按照自己服务设置
error_page 500 502 503 504 /50x.html;
error_page 404 /404.html; # 这个自己写了放到html目录下,不然应该是nginx代码里写死的
resolver 114.114.114.114;
# 定义日志格式 这个别名是main
log_format main '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for"';
sendfile on;
keepalive_timeout 30;
include sites/*.http.conf; # 具体的server放在这里
}
重点是sites下需要两个新建的配置文件,
一个是ups.http.upstream:
upstream test_server{
server serverA:8081;
server serverB:8081;
}
这里其实是有两个注意点的,一个是serverA 这个是配合后面的dockerDNS使用的,还有个自然是端口号,和server程序监听的端口号一致.
另外一个文件是 ups.http.conf,这里在开头引用了upsream文件,并利用proxy_pass实现了转发.
include sites/ups.http.upstream;
server{
listen 80 default_server;
server_name localhost;
access_log logs/ups.log main;
location /{
set $upstream_host $host;
proxy_pass http://test_server;
}
}
这边是Dockerfile,myconf下就是上面的文件nginx.conf以及sites文件夹,sites里是其他两个文件.另外还创建了一个空的logs文件夹
FROM nginx
MAINTAINER evan
COPY myconf/ /etc/nginx
EXPOSE 80
ENTRYPOINT ["nginx","-g","daemon off;"]
到这里实验环境就准备好了,下面其实就是docker部分了,时间有限,这里仅仅提下使用方法.如果docker没有安装的话可以参考官方文档进行操作,后面有机会我也会开始写一些docker的简单教程~
上文提到的dockerDNS其实是docker提供的一种容器间通信的方法.具体的就不赘述了,如果有兴趣的话可以自行搜索或者等我的blog哦.
首先我们要创建自己的docker子网
docker network create --driver bridge --subnet 172.22.16.0/24 --gateway 172.22.16.1 my_net
这里相当于创建了一个局域网,网段是172.22.16.然后在运行server和nginx容器的时候我会把他们都指定到这个网段,这样才能保证局域网内各容器的网络通信.
接下来首先启动两台server容器
docker run -itd --rm --name serverA --hostname serverA --network=my_net evanshao/lbserver
docker run -itd --rm --name serverB --hostname serverB --network=my_net evanshao/lbserver
这里用--hostname
指定机器的host配合server的取值,--name
相当于指定局域网内的通信域名,这里需要注意的是--name
指定的才是我们访问的域名,这里我顺手写成和hostname一样的了,不要混淆.
然后我们需要启动nginx
docker run -itd --rm --name lbnginx -p 80:80 --network=my_net evanshao/lbnginx
这时候实验环境就已经搭建完成了,我们通过浏览器访问http://192.168.31.147/test
就可以看到效果了:
刷新就变成
这边配置默认应该是轮询,当你停掉一个容器的时候就会只访问到活着的那台机器了.
这里如果没时间自己操作的话,直接按照我上面的三条docker run命令执行即可.
后面可以慢慢还原.
这里写的有些粗略了,因为上一篇文章已经有提到一些nginx关键字的用法,官方也写得很详细了.主要还是展示下如果通过docker展现这一场景,后续我也会慢慢补充一些docker的知识,希望到时候能对你们有所帮助.