Docker下的OpenResty三部曲之三:OpenResty加Tomcat的服务

简介: 前面两章我们实战了OpenResty的lua脚本开发,并且将web服务发布在Docker环境下,本章我们在kubernetes环境下搭建OpenResty加Tomcat的web服务

欢迎访问我的GitHub

这里分类和汇总了欣宸的全部原创(含配套源码): https://github.com/zq2599/blog_demos

本篇概览

  • 本章是《Docker下的OpenResty三部曲》的终篇,前面两章我们实战了OpenResty的lua脚本开发,并且将web服务发布在Docker环境下,本章我们在kubernetes环境下搭建OpenResty加Tomcat的web服务;

前文信息

kubernetes下实战Nginx和Tomcat的参考文章

  • 您可以通过以下文章了解更详细的kubernetes实战:

《kubernetes下的Nginx加Tomcat三部曲之一:极速体验》
《kubernetes下的Nginx加Tomcat三部曲之二:细说开发》
《kubernetes下的Nginx加Tomcat三部曲之三:实战扩容和升级》

环境信息

  • 本次实战搭建的环境如下所示:

这里写图片描述

本次实战的web服务

  • 本次实战的web服务,主要功能为:浏览器发起http请求到OpenResty,OpenResty负责去处理业务,处理过程中向Tomcat发起http请求,将Tomcat响应的信息返回给浏览器;

和常见的Nginx加Tomcat有什么不同?

  • 上图的架构和常见的Nginx加Tomcat很相似,不过还是有区别的:
  1. Nginx节点主要工作是将请求转发到Tomcat,由Tomcat去执行具体业务;
  2. OpenResty节点上的lua脚本可以执行具体业务,处理的过程中如有必要可以主动发起http请求到Tomcat,调用Tomcat提供的服务;
  3. 关于OpenResty加Tomcat架构的更多特性和优点请移步开涛大神的博客:《跟我学Nginx+Lua开发》

实战源码和Docke镜像材料下载

  • 本次构建镜像所需的材料我已准备齐全,您可以在github下载到:
名称 链接 备注
项目主页 https://github.com/zq2599/blog_download_files 该项目在GitHub上的主页
git仓库地址(https) https://github.com/zq2599/blog_download_files.git 该项目源码的仓库地址,https协议
git仓库地址(ssh) git@github.com:zq2599/blog_download_files.git 该项目源码的仓库地址,ssh协议
  • 这个git项目中有多个目录,本次所需的资源放在tomcat_openresty_docker_image_files,如下图红框所示:

在这里插入图片描述

  • 注意,本章用到的资源目录是tomcat_openresty_docker_image_files,上一章用的是nginx_lua_docker_image_files,里面是不同资源;
  • Tomcat上的web工程源码在k8stomcatdemo目录下,是个普通的springboot工程,提供一个http接口可以返回Tomcat所在机器的IP地址,这个web工程已经被制作成镜像文件bolingcavalry/k8stomcatdemo:0.0.1-SNAPSHOT,有关这个工程的更多信息,请参照《kubernetes下的Nginx加Tomcat三部曲之二:细说开发》

列举步骤

  • 今天的整个实战,我们要做以下事情:
  1. 在前一章的基础上重做OpenResty的Docker镜像,新增一些内容;
  2. 在kubernetes创建Tomcat的副本集和service;
  3. 在kubernetes创建OpenResty的副本集和service;
  4. 通过浏览器验证kubernetes环境中的OpenResty加Tomcat提供的服务;

为什么要重做Docker镜像

  • 在上一章我们已经做了OpenResty的镜像并体验过了,为何本章还要重做呢?
  1. 在镜像中安装vim,并解决vim显示中文乱码的问题;
  2. 新增一个http接口和lua脚本,浏览器访问这个接口时,对应的lua脚本会向Tomcat发请求;
  3. 将OpenResty的http模块集成到镜像中;
  4. 曲折的解决OpenResty的http模块无法解析域名的问题;
  • 前期铺垫说了这么多,接下来我们就开始实战吧;

制作OpenResty镜像

安装vim,并解决vim显示中文乱码的问题

  • 以下是Dockerfile中vim相关的内容:
#创建安装命令
RUN apt-get install -y make vim gcc libreadline-dev libncurses5-dev libpcre3-dev libssl-dev perl 

