主要讲的是解决问题的思路。当然也附带了尽可能详细的步骤,感兴趣的童鞋可以一步一步跟着来实践一把。因为运维职业的缘故,基本上是把事故当故事来写了,希望能够喜欢。
至少10年了,没在一线玩过 Tomcat 了,这次客户现场就来了一场遭遇战。虽然客户说了他来搭建,但是项目进度不等人,还是自己动手吧。当然了,新服务器是要走流程申请的,只能在现有服务器想办法。犹记得当年解决 Tomcat 部署这些都是小菜,没想到在苛刻的商业环境中,处处是坑,步步有雷。不过,咱干过开发也干过运维,这点儿动手的事情,还不至于发邮件请救兵不是。干!
服务器在内网,有瘦终端可以访问。MacBook 只能访问外网,一边查资料,一边比对着在内网做,效果不好,老是担心现有环境给整趴了:开发测试那边就没得玩了。干过开发的都知道,服务器从来都是直接上 root 账号。干过运维的人都知道,永远别碰 root。╮(╯▽╰)╭哎,职业病,还是小心谨慎地好。
只能调整了方法:先在 MacBook 上搭建单机多实例,验证通过之后,再去内网服务器动手。本来计划20~30分钟搞完的事,最终花了小半天时间验证了方案,在内网实施的时候,又遇到苛刻的环境限制,逐步排雷,最终搞定。客户满意,项目进度开心。
根据实际环境,判断问题解决方向:单机多实例;放弃内网危险的尝试:不能快速有效解决,且账号权限太大;选择外网验证方案后再进内网实施。很多时候,选择大于努力。
写个验证文件打包成 war 包。为啥不使用现有代码。一是因为现有 war 包在内网,二是因为太复杂,除了问题不能排除是代码自身的问题还是我们的部署方式有问题,或者是内外网网络环境的问题,亦或是 RPWT。
对于验证方案,排查问题时,尽量简化,抛却一切外在的东西,只验证核心。方案验证通过,再引入实际war包验证。这和面向对象编程的指导思想是一致的:通过抽象来提炼最核心的东西,每次聚焦一个地方,不要全面出击。人,毕竟精力有限。
至于为什么用 tomcat7,没什么,客户这儿只允许这个版本。
已 commit 到 docker hub,心急的童鞋自行
docker pull aninputforce/tomcat7-ins
这个不是诊断问题的思路,是最终解决完问题后的,对整体方案的梳理,这样的顺序才整洁,有基础时间紧的童鞋直接看这个就足够了。有时间的童鞋可以看看正文,贯穿了分析问题解决问题的思路。
# 简化问题:建模先--宿主机编辑 -> jdk7打war包 -> tomcat默认配置 -> 单机单实例 -> 单机双实例 ├── # docker搭建jdk7初始环境:用来打包验证用的war包 │ ├── docker search jdk7 │ ├── docker pull codenvy/jdk7 │ ├── docker run --name jjj codenvy/jdk7 /bin/bash │ ├── java -version && mkdir ~/web && ls ~/ && exit # 镜像容器环境工作正常,创建工作目录,退出 │ ├── mkdir ~/prms001 ~/prms002 # 宿主机 │ ├── # 编辑prms001/index.htm,编辑prms002/index.htm │ ├── docker cp prms001 jjj:/home/user/web && docker cp prms002 jjj:/home/user/web │ ├── docker exec -it jjj /bin/bash # 进入容器 │ ├── sudo chown -R user:user prms001 prms002 改变属组 │ ├── cd ~/web/prms001 && jar -cvf prms001.war ./* && ls -la │ ├── cd ~/web/prms002 && jar -cvf prms002.war ./* && ls -la && exit │ ├── docker cp jjj:/home/user/web/prms001/prms001.war ~/. │ ├── docker cp jjj:/home/user/web/prms002/prms002.war ~/. │ └── docker rm jjj # 退出容器,jdk7容器使命结束 ├── # docker搭建tomcat7初始环境:用来推演单机多实例 │ ├── # docker拉取tomcat7镜像 │ ├── # 启动名为www的tomcat容器 │ │ ├── ./startup.sh # 启动web服务 │ │ ├── curl localhost:8080 # 访问正常 │ │ ├── ./shutdown.sh # 停止web服务 │ │ └── # 搭建第一个实例 │ │ ├── mkdir tom-ins001 │ │ ├── mv work tom-ins001/ && mv conf/ tom-ins001/ mv logs/ tom-ins001/ │ │ ├── mv temp/ tom-ins001/ && mv webapps/ tom-ins001/ │ │ ├── export CATALINA_BASE=$CATALINA_HOME/tom-ins001/ │ │ ├── sh $CATALINA_HOME/bin/startup.sh -Dcatalina.base │ │ ├── curl localhost:8080 # 访问正常 │ │ └── exit && docker commit www mytomcat:latest && docker rm www # 容器www使命结束 │ └── docker run --name web -it -p 8080:8080 -p 80:80 mytomcat /bin/bash # 启动新容器 │ ├── # 启动第一个实例 │ │ ├── export CATALINA_BASE=$CATALINA_HOME/tom-ins001/ │ │ ├── sh $CATALINA_HOME/bin/startup.sh -Dcatalina.base │ │ └── curl localhost:8080 # 访问正常 │ └── # 搭建并启动第二个实例 │ ├── cp -r tom-ins001/ tom-ins002 │ ├── # 编辑tom-ins002/conf/server.xml的3个端口,规避和实例1冲突, │ │ ├── Server port="8001"、 Connector port="80" protocol="HTTP/1.1" │ │ ├── Connector port="8002" protocol="AJP/1.3" │ │ ├── docker cp www:/usr/local/tomcat/conf/server.xml . │ │ ├── vi server.xml │ │ └── docker cp ./server.xml www:/usr/local/tomcat/conf/ │ └── # 启动新容器 启动实例2 │ ├── export CATALINA_BASE=$CATALINA_HOME/tom-ins002/ │ ├── sh $CATALINA_HOME/bin/startup.sh -Dcatalina.base │ ├── curl localhost:80 # 访问正常 │ ├── exit && docker commit web mytomcat:latest │ └── docker rm web # 容器web使命结束 └── # 展示单机双实例: ├── # 配置实例2根目录运行 │ ├── docker run --name web -d -it -p 8080:8080 -p 80:80 mytomcat /bin/bash # 启动新容器 │ ├── docker exec -it web /bin/bash │ ├── cd /usr/local/tomcat/tom-ins002/webapps && tar cvf rootbak.tar ./ROOT/* │ ├── cd ROOT && rm -rf * # 清空ROOT目录 │ ├── mkdir /usr/local/tomcat/myapps && exit # 创建实例2war包存放目录,退出容器 ├── # 部署实例1、实例2的war包,启动验证 │ ├── # 编辑ROOT.xml,配置实例2的war包解到 /usr/local/tomcat/tom-ins002/ROOT 目录 │ ├── docker cp ~/ROOT.xml web:/usr/local/tomcat/tom-ins002/conf/Catalina/localhost │ ├── docker cp ~/prms002.war web:/usr/local/tomcat/myapps │ └── docker cp ~/prms001.war web:/usr/local/tomcat/tom-ins001/webapps ├── docker exec -it web /bin/bash │ ├── export CATALINA_BASE=$CATALINA_HOME/tom-ins001/ │ ├── sh $CATALINA_HOME/bin/startup.sh -Dcatalina.base │ ├── curl localhost:8080 # 访问正常:Hello from Tomcat instance 001 │ ├── export CATALINA_BASE=$CATALINA_HOME/tom-ins002/ │ ├── sh $CATALINA_HOME/bin/startup.sh -Dcatalina.base │ └── curl localhost # 访问正常:Hello from Tomcat instance 002 └── # 宿主机验证 ├── curl localhost:8080 # 访问正常:Hello from Tomcat instance 001 ├── curl localhost # 访问正常:Hello from Tomcat instance 002 └── exit && docker commit web mytomcat:latest # 退出,提交容器变动到镜像,验证通过;
以下开始讲故事:
换做十年前,要学习 Java,光搭建个环境,就能耗尽新人 90% 的热情。放弃内网尝试,转由外网先验证方案,我也是经过略微的思想斗争的,不过转念一想,有 Docker 神器,也就淡定了。
在内网的一番碰墙,也不是没有一点儿成果,至少理顺了方向:
开始,进行 tomcat 单机多实例方案的推演。
至于docker环境搭建,请参考官方文档。我的另一篇笔记里附有链接:<u style="text-decoration: none; border-bottom: 1px dashed rgb(128, 128, 128);">Docker的第一次亲密接触( https://my.oschina.net/hexie/blog/785315 )</u>
docker pull tomcat:7.0
容器名www,端口8080:
ChinaDreams:work-diary kangcunhua$ docker run --name www -it -p 8080:8080 tomcat:7.0 /bin/bash root@4b8f58d2cd64:/usr/local/tomcat# cd bin root@4b8f58d2cd64:/usr/local/tomcat/bin# java -version java version "1.7.0_131" OpenJDK Runtime Environment (IcedTea 2.6.9) (7u131-2.6.9-2~deb8u1) OpenJDK 64-Bit Server VM (build 24.131-b00, mixed mode) root@4b8f58d2cd64:/usr/local/tomcat/bin# ./startup.sh root@4b8f58d2cd64:/usr/local/tomcat/bin# ps -ef | grep java root@4b8f58d2cd64:/usr/local/tomcat/logs# tail -f catalina.out root@4b8f58d2cd64:/usr/local/tomcat/logs# curl localhost:8080
查看 java 进程有,查看日志正常,访问 http://localhost:8080 正常,证明镜像和容器是可以正常工作的。
root@4b8f58d2cd64:/usr/local/tomcat# mkdir tom-ins001 root@4b8f58d2cd64:/usr/local/tomcat# ls LICENSE RELEASE-NOTES bin include logs native-jni-lib tom-ins001 work NOTICE RUNNING.txt conf lib myapps temp webapps root@4b8f58d2cd64:/usr/local/tomcat# mv work tom-ins001/ root@4b8f58d2cd64:/usr/local/tomcat# mv conf/ tom-ins001/ root@4b8f58d2cd64:/usr/local/tomcat# mv logs/ tom-ins001/ root@4b8f58d2cd64:/usr/local/tomcat# mv temp/ tom-ins001/ root@4b8f58d2cd64:/usr/local/tomcat# mv webapps/ tom-ins001/ root@4b8f58d2cd64:/usr/local/tomcat# ls LICENSE NOTICE RELEASE-NOTES RUNNING.txt bin include lib myapps native-jni-lib tom-ins001 root@4b8f58d2cd64:/usr/local/tomcat# cd tom-ins001/ root@4b8f58d2cd64:/usr/local/tomcat/tom-ins001# ls conf logs temp webapps work root@4b8f58d2cd64:/usr/local/tomcat/tom-ins001# echo $CATALINA_HOME /usr/local/tomcat root@4b8f58d2cd64:/usr/local/tomcat/tom-ins001# export CATALINA_BASE=$CATALINA_HOME/tom-ins001/ root@4b8f58d2cd64:/usr/local/tomcat/tom-ins001# sh $CATALINA_HOME/bin/startup.sh -Dcatalina.base root@4b8f58d2cd64:/usr/local/tomcat/tom-ins001# ps -ef | grep java root@4b8f58d2cd64:/usr/local/tomcat/tom-ins001# tail -f catalina.out root@4b8f58d2cd64:/usr/local/tomcat/tom-ins001# curl localhost:8080
启动成功,宿主机访问 http://localhost:8080 正常
root@4b8f58d2cd64:/usr/local/tomcat/tom-ins001# exit ChinaDreams:~ kangcunhua$ docker commit www mytomcat:latest
基于刚提交生成的镜像,新启一个容器。启动实例1,验证正常
ChinaDreams:~ kangcunhua$ docker run --name web -it -p 8080:8080 -p 80:80 mytomcat /bin/bash root@c8cc5f309d18:/usr/local/tomcat/tom-ins001# export CATALINA_BASE=$CATALINA_HOME/tom-ins001 root@c8cc5f309d18:/usr/local/tomcat/tom-ins001# sh $CATALINA_HOME/bin/startup.sh -Dcatalina.base root@c8cc5f309d18:/usr/local/tomcat/tom-ins001# ps -ef | grep java root@c8cc5f309d18:/usr/local/tomcat/tom-ins001# tail -f catalina.out root@c8cc5f309d18:/usr/local/tomcat/tom-ins001# curl localhost:8080
root@c8cc5f309d18:/usr/local/tomcat# cp -r tom-ins001/ tom-ins002 root@c8cc5f309d18:/usr/local/tomcat# ls LICENSE NOTICE RELEASE-NOTES RUNNING.txt bin include lib myapps native-jni-lib tom-ins001 tom-ins002 root@c8cc5f309d18:/usr/local/tomcat# cd tom-ins002 root@c8cc5f309d18:/usr/local/tomcat/tom-ins002# ls conf logs temp webapps work root@c8cc5f309d18:/usr/local/tomcat/tom-ins002# cd .. root@c8cc5f309d18:/usr/local/tomcat# cd tom-ins001/ root@c8cc5f309d18:/usr/local/tomcat/tom-ins001# ls conf logs temp webapps work
主要是修改三处端口,避免和实例1端口冲突。
<?xml version='1.0' encoding='utf-8'?> <Server port="8001" shutdown="SHUTDOWN"> <!-- 此处省略了无修改的内容 --> <Service name="Catalina"> <Connector port="80" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> <Connector port="8002" protocol="AJP/1.3" redirectPort="8443" /> <!-- 此处省略了无修改的内容 --> </Service> </Server>
作用是指定一个不在 webapps 目录的 war 包,部署时自动解压到 webapps/ROOT 目录。
<?xml version="1.0" encoding="UTF-8"?> <Context path="/prms" docBase="/usr/local/tomcat/myapps/prms002.war"></Context>
ChinaDreams:~ kangcunhua$ docker cp ~/ROOT.xml www:/usr/local/tomcat/tom-ins002/conf/Catalina/localhost ChinaDreams:~ kangcunhua$ docker exec -it www /bin/bash root@4b8f58d2cd64:/usr/local/tomcat# cd conf/Catalina/localhost/ root@4b8f58d2cd64:/usr/local/tomcat/conf/Catalina/localhost# ls ROOT.xml root@4b8f58d2cd64:/usr/local/tomcat/conf/Catalina/localhost# more ROOT.xml <?xml version="1.0" encoding="UTF-8"?> <Context path="/prms" docBase="/usr/local/tomcat/myapps/prms002.war"></Context> root@4b8f58d2cd64:/usr/local/tomcat/conf/Catalina/localhost# pwd /usr/local/tomcat/conf/Catalina/localhost
root@4b8f58d2cd64:/usr/local/tomcat/conf/Catalina/localhost# ls -al total 12 drwxr-xr-x 2 root root 4096 Jul 31 05:58 . drwxr-xr-x 3 root root 4096 Jul 31 04:23 .. -rw-r--r-- 1 502 dialout 111 Jul 31 05:56 ROOT.xml root@4b8f58d2cd64:/usr/local/tomcat/conf/Catalina/localhost# chown root:root ROOT.xml root@4b8f58d2cd64:/usr/local/tomcat/conf/Catalina/localhost# ls -la total 12 drwxr-xr-x 2 root root 4096 Jul 31 05:58 . drwxr-xr-x 3 root root 4096 Jul 31 04:23 .. -rw-r--r-- 1 root root 111 Jul 31 05:56 ROOT.xml
在 tomcat 容器中,发现 jar 命令找不到。
root@4b8f58d2cd64:/usr/local/tomcat/webapps/examples# jar -cvf prms.war ./* bash: jar: command not found
本地没有 java 环境。果断上 docker 构建一个
ChinaDreams:~ kangcunhua$ docker search jdk7 ChinaDreams:~ kangcunhua$ docker pull codenvy/jdk7 ChinaDreams:~ kangcunhua$ docker run --name jjj -it codenvy/jdk7 /bin/bash user@b040d98042c0:/$ java -version user@b040d98042c0:/$ jar user@b040d98042c0:/$ mkdir ~/web && ls ~/ && exit 创建工作目录,退出
ChinaDreams:~ kangcunhua$ mkdir ~/prms001 ~/prms002 ChinaDreams:~ kangcunhua$ vi ~/prms001/index.html ChinaDreams:~ kangcunhua$ vi ~/prms002/index.html ChinaDreams:~ kangcunhua$ docker cp prms001 jjj:/home/user/web && docker cp prms002 jjj:/home/user/web ChinaDreams:~ kangcunhua$ docker exec -it jjj /bin/bash 进入容器 user@b040d98042c0:~/web$ sudo chown -R user:user prms001 prms002 改变属组 user@b040d98042c0:~/web$ cd ~/web/prms001 && jar -cvf prms001.war ./* && ls -la user@b040d98042c0:~/web$ cd ~/web/prms002 && jar -cvf prms002.war ./* && ls -la && exit ChinaDreams:~ kangcunhua$ docker cp jjj:/home/user/web/prms001/prms001.war ~/. ChinaDreams:~ kangcunhua$ docker cp jjj:/home/user/web/prms001/prms002.war ~/. ChinaDreams:~ kangcunhua$ docker rm jjj 退出容器,jdk7容器使命结束
<html> <head> <meta charset="UTF-8" > <title> Tomcat instance 1</title> </head> <body> <h1> Hello from Tomcat instance 1</h1> </body> </html>
<html> <head> <meta charset="UTF-8" > <title> Tomcat instance 2</title> </head> <body> <h1> Hello from Tomcat instance 2</h1> </body> </html>
回到 tomcat 容器
root@c8cc5f309d18:/usr/local/tomcat# export CATALINA_BASE=$CATALINA_HOME/tom-ins001 root@c8cc5f309d18:/usr/local/tomcat# sh $CATALINA_HOME/bin/startup.sh -Dcatalina.base root@c8cc5f309d18:/usr/local/tomcat# curl localhost:8080 访问正常 root@c8cc5f309d18:/usr/local/tomcat# export CATALINA_BASE=$CATALINA_HOME/tom-ins002/ root@c8cc5f309d18:/usr/local/tomcat# sh $CATALINA_HOME/bin/startup.sh -Dcatalina.base root@c8cc5f309d18:/usr/local/tomcat# curl localhost:80 访问正常
docker commit web mytomcat:latest && docker rm web
ocker run --name web -it -p 8080:8080 -p 80:80 mytomcat /bin/bash
<u style="text-decoration: none; border-bottom: 1px dashed rgb(128, 128, 128);"> http://localhost/ </u> 访问正常:Hello from Tomcat instance 001.
<u style="text-decoration: none; border-bottom: 1px dashed rgb(128, 128, 128);"> http://localhost:8080 </u> 访问正常:Hello from Tomcat instance 002.
单机多实例方案本地通过
export CATALINA_BASE=$CATALINA_HOME/tom-ins001 && sh $CATALINA_HOME/bin/startup.sh -Dcatalina.base export CATALINA_BASE=$CATALINA_HOME/tom-ins002 && sh $CATALINA_HOME/bin/startup.sh -Dcatalina.base
export CATALINA_BASE=$CATALINA_HOME/tom-ins001 && sh $CATALINA_HOME/bin/shutdown.sh -Dcatalina.base export CATALINA_BASE=$CATALINA_HOME/tom-ins002 && sh $CATALINA_HOME/bin/shutdown.sh -Dcatalina.base
ps -ef | grep java kill -9 xxx tomcat实例进程号 tail -f $CATALINA_HOME/tom-ins001/logs/catalina.out tail -f $CATALINA_HOME/tom-ins002/logs/catalina.out curl localhost:8080/prms001/ curl localhost
保留了最关键的要素:
. ├── bin ├── lib ├── myapps │ └── prms002.war ├── tom-ins001 │ ├── conf │ │ └── server.xml │ ├── logs │ │ └── catalina.out │ ├── webapps │ │ ├── prms001 │ │ └── prms001.war │ └── work └── tom-ins002 ├── conf │ ├── Catalina │ │ └── localhost │ │ └── ROOT.xml │ └── server.xml ├── logs ├── temp ├── webapps │ └── ROOT │ ├── META-INF │ │ └── MANIFEST.MF │ └── index.htm └── work
update:2017.8.8
ChinaDreams:work-diary kangcunhua$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE mytomcat latest 3f6c6cce5355 7 days ago 370MB ChinaDreams:work-diary kangcunhua$ docker tag 3f6c6cce5355 aninputforce/tomcat7-ins:latest ChinaDreams:work-diary kangcunhua$ docker push aninputforce/tomcat7-ins ChinaDreams:work-diary kangcunhua$ docker push aninputforce/tomcat7-ins:1.0 ChinaDreams:work-diary kangcunhua$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE mytomcat latest 3f6c6cce5355 7 days ago 370MB aninputforce/tomcat7-ins 1.0 3f6c6cce5355 7 days ago 370MB aninputforce/tomcat7-ins latest 3f6c6cce5355 7 days ago 370MB
一切都很顺利,直到碰上访问80端口。。。。
备份后,搭建实例1,确保原始应用能正常;
停止实例1,保证实例2默认也能运行;
编辑server.xml,ROOT.xml,清空ROOT目录,新建myapps目录,拷贝war包进去;
curl http://localhost web server上访问正常。
局域网访问 , http://10.29.11.23 不!能!访!问!!!
实例2需要使用 80 端口。受阻。
坑+:没有任何限制。我们需要客户的信息,但是不能全信。就像这次请教客户说的“我们对端口没有任何限制”。不要盲目相信客户说的,要相信科学排查。
依稀记得架构师课程 PC 大神讲过,linux 默认只有 root 用户才能访问 80 端口。当时我一直有个疑问,那我们 web server 需要用到 80 端口是怎么解决的?我记得请教过PC 老师,可惜当时课程紧,虽然听的云里雾里的,也没好意思多追问,更没线下自己实践。直到这次在客户现场栽了跟头。
开发测试环境,我们倒是有 root 账号,但是我们 web server 总不能用 root 部署吧,太不专业了。在 Reboot 校友群中厚着脸皮请教了各位童鞋,很快 get 了解决方案:将所有80端口的访问,转发到 8081 即可;8081 就是我们可以配置的 tomcat 实例2的访问端口,这个是普通用户有权限的。
刚检查防火墙时,看到 80 端口是放开的。部署机上可以访问,局域网打不开:将所有针对 80 端口的访问,转发到 8081。
[root@tomcat7conf]# iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8081
修改了 tomins-002 的 server.xml,仍是部署机上可以访问,局域网打不开;
配置上 8081 端口,重启防火墙生效,部署机访问正常,局域网打开正常
找到 FW_SERVICES_EXT_TCP,加上 8081 端口
[root@tomcat7conf]# vi /etc/sysconfig/SuSEfirewall2 [root@tomcat7conf]# rcSuSEfirewall2 restart
切换到 tomcat 用户,重启 tomcat,局域网访问正常。
发现系统首页这个链接,虽然配置的是”#”,但是一点击就回到 project 的路径。经查找文件,发现是在开发平台的两个js文件中,写了硬编码。应该是平台自动生成代码时用了硬编码,改之。
发现只要是配置了根目录访问,统一认证就报错。去掉统一认证接入就能正常访问。反馈给客户,协调解决;悬了两天,未能有任何反馈,追着逼急了,唯一答案就是:成熟产品,我们不要先去怀疑统一认证平台。
我这个暴脾气,马上和工程师排查。单步跟一下,发现是提交到统一认证时,我们要传过去一个参数 ssotarget,这个 ssotarget 是通过认证后,浏览器要打开的首页,context-path 不为空时,url 正常,context-path 为 null,即我们部署到根目录时,ssotarget 只能得到个”/“。检查统一认证接入逻辑,发现是使用了平台提供的 filter,反编译,单步跟踪,发现 ssotarget 来自 homepage 的赋值。捏着鼻子看源码,果然代码逻辑有问题,伪算法如下:
String ccontext_path=request.getContextPath(); // 得到web 服务上下文 String urlt = requerst.getRequestURL(); // 得到请求的完整网址 String cwebhost = urlt.substring(0, urlt.IndexOf (context-path)); // 得到http://hostname:端口 homepage = webhost + context_path + "/"; // 拼出web server的应用首页地址
改之
String context_path = request.getContextPath(); String homepage = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
尝试,自己改了源码之后重新打 jar 包,commit svn,jenkins 编译部署后发现没起作用。想起来使用的是 maven,所有 jar 包都来自平台的私有仓库,这。。。
换种思路,写个 java 类继承一下,结果一看对应逻辑所在 function,private 的,往上再看 class,finall 的,一万只神兽啊!!!
要啥面向对象,简单粗暴,源码照抄,修订了后命名为 MySsoFilter.java,在工程配置文件替换上我们写的 filter,svn commit,jenkins 立即构建部署,世间从此安静。
docker + k8s
此课程为网络直播课程,一共 10 个课时,每周上一个全天,历时两个多月。附加:录播视频+笔记+除课堂外的答疑时间(7次+)2019-1-13 开课,原价 5800 ,现在周年活动 100 定金抵 500
课程主讲师
10年一线软件开发经验,先后经历了传统安全公司,以及多家互联网公司;在安全开发方面,曾开发过 Linux 防火墙、web 应用防火墙、Linux 安全内核加固,基于大流量的 Web 安全威胁分析等项目;在互联网公司工作时,曾基于 DPDK 高性能网络开发框架开发过基于全流量的网络流量分析平台和基于 Sflow 网络流量分析平台,基于 Golang 开发 SmartDNS 等;开发语言也是从C -> python -> golang 的转变过程?现从事基于 K8S 和 Docker在私有云平台建设方面的研发工作;具备丰富的Linux系统开发经验、网络开发经验以及项目管理经验;目前开发工作90+% 都在用 Golang,Golang 是一门简洁、高效、强大且灵活的编程语言。
关于课程的具体内容想要了解的, 扫码加小助手咨询
扫码咨询,备注“来源简书”