高能提醒,全文约3700字,系统搭建有难度,建议收藏后食用
微服务架构是一种云原生架构方法,在近年来逐渐为开发者所熟知。与其他架构相比,它具有以下几个显著的优点:
废话不多说,开始搭建一个微服务架构吧!
用户服务: http:// ip :port/user/...
商品服务: http:// ip :port/goods/...
搭建系统采用4台Vmware虚拟的Ubuntu Server18.04主机,均为1核+2G内存:
Docker Network是一种虚拟网络,能够分离容器与真实外界网络的通信,有助于保护系统安全。Docker Network分类众多,本文使用的是Overlay
网络,它是多个Docker主机之间的分布式网络,通常用于多主机通信,同一个Overlay网络中的所有节点都是可以相互通信的,却不能对外通信,如果需要的话应该让节点主动开放对外的端口。
2. Docker Swarm
Docker Swarm是Docker内置的一种容器编排工具,它最实用的功能就是一条指令开启多个容器。在Swarm中,节点有Manager
和Node
两种角色,其中Manager负责容器调度,Node负责听从Manager指挥开启/关闭容器。
3. Docker Registry
Docker Registry是Docker的一款开源项目,用于搭建一个私有的镜像服务器,配合Swarm能够方便各主机之间镜像的分发,同时也能保密系统内的代码。
在单体应用中,应用间的调用通常都是硬编码在代码或配置文件中,而随着应用架构转向微服务,各服务的地址和端口都是动态变化的,因此我们需要一个统一的中心化组件来保存各应用实例的信息,称之为服务注册。同时,该中心化组件还应能够查询到各实例的信息,称之为服务发现。本文采用consul实现服务注册和服务发现,应用在启动时需要向consul发送HTTP请求进行服务注册,而调用服务方则需要在调用前通过DNS查询服务信息即服务发现。
2. Registrator自动化服务注册与服务注销
Registrator是一款开源的自动化服务注册与服务注销工具,使得应用无需编写额外的代码进行服务注册,在应用下线时,也能自动完成服务注销。
kong是一款基于nginx的API网关,与nginx不同的是,kong可以查询DNS信息动态获取服务信息并将请求分发到正在活跃的服务节点上。
2. 插件机制
除了路由转发功能外,插件化机制也为kong提供了强大的生命力,用户可以在kong的配置中加入用户鉴权、流量控制、日志收集等超实用的功能。
3. konga GUI管理界面
konga是一款开源的kong GUI管理界面,能够帮助运维人员轻松配置kong网关。
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
2. 配置Docker镜像加速器:在阿里云搜“容器镜像”,登录后进入控制台侧栏底部有个容器镜像加速。
192.168.10.100
主机中创建一个Swarm,该节点为Swarm Manager:$ docker swarm init --advertise-addr 192.168.10.100
Swarm initialized: current node (dxn1zf6l61qsb1josjja83ngz) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join
--token SWMTKN-1-49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2e7c
192.168.10.100:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
Note:指令运行后的输出包含其他主机加入该Swarm的指令
2. 在192.168.10.101
、192.168.10.102
、192.168.10.103
执行命令加入Swarm:
$ docker swarm join
--token SWMTKN-1-49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2e7c
192.168.10.100:2377
3. 在Swarm Manager中查看Swarm节点情况
docker node ls
192.168.10.100
创建一个Overlay网络,网络名称为micro
docker network create -d overlay --attachable micro
2. 容器连接Overlay网络
在容器创建时加上--network=<网络名称>
,如:
docker run -d --network=micro redis
192.168.10.101
启动registry私有镜像服务器docker run -d -p 5000:5000 registry
2. 上传本地镜像到registry私有镜像服务器
docker image tag <本地镜像名称> 192.168.10.101:5000/<本地镜像名称>
docker push 192.168.10.101:5000/<本地镜像名称>
Note:docker image tag
命令为本地镜像创建一个别名,当执行docker push
命令时,docker将自动读取该别名前的ip+port,并 将镜像上传到ip+port对应的镜像服务器中。
3. 让我们来试着上传一个镜像吧
docker pull alpine
docker image tag alpine 192.168.10.101:5000/alpine-test
docker push 192.168.10.101:5000/alpine-test
Note:执行上述命令若出现http: server gave HTTP response to HTTPS client
这种错误信息,则在/etc/docker/daemon.json
中追加(若该文件不存在则创建一个同名文件):"insecure-registries" : ["
:5000"]
并使用systemctl restart docker
重启docker,强烈建议只在测试环境中使用该方法,生产环境中请使用CA证书,详情请见 https:// docs.docker.com/registr y/deploying/#run-an-externally-accessible-registry
4. 拉取registry私有镜像服务器中的镜像
docker pull 192.168.10.101:5000/<镜像名称>
192.168.10.100
启动第一个consul实例$ docker run -d -p 8500:8500 -p 8600:8600 -p 8600:8600/udp -p 8300:8300 -p 8301:8301 -p 8301:8301/udp -p 8302:8302 -p 8302:8302/udp consul agent -server -bootstrap -ui -client=0.0.0.0 -advertise=192.168.10.100
2. 在192.168.10.101
和192.168.10.102
启动另外两个consul实例
(192.168.10.101)$ docker run -d -p 8500:8500 -p 8600:8600 -p 8600:8600/udp -p 8300:8300 -p 8301:8301 -p 8301:8301/udp -p 8302:8302 -p 8302:8302/udp consul agent -server -join=192.168.10.100 -client=0.0.0.0 -advertise=192.168.10.101
(192.168.10.102)$ docker run -d -p 8500:8500 -p 8600:8600 -p 8600:8600/udp -p 8300:8300 -p 8301:8301 -p 8301:8301/udp -p 8302:8302 -p 8302:8302/udp consul agent -server -join=192.168.10.100 -client=0.0.0.0 -advertise=192.168.10.102
3. 在浏览器中打开http://192.168.10.100:8500,进入如下页面,则consul集群搭建成功
docker pull gliderlabs/registrator
2. 在Swarm Manager上为所有Swarm主机上启动Registrator
docker service create --name=registrator --mount type=bind,src=/var/run/docker.sock,dst=/tmp/docker.sock --mode global --network=micro gliderlabs/registrator -deregister="always" -internal consul://192.168.10.100:8500
Note:以下是命令中相关参数的说明--name
设定该服务的名称是registrator--mount
设定每个容器挂载主机的目录,这是Registrator启动所要求的--mode
设定global表示每个Swarm主机都要启动一个Registrator实例--network
设定该服务内所有实例都属于micro
这个Overlay网络-deregister
设定"always"表示服务下线时自动执行服务注销-internal
设定Registrator可以自动注册网络内部的实例,方便网络内实例互相调用consul://192.168.10.100:8500
指明了Consul的服务地址,写consul集群中其他实例的地址也可以
192.168.10.103
启动Kong依赖的数据库postgres
:docker run -d --name kong-database
--network=micro
-p 5432:5432
-e "POSTGRES_USER=kong"
-e "POSTGRES_DB=kong"
-e "POSTGRES_PASSWORD=kong"
postgres:9.6
2. 在192.168.10.103
查询postgres
在Overlay网络中的地址
$ docker container inspect kong-database
...
"Networks": {
"micro": {
"IPAMConfig": {
"IPv4Address": "10.0.2.174" <-- 这个就是postgres在micro网络中的ip
},
...
3. 在192.168.10.103
初始化Kong的数据库
docker run --rm
--network=micro
-e "KONG_DATABASE=postgres"
-e "KONG_PG_HOST=kong-database"
-e "KONG_PG_USER=kong"
-e "KONG_PG_PASSWORD=kong"
-e "KONG_CASSANDRA_CONTACT_POINTS=kong-database"
kong:latest kong migrations bootstrap
4. 在192.168.10.103
启动Kong
docker run -d --name kong
--network=micro
-e "KONG_DATABASE=postgres"
-e "KONG_PG_HOST=10.0.2.174"
-e "KONG_PG_USER=kong"
-e "KONG_PG_PASSWORD=kong"
-e "KONG_CASSANDRA_CONTACT_POINTS=kong-database"
-e "KONG_PROXY_ACCESS_LOG=/dev/stdout"
-e "KONG_ADMIN_ACCESS_LOG=/dev/stdout"
-e "KONG_PROXY_ERROR_LOG=/dev/stderr"
-e "KONG_ADMIN_ERROR_LOG=/dev/stderr"
-e "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl"
-e "KONG_DNS_RESOLVER=192.168.10.100:8600,192.168.10.101:8600,192.168.10.102:8600"
-e "KONG_DNS_ORDER=SRV,LAST,A,CNAME"
-p 8000:8000
-p 8443:8443
-p 8001:8001
-p 8444:8444
kong:latest
Note:以下是命令中需要配置的参数说明KONG_PG_HOST
是上一步中查询到的postgres
在Overlay网络中的地址KONG_DNS_RESOLVER
是DNS解析地址列表,本文中开启了三个consul服务,其DNS解析端口默认是8600
5. 测试一下Kong是否启动,若如下命令输出一大堆信息则表示启动成功
curl -i http://192.168.10.103:8001/
192.168.10.103
启动Kongadocker run -d -p 1337:1337 --network micro pantsel/konga
2. 打开浏览器,进入Konga管理界面:http://192.168.10.103:1337
至此,微服务基本架构就搭建完毕啦!
alpine是一种超精简的Linux版本(镜像不到10MB),如果对内存要求比较苛刻的话就可以考虑用这款linux哦
# 指定创建的基础镜像
FROM alpine:latest
# 作者描述信息
MAINTAINER alpine_sshd_service
# 替换阿里云更新源、安装ssh、修改配置文件、生成key、同步时间、设置账号密码为root和admin
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
&& apk update
&& apk add --no-cache openssh tzdata
&& cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
&& sed -i "s/#PermitRootLogin.*/PermitRootLogin yes/g" /etc/ssh/sshd_config
&& ssh-keygen -t dsa -P "" -f /etc/ssh/ssh_host_dsa_key
&& ssh-keygen -t rsa -P "" -f /etc/ssh/ssh_host_rsa_key
&& ssh-keygen -t ecdsa -P "" -f /etc/ssh/ssh_host_ecdsa_key
&& ssh-keygen -t ed25519 -P "" -f /etc/ssh/ssh_host_ed25519_key
&& echo "root:admin" | chpasswd
# 开放22、8000端口
EXPOSE 22
EXPOSE 8000
# 容器启动时执行ssh启动命令
CMD ["/usr/sbin/sshd", "-D"]
2. 使用Dockerfile构建镜像
docker build -t alpine-base:v1 .
3. 运行alpine-base实例
docker run -d -P --name=base-srv --network=micro alpine-base:v1
Note:这里使用-P
参数是将容器的开放端口随机映射到30000以上,这是为了不占用主机其他应用程序的端口,使用docker container ls
可以查看到容器的映射端口,这里的映射结果是0.0.0.0:32771->22/tcp, 0.0.0.0:32770->8000/tcp
4. ssh连接容器实例
这里我们使用XShell连接容器,新建连接,填写IP、端口、账号密码等信息
开启连接进入容器
5. 编写服务代码
本文使用Python的Tornado框架编写一个简单的web服务,在访问/index
路径时返回"index"字符串
首先安装一下Python解释器和Tornado框架
apk add python3
apk add py3-pip
pip3 install tornado
编写main.py文件
import tornado.ioloop
import tornado.web
import tornado.log
class IndexHandler(tornado.web.RequestHandler):
def get(self, *args, **kwargs):
self.write("index")
def make_app():
return tornado.web.Application(
handlers=[
(r"/index", IndexHandler),
],
)
if __name__ == "__main__":
app = make_app()
app.listen(8000)
tornado.log.enable_pretty_logging()
tornado.ioloop.IOLoop.current().start()
6. 生成首个镜像版本并上传Registor私有镜像仓库
docker commit base-srv tornado-srv:v1
docker tag tornado-srv:v1 192.168.10.101:5000/tornado-srv:v1
docker push 192.168.10.101:5000/tornado-srv:v1
docker service create --name=tornado-srv --network=micro --replicas=3 192.168.10.101:5000/tornado-srv:v1 python3 /root/main.py
Note:以下是命令中相关参数的说明--name
设定服务名称为"tornado-srv"--network
设定服务网络为“micro”--replicas
设定服务有3个副本192.168.10.101:5000/tornado-srv:v1
是私有镜像名称python3 /root/main.py
是第一次启动容器实例时执行的命令,这里我们要启动web服务
2. 进入http://192.168.10.100:8500就能看到部署的实例,这里后缀指明了服务的端口,事实上这里我们只要使用8000端口就可以了,即tornado-srv-8000
2. 进入konga控制台,首先需要连接Kong,需要填写Name和Kong Admin URL
3. 连接成功后点击add service,填写相关信息
Note:以下是信息中相关参数的说明Name
:服务的名称Protocol
:服务的协议,这里我们只有httpHost
:由于我们配置了DNS自动解析,因此这里我们只需要填写DNS解析域名即可,格式为 <服务在consul中的名称>.service.consulPort
:服务的端口,这里设定容器的开放服务端口为8000
4. 为service添加route
Note:以下是信息中相关参数的说明Name
:route的命名Paths
:route的路径,每个service可以有多个route
5. 使用Postman测试请求
6. 最后,用一张图来总结这个配置过程:
https://www.consul.io/docs
https://docs.docker.com/engine/swarm/
https://docs.docker.com/registry/
https://docs.konghq.com/getting-started-guide/2.1.x/overview/
作者水平有限,若有缺失严谨性请轻喷。
在撰写本文时作者查阅了大量资料,劳动不易点个赞是支持作者的最好动力。