#修改vim的配置信息,修复中文乱码问题
RUN sed -i '$a\set fileencodings=utf-8,ucs-bom,gb18030,gbk,gb2312,cp936' /etc/vim/vimrc
RUN sed -i '$a\set termencoding=utf-8' /etc/vim/vimrc
RUN sed -i '$a\set encoding=utf-8' /etc/vim/vimrc
  • 如上所示,通过sed命令向/etc/vim/vimrc文件中追加了三行,以保证中文显示;

添加OpenResty的http模块

  • 首先下载http.lua和http_headers.lua这两个文件,放在Dockerfile所在目录,然后在Dockerfile添加以下内容:
#将http库文件复制到默认库
COPY ./http.lua $INSTALL_PATH/lualib/resty
COPY ./http_headers.lua $INSTALL_PATH/lualib/resty

增加一个http接口

  • 为了对外新增一个http接口lua_http,在boling_cavalry.conf文件中增加了以下内容,
location ~ /lua_http/(\d+)/(\d+) {
        #设置nginx变量
        set $a $1;
        set $b $host;
        default_type "text/html";
        #nginx内容处理
        content_by_lua_file /usr/local/work/lua/test_http.lua;
    }
  • 如上所示,当浏览器输入http://192.168.119.150:9000/lua_http/333/666这样URL时,就会由test_http.lua这个脚本来处理,test_http.lua的内容如下所示:
ngx.say("---------------------------------------------------------<br/>");

local http = require("resty.http")
--创建http客户端实例
local httpc = http.new()

local resp, err = httpc:request_uri("http://127.0.0.1:80",{
    method = "GET",
    path = "/tomcat_proxy/getserverinfo",
    headers = {
        ["User-Agent"] = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.111 Safari/537.36"
    }
})

if not resp then
    ngx.say("request error :", err)
    return
end


ngx.say("resp status--", resp.status)

ngx.say("<br/><br/>resp body--", resp.body)

httpc:close()
  • 如上所示,该脚本的处理很简单:发起一个http请求,将收到响应的code和body在页面上显示出来;
  • 你们注意到了吗?请求的地址是127.0.0.1,是OpenResty自己,不是Tomcat!!!
  • 为什么要向自己发http请求呢?不是应该发请求给Tomcat么?我们一起来梳理一下吧:
  • 按照原本的设计,此处的URL应该是http://tomcathost:8080/getserverinfo,tomcathost是Tomcat的Pod在kubernetes暴露的service名称,在kubernetes环境中tomcathost会被解析成Tomcat的Pod地址,请求就到了Tomcat了;
  • 但是,OpenResty的httpc:request_uri这个API无法将tomcathost这个hostname解析成Tomcat的Pod地址,或者说不会用到kubernetes提供的DNS服务,因此请求无法到达Tomcat的Pod;
  • 开涛大神的实例也用到了这个API,他在nginx.conf中配置了resolver 8.8.8.8,访问的是外网hostname:s.taobao.com,但我这里是kubernetes环境内的hostname,试过此方法,失败;
  • 网上也有遇到此类问题的,写了脚本定时扫描/etc/hosts,将hostname对应的IP保存来下,在OpenResty中发起http请求时直接从这个对应关系中取IP,这个方法在Docker环境使用是OK的,Docker的link用的就是/etc/hosts中的关系,但是在kubernetes下,OpenResty的/etc/hosts中并没有写入Tomcat的IP,所以,失败;

我的笨办法,让OpenResty请求到Tomcat

  • 我用的是笨办法,能将请求发到Tomcat,但是很曲折,理论上存在性能损失,亲爱的读者如果您有更科学的方法,期望能得到您的指点;
  • 笨办法的思路如下:
  1. 在nginx.conf中新建一个upstream:
upstream tomcat_client {
         server tomcathost:8080;
    } 
  • 此upstream中的server用到了tomcathost,这是kubernetes中Tomcat的service的名字,能被成功的解析成Tomcat的Pod的IP;
  1. 再增加一个http接口tomcat_proxy,boling_cavalry.conf文件中增加了以下内容:
location ~ /tomcat_proxy/(.*) {
        rewrite /tomcat_proxy(/.*) $1 break;
        proxy_pass http://tomcat_client;
        proxy_redirect default;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
  • 如上所示,如此一来,所有url是tomcat_proxy/xxxxxxx的请求都会被转发到Tomcat了;
  • 注意这一行:rewrite /tomcat_proxy(/.*) $1 break;,可以这么理解:

a. http://127.0.0.1:80/tomcat_proxy/getserverinfo 这个请求可以被tomcat_proxy(/.*)这个正则表达式匹配;
b. 因为/getserverinfo和第一个圆括号中的表达式匹配,所以$1的值就是/getserverinfo
c. 因此请求/tomcat_proxy/getserverinfo被rewrite成了$1,也就是/getserverinfo,带上IP的完整的url就是http://127.0.0.1:80/getserverinfo ;
d. 所以,http://127.0.0.1:80/tomcat_proxy/getserverinfo 被转发到了 http://tomcathost:8080/getserverinfo ,在rewrite的时候将tomcat_proxy抹去了;

  • 最终,在调用OpenResty的request_uri方法的时候,请求的URL是 http://127.0.0.1:80/tomcat_proxy/getserverinfo ,可以被成功转发到Tomcat,关键是Nginx中的upstream的hostname在kubernetes可以被成功解析成IP地址;
  • 最后,在制作Dockerfile的时候,记得将新增的test_http.lua复制到镜像中:
COPY ./test_http.lua $WORK_PATH/lua
  • 以上就是制作新的Dockerfile时要新增的内容了,在Dockerfile所在目录执行以下命令构建镜像,注意TAG是0.0.2,区别于上一章镜像的0.0.1:
docker build -t bolingcavalry/ubuntu16-openresty:0.0.2 .

让kubernetes的机器用上web工程的Docker镜像

  • 现在的镜像只存在于开发和构建web工程的电脑上,为了让kubernetes的node机器能用上这个镜像,可以用以下四种方式实现:
  1. 用docker push命令将本机镜像推送到hub.docker.com网站,这样其他机器都可以通过docker pull命令取得了,我就是用的这种方法,需要在hub.docker.com上注册;
  2. 用docker save命令导出镜像文件,再用docker load命令导入到kubernetes的node机器;
  3. kubernetes所在机器安装java和maven环境,将工程在这里编译构建;
  4. 使用docker私有仓库,例如搭建局域网私有仓库或者阿里云私有仓库,参考《maven构建docker镜像三部曲之三:推送到远程仓库(内网和阿里云)》

在kubernetes创建Tomcat的副本集和service

  • 登录到一台可以执行kubectl命令的机器,创建文件tomcat.yaml:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: tomcathost
spec:
  replicas: 3
  template:
    metadata:
     labels:
       name: tomcathost
    spec:
     containers:
     - name: tomcathost
       image: bolingcavalry/k8stomcatdemo:0.0.1-SNAPSHOT
       tty: true
       ports:
       - containerPort: 8080
  • 以上文件用来定义Tomcat的Pod的副本集;
  • 在tomcat.yaml所在目录创建tomcat-svc.yaml文件,内容如下:
apiVersion: v1
kind: Service
metadata:
  name: tomcathost
spec:
  type: ClusterIP
  ports:
       - port: 8080
  selector:
    name: tomcathost
  • 以上文件将Tomcat的Pod副本包装成service,名字是tomcathost,这样kubernetes环境中的其他Pod通过tomcathost这个hostname就能访问到Tomcat的Pod副本了;
  • 在tomcat.yaml文件所在目录下执行以下命令,创建Pod和service:
kubectl create -f tomcat.yaml,tomcat-svc.yaml
  • 以上命令依次创建Pod和service;
  • 执行kubectl get service查看service情况,如下:
root@maven:/usr/local/work/openrest_rewrite# kubectl create -f tomcat.yaml,tomcat-svc.yaml
deployment "tomcathost" created
service "tomcathost" created
root@maven:/usr/local/work/openrest_rewrite# kubectl get service
NAME           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes     ClusterIP   10.43.0.1       <none>        443/TCP          62d
tomcathost     ClusterIP   10.43.192.125   <none>        8080/TCP         1m
  • 至此,Tocmat服务就OK了,接下来我们创建OpenResty服务吧;

在kubernetes创建OpenResty的副本集和service

  • 在tomcat.yaml所在目录下,创建文件openresty.yaml:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: openresty001
spec:
  replicas: 1
  template:
    metadata:
     labels:
      name: openresty001
    spec:
     containers:
     - name: openresty001
       image: bolingcavalry/ubuntu16-openresty:0.0.2
       ports:
       - containerPort: 80
  • 以上文件用来定义OpenResty的Pod的副本集;
  • 在openresty.yaml所在目录创建openresty-svc.yaml文件,内容如下:
apiVersion: v1
kind: Service
metadata:
  name: openresty001
spec:
  type: NodePort
  ports:
       - port: 80
         nodePort: 30007
  selector:
    name: openresty001
  • 以上文件将openresty的Pod副本包装成service,名字是openresty001,并且将80端口和所在节点机器的30007端口建立映射;
  • 在openresty.yaml文件所在目录下执行以下命令,创建Pod和service:
kubectl create -f openresty.yaml,openresty-svc.yaml
  • 以上命令依次创建Pod和service;
  • 执行kubectl get service查看service情况,如下:
root@maven:/usr/local/work/openrest_rewrite# kubectl create -f openresty.yaml,openresty-svc.yaml
deployment "openresty001" created
service "openresty001" created
root@maven:/usr/local/work/openrest_rewrite# kubectl get service
NAME           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes     ClusterIP   10.43.0.1       <none>        443/TCP          62d
openresty001   NodePort    10.43.148.118   <none>        80:30007/TCP     8s
tomcathost     ClusterIP   10.43.192.125   <none>        8080/TCP         43m
  • 终于将所有的服务都创建好了,接下来开始验证吧;

验证服务

  • OpenResty服务所在的机器IP是192.168.119.153,所以在浏览器输入:http://192.168.119.153:30007/lua_http/333/666 ,可以看到如下效果:

这里写图片描述

  • 如上所示,结合test_http.lua的源码来看,“200”是Tomcat的返回code,“10.42.11.12”是Tomcat所在Pod的IP地址,我们去kubernetes的dashboard印证一下,如下图,红框1是查看信息的路径,红框2是Pod的IP地址,果然有10.42.11.12:

这里写图片描述

  • 至此,《Docker下的OpenResty三部曲》就全部结束了,由于文章大纲没有设计好,导致第三章内容太多,在这里向您道歉了,如果有疑问欢迎您邮件至 zq2599@gmail.com,我们一起探讨,也希望本文能对您的kubernetes实战有所帮助;

欢迎关注阿里云开发者社区博客:程序员欣宸

学习路上,你不孤单,欣宸原创一路相伴...
相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务&nbsp;ACK 容器服务&nbsp;Kubernetes&nbsp;版(简称&nbsp;ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情:&nbsp;https://www.aliyun.com/product/kubernetes
相关文章
|
1月前
|
前端开发 关系型数据库 MySQL
IDEA集成Docker插件打包服务镜像与运行【附Docker命令汇总】
IDEA集成Docker插件打包服务镜像与运行【附Docker命令汇总】
|
2月前
|
监控 网络协议 Linux
使用Docker部署监控服务Uptime Kuma并实现无公网ip远程访问本地服务
使用Docker部署监控服务Uptime Kuma并实现无公网ip远程访问本地服务
111 0
|
3月前
|
TensorFlow 调度 算法框架/工具
【Hello AI】通过Docker安装并使用cGPU服务
cGPU服务可以隔离GPU资源,实现多个容器共用一张GPU卡。该服务作为阿里云容器服务Kubernetes版ACK(Container Service for Kubernetes)的组件对外提供服务,本文介绍如何通过Docker安装并使用cGPU服务。
|
1月前
|
存储 Linux 数据安全/隐私保护
如何在本地Docker中部署MinIO服务并实现远程访问管理界面
如何在本地Docker中部署MinIO服务并实现远程访问管理界面
175 0
|
3月前
|
Arthas 监控 Java
Arthas 可以用于监控和诊断在 Windows 系统下部署的 Tomcat 服务
Arthas 可以用于监控和诊断在 Windows 系统下部署的 Tomcat 服务
163 2
|
4月前
|
监控 Linux 开发者
Docker服务systemd配置文件详解
Docker服务systemd配置文件详解
107 0
|
1月前
|
弹性计算 关系型数据库 MySQL
阿里云ECS使用docker搭建mysql服务
阿里云ECS使用docker搭建mysql服务
147 1
|
4月前
|
应用服务中间件
今日分享记录:WIN10中如何将tomcat注册到Server服务中
今日分享记录:WIN10中如何将tomcat注册到Server服务中
48 1
|
4月前
|
Docker 容器
Docker服务启动失败报错:Job for docker.service failed because the control process exited with error code.
Docker服务启动失败报错:Job for docker.service failed because the control process exited with error code.
|
18天前
|
关系型数据库 MySQL Nacos
【深入浅出Nacos原理及调优】「实战开发专题」采用Docker容器进行部署和搭建Nacos服务以及“坑点”
【深入浅出Nacos原理及调优】「实战开发专题」采用Docker容器进行部署和搭建Nacos服务以及“坑点”
42 1