多节点 docker 部署 elastic 集群
参考
Install Elasticsearch with Docker
Images
环境
docker
# docker version
Client: Docker Engine - CommunityVersion: 24.0.7API version: 1.43Go version: go1.20.10Git commit: afdd53bBuilt: Thu Oct 26 09:08:01 2023OS/Arch: linux/amd64Context: defaultServer: Docker Engine - CommunityEngine:Version: 24.0.7API version: 1.43 (minimum version 1.12)Go version: go1.20.10Git commit: 311b9ffBuilt: Thu Oct 26 09:08:01 2023OS/Arch: linux/amd64Experimental: falsecontainerd:Version: 1.6.26GitCommit: 3dd1e886e55dd695541fdcd67420c2888645a495runc:Version: 1.1.10GitCommit: v1.1.10-0-g18a0cb0docker-init:Version: 0.19.0GitCommit: de40ad0
# docker compose version
Docker Compose version v2.21.0
images
image | tag |
---|---|
docker.elastic.co/kibana/kibana | 8.11.2-amd64 |
docker.elastic.co/elasticsearch/elasticsearch | 8.11.2-amd64 |
环境
node | role | MountPoint |
---|---|---|
172.22.175.110 | es01 kibana | /opt/data/es01 /opt/data/kibana |
172.22.175.111 | es02 | /opt/data/es02 |
172.22.175.112 | es03 | /opt/data/es03 |
- /etc/hosts
127.0.0.1 localhost
172.22.175.110 es01
172.22.175.111 es02
172.22.175.112 es03
- sysctl
# echo "vm.max_map_count=262144" >>/etc/sysctl.conf
# sysctl -p
部署
es01
- 挂载目录准备
# mkdir -p /opt/data/{es01,kibana}
### container 中使用非 root 运行的 es 和 kibana, 他们账户的 id 是 1000
# chown -R 1000:1000 /opt/data/{es01,kibana}
- .env
# Password for the 'elastic' user (at least 6 characters)
ELASTIC_PASSWORD=1qazXSW@# Password for the 'kibana_system' user (at least 6 characters)
KIBANA_PASSWORD=1qazXSW@# Version of Elastic products
STACK_VERSION=8.11.2-amd64# Set the cluster name
CLUSTER_NAME=bj-es-docker# Set to 'basic' or 'trial' to automatically start the 30-day trial
LICENSE=basic
#LICENSE=trial# Port to expose Elasticsearch HTTP API to the host
ES_PORT=9200
#ES_PORT=127.0.0.1:9200# Port to expose Kibana to the host
KIBANA_PORT=5601
#KIBANA_PORT=80# Increase or decrease based on the available host memory (in bytes)
MEM_LIMIT=17179869184# Project namespace (defaults to the current folder name if not set)
#COMPOSE_PROJECT_NAME=myproject
- docker-compose.yaml
version: "3"services:setup:image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}volumes:- ./certs:/usr/share/elasticsearch/config/certsuser: "0"command: >bash -c 'if [ x${ELASTIC_PASSWORD} == x ]; thenecho "Set the ELASTIC_PASSWORD environment variable in the .env file";exit 1;elif [ x${KIBANA_PASSWORD} == x ]; thenecho "Set the KIBANA_PASSWORD environment variable in the .env file";exit 1;fi;if [ ! -f config/certs/ca.zip ]; thenecho "Creating CA";bin/elasticsearch-certutil ca --silent --pem -out config/certs/ca.zip;unzip config/certs/ca.zip -d config/certs;fi;if [ ! -f config/certs/certs.zip ]; thenecho "Creating certs";echo -ne \"instances:\n"\" - name: es01\n"\" dns:\n"\" - es01\n"\" ip:\n"\" - 172.22.175.110\n"\" - name: es02\n"\" dns:\n"\" - es02\n"\" ip:\n"\" - 172.22.175.111\n"\" - name: es03\n"\" dns:\n"\" - es03\n"\" ip:\n"\" - 172.22.175.112\n"\> config/certs/instances.yml;bin/elasticsearch-certutil cert --silent --pem -out config/certs/certs.zip --in config/certs/instances.yml --ca-cert config/certs/ca/ca.crt --ca-key config/certs/ca/ca.key;unzip config/certs/certs.zip -d config/certs;fi;echo "Setting file permissions"chown -R root:root config/certs;find . -type d -exec chmod 750 \{\} \;;find . -type f -exec chmod 640 \{\} \;;echo "Waiting for Elasticsearch availability";until curl -s --cacert config/certs/ca/ca.crt https://es01:9200 | grep -q "missing authentication credentials"; do sleep 30; done;echo "Setting kibana_system password";until curl -s -X POST --cacert config/certs/ca/ca.crt -u "elastic:${ELASTIC_PASSWORD}" -H "Content-Type: application/json" https://es01:9200/_security/user/kibana_system/_password -d "{\"password\":\"${KIBANA_PASSWORD}\"}" | grep -q "^{}"; do sleep 10; done;echo "All done!";'healthcheck:test: ["CMD-SHELL", "[ -f config/certs/es01/es01.crt ]"]interval: 1stimeout: 5sretries: 120es01:depends_on:setup:condition: service_healthyimage: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}volumes:- ./certs:/usr/share/elasticsearch/config/certs- /opt/data/es01:/usr/share/elasticsearch/dataenvironment:- node.name=es01- cluster.name=${CLUSTER_NAME}- cluster.initial_master_nodes=es01,es02,es03- discovery.seed_hosts=es02,es03- ELASTIC_PASSWORD=${ELASTIC_PASSWORD}- bootstrap.memory_lock=true- xpack.security.enabled=true- xpack.security.http.ssl.enabled=true- xpack.security.http.ssl.key=certs/es01/es01.key- xpack.security.http.ssl.certificate=certs/es01/es01.crt- xpack.security.http.ssl.certificate_authorities=certs/ca/ca.crt- xpack.security.transport.ssl.enabled=true- xpack.security.transport.ssl.key=certs/es01/es01.key- xpack.security.transport.ssl.certificate=certs/es01/es01.crt- xpack.security.transport.ssl.certificate_authorities=certs/ca/ca.crt- xpack.security.transport.ssl.verification_mode=certificate- xpack.license.self_generated.type=${LICENSE}restart: alwaysnetwork_mode: hostulimits:memlock:soft: -1hard: -1healthcheck:test:["CMD-SHELL","curl -s -k --cacert config/certs/ca/ca.crt https://localhost:9200 | grep -q 'missing authentication credentials'",]interval: 10stimeout: 10sretries: 120kibana:depends_on:es01:condition: service_healthyimage: docker.elastic.co/kibana/kibana:${STACK_VERSION}volumes:- ./certs:/usr/share/kibana/config/certs- /opt/data/kibana:/usr/share/kibana/dataenvironment:- SERVERNAME=kibana- ELASTICSEARCH_HOSTS=https://es01:9200- ELASTICSEARCH_USERNAME=kibana_system- ELASTICSEARCH_PASSWORD=${KIBANA_PASSWORD}- ELASTICSEARCH_SSL_CERTIFICATEAUTHORITIES=config/certs/ca/ca.crtrestart: alwaysnetwork_mode: hosthealthcheck:test:["CMD-SHELL","curl -k -s -I http://localhost:5601 | grep -q 'HTTP/1.1 302 Found'",]interval: 10stimeout: 10sretries: 120
- 启动
# docker compose up -d
[+] Running 4/4✔ Network es_default Created 0.2s✔ Container es-setup-1 Healthy 0.4s✔ Container es-es01-1 Healthy 0.1s✔ Container es-kibana-1 Started 0.1s
- 同步 certs 和 .env 到其他节点
# scp -r certs/ .env es02:/opt/compose/es/
ca.crt 100% 1200 899.3KB/s 00:00
ca.key 100% 1675 1.4MB/s 00:00
certs.zip 100% 7615 6.8MB/s 00:00
ca.zip 100% 2515 2.5MB/s 00:00
es03.crt 100% 1176 1.3MB/s 00:00
es03.key 100% 1675 1.8MB/s 00:00
instances.yml 100% 230 228.9KB/s 00:00
es01.crt 100% 1176 1.2MB/s 00:00
es01.key 100% 1675 1.7MB/s 00:00
es02.key 100% 1675 1.2MB/s 00:00
es02.crt 100% 1172 1.1MB/s 00:00
.env
# scp -r certs/ .env es03:/opt/compose/es/
ca.crt 100% 1200 197.9KB/s 00:00
ca.key 100% 1675 849.8KB/s 00:00
certs.zip 100% 7615 3.3MB/s 00:00
ca.zip 100% 2515 1.5MB/s 00:00
es03.crt 100% 1176 604.2KB/s 00:00
es03.key 100% 1675 932.1KB/s 00:00
instances.yml 100% 230 140.3KB/s 00:00
es01.crt 100% 1176 652.2KB/s 00:00
es01.key 100% 1675 1.2MB/s 00:00
es02.key 100% 1675 672.5KB/s 00:00
es02.crt 100% 1172 844.9KB/s 00:00
.env
es02
- 挂载目录准备
# mkdir -p /opt/data/es02
# chown -R 1000:1000 /opt/data/es02
- .env
同 es01 - docker-compose.yaml
version: '3'
services:es02:image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}volumes:- ./certs:/usr/share/elasticsearch/config/certs- /opt/data/es02/:/usr/share/elasticsearch/dataenvironment:- node.name=es02- cluster.name=${CLUSTER_NAME}- cluster.initial_master_nodes=es01,es02,es03- discovery.seed_hosts=es01,es03- bootstrap.memory_lock=true- xpack.security.enabled=true- xpack.security.http.ssl.enabled=true- xpack.security.http.ssl.key=certs/es02/es02.key- xpack.security.http.ssl.certificate=certs/es02/es02.crt- xpack.security.http.ssl.certificate_authorities=certs/ca/ca.crt- xpack.security.transport.ssl.enabled=true- xpack.security.transport.ssl.key=certs/es02/es02.key- xpack.security.transport.ssl.certificate=certs/es02/es02.crt- xpack.security.transport.ssl.certificate_authorities=certs/ca/ca.crt- xpack.security.transport.ssl.verification_mode=certificate- xpack.license.self_generated.type=${LICENSE}restart: alwaysnetwork_mode: hostulimits:memlock:soft: -1hard: -1healthcheck:test:["CMD-SHELL","curl -s -k --cacert config/certs/ca/ca.crt https://localhost:9200 | grep -q 'missing authentication credentials'",]interval: 10stimeout: 10sretries: 120
- 启动
# docker compose up -d
[+] Running 1/1✔ Container es-es02-1 Started
### 等一会儿,等 health 变成 healthy
# docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
es-es02-1 docker.elastic.co/elasticsearch/elasticsearch:8.11.2-amd64 "/bin/tini -- /usr/local/bin/docker-entrypoint.sh eswrapper" es02 12 seconds ago Up 10 seconds (health: starting)
。。。
# docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
es-es02-1 docker.elastic.co/elasticsearch/elasticsearch:8.11.2-amd64 "/bin/tini -- /usr/local/bin/docker-entrypoint.sh eswrapper" es02 3 minutes ago Up 3 minutes (healthy)
es03
- 挂载目录准备
# mkdir -p /opt/data/es03
# chown -R 1000:1000 /opt/data/es03
- .env
同 es01 - docker-compose.yaml
version: '3'
services:es03:image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}volumes:- ./certs:/usr/share/elasticsearch/config/certs- /opt/data/es03:/usr/share/elasticsearch/dataenvironment:- node.name=es03- cluster.name=${CLUSTER_NAME}- cluster.initial_master_nodes=es01,es02,es03- discovery.seed_hosts=es01,es02- bootstrap.memory_lock=true- xpack.security.enabled=true- xpack.security.http.ssl.enabled=true- xpack.security.http.ssl.key=certs/es03/es03.key- xpack.security.http.ssl.certificate=certs/es03/es03.crt- xpack.security.http.ssl.certificate_authorities=certs/ca/ca.crt- xpack.security.transport.ssl.enabled=true- xpack.security.transport.ssl.key=certs/es03/es03.key- xpack.security.transport.ssl.certificate=certs/es03/es03.crt- xpack.security.transport.ssl.certificate_authorities=certs/ca/ca.crt- xpack.security.transport.ssl.verification_mode=certificate- xpack.license.self_generated.type=${LICENSE}restart: alwaysnetwork_mode: hostulimits:memlock:soft: -1hard: -1healthcheck:test:["CMD-SHELL","curl -s -k --cacert config/certs/ca/ca.crt https://localhost:9200 | grep -q 'missing authentication credentials'",]interval: 10stimeout: 10sretries: 120
- 启动
s# docker compose up -d
[+] Running 1/1✔ Container es-es03-1 Started
### 等一会儿,等 health 变成 healthy
# docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
es-es03-1 docker.elastic.co/elasticsearch/elasticsearch:8.11.2-amd64 "/bin/tini -- /usr/local/bin/docker-entrypoint.sh eswrapper" es03 12 seconds ago Up 11 seconds (health: starting)
。。。
# docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
es-es03-1 docker.elastic.co/elasticsearch/elasticsearch:8.11.2-amd64 "/bin/tini -- /usr/local/bin/docker-entrypoint.sh eswrapper" es03 About a minute ago Up About a minute (healthy)
验证
# curl --user "elastic:1qazXSW@" -k https://172.22.175.110:9200/_cat/nodes?v
ip heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
172.22.175.111 6 67 1 0.31 0.83 0.54 cdfhilmrstw * es02
172.22.175.112 10 65 2 1.58 0.80 0.31 cdfhilmrstw - es03
172.22.175.110 12 90 2 0.67 0.82 0.88 cdfhilmrstw - es01
# curl --user "elastic:1qazXSW@" -k https://172.22.175.110:9200/_cat/health?v
epoch timestamp cluster status node.total node.data shards pri relo init unassign pending_tasks max_task_wait_time active_shards_percent
1705029621 03:20:21 bj-es-docker green 3 3 61 30 0 0 0 0 - 100.0%
### PS: kibana 也能通过浏览器访问和使用
总结
官网的例子是在 1 个节点上通过 docker-compose 跑起来的 3 个实例,不符合需求,故将官方的 docker-compose.yml 进行拆分加上适当的调整来满足需求;因犯懒癌,所以将网络都设置为 host 模式,避免网络问题去 troubleshooting 半天,从而运气不错,一次性搞定。
相关文章:

多节点 docker 部署 elastic 集群
参考 Install Elasticsearch with Docker Images 环境 docker # docker version Client: Docker Engine - CommunityVersion: 24.0.7API version: 1.43Go version: go1.20.10Git commit: afdd53bBuilt: Thu Oct 26 09:08:01 202…...

2023年全国职业院校技能大赛软件测试赛题—单元测试卷⑨
单元测试 一、任务要求 题目1:根据下列流程图编写程序实现相应分析处理并显示结果。返回文字“xa*a*b的值:”和x的值;返回文字“xa-b的值:”和x的值;返回文字“xab的值:”和x的值。其中变量a、b均须为整型…...

C++核心编程——文件操作
本专栏记录C学习过程包括C基础以及数据结构和算法,其中第一部分计划时间一个月,主要跟着黑马视频教程,学习路线如下,不定时更新,欢迎关注。 当前章节处于: ---------第1阶段-C基础入门 ---------第2阶段实战…...

【REST2SQL】05 GO 操作 达梦 数据库
【REST2SQL】01RDB关系型数据库REST初设计 【REST2SQL】02 GO连接Oracle数据库 【REST2SQL】03 GO读取JSON文件 【REST2SQL】04 REST2SQL第一版Oracle版实现 信创要求用国产数据库,刚好有项目用的达梦,研究一下go如何操作达梦数据库 1 准备工作 1.1 安…...

GitLab 502 Whoops, GitLab is taking too much time to respond. 解决
1、先通过gitlab-ctl restart进行重启,2分钟后看是否可以正常访问,为什么要2分钟,因为gitlab启动会有很多配套的服务启动,包括postgresql等 2、如果上面不行,再看gitlab日志,通过gitlab-ctl tail命令查看&…...

vi ~/.bashrc 后如何编辑并退出
在使用 vi 编辑器打开 ~/.bashrc 文件后,可以按照以下步骤编辑并保存退出: vi ~/.bashrc 按 i 进入插入模式: 在 vi 编辑器中,按 i 键将进入插入模式。在插入模式中,您可以编辑文本。 编辑文件: 在插入模…...

KVM Vcpu概述
KVM Vcpu概述 Intel VTSMP系统CPU过载使用CPU模型CPU绑定和亲和性CPU优化 Intel VT Intel的硬件虚拟化技术大致分为3类: 1、VT-x技术:是指Intel处理器中的一些虚拟化技术支持,包括CPU中最基础的VMX技术,也包括内存虚拟化的硬件支…...

linux服务器ftp部署
1、ftp服务安装 # 检查是否安装 1、查询安装列表 sudo systemctl list-unit-files --typeservice | grep ftp 2、查询ftp服务状态 sudo service vsftpd status 或者 sudo systemctl status vsftpd # yum安装,一般yum仓库都有ftp安装包 sudo yum install vsftpd # 启…...

NSIS 安装windows 安装包(包括QT和MFC)
NSIS(Nullsoft Scriptable Install System)是一个开源的 Windows 系统下安装程序制作程序。它提供了安装、卸载、系统设置、文件解压缩等功能。 基本概念 区段 是对应某种安装/卸载选项的处理逻辑,该段代码仅当用户选择相应的选项才被执行…...

K8S----PVPVCSC
一、简介 1、PV(persistent volume)–持久卷 PV是集群中的一块存储,可以由管理员事先静态(static)制备, 也可以使用存储类(Storage Class)来动态(dynamic)制备。 持久卷是集群资源,就像节点也是集群资源一样。PV 持久卷和普通的 Volume 一样, 也是使用卷插件(volume p…...

RSIC-V“一芯”学习笔记(一)——概述
考研的文章和资料之后想写的时候再写怕趴 文章目录 一、阶段设计二、环境、开发语言和工具三、最重要的两个观念四、处理器芯片设计五、处理器芯片设计包含很多软件问题六、处理器芯片的评价指标七、复杂系统的构建和维护八、专业世界观九,提问的艺术(提问模板)十、…...

MATLAB读取图片并转换为二进制数据格式
文章目录 前言一、MATLAB 文件读取方法1、文本文件读取2、二进制文件读取3、 图像文件读取4、其他文件读取 二、常用的图像处理标准图片链接三、MATLAB读取图片并转换为二进制数据格式1、matlab 源码2、运行结果 前言 本文记录使用 MATLAB 读取图片并转换为二进制数据格式的方…...

时序数据库
SELECT *,max(lp_index) FROM lp.tdm_lp_original_data where ts > 2023-12-28 18:11:33.521 and ts < 2023-12-29 19:03:12.148 INTERVAL(2s) FILL(PREV) 在时间序列数据库TDengine中,FILL函数与GROUP BY子句结合使用,提供了对于在指定间隔内…...

【第一次使用finalshell连接虚拟机内的centos】小白处理方式
第一次使用finalshell连接centos7的时候,因为都是新环境什么都没有配置,所以就需要安装finalshell和对新的centos7 进行一些配置。 安装finalshel,默认不安装d盘,就需要对安装路径做一下调整,其余都是下一步默认安装的…...

Pinia 踩坑记录
1、子store中如何使用router 以user.ts 这个store为例 错误写法 // 说明:不能使用插件实例化router,否则获取不到router的函数 // 错误写法如下:import { useRouter } from "vue-router"actions:{login(){const router useRout…...

在ASP.NET MVC中使用JQuery提供的弹出窗口(模态窗口)
在ASP.NET MVC中使用JQuery提供的弹出窗口(模态窗口) 原理 使用<div>图层灵活显示在浏览器的任何位置。默认情况下指定<div>不可见 引用 样式表 在JQuery的官方网站可以下载对应的css样式表。打开官网的样例页。 找到样式表引用路径 …...

基本工具配置
github加速 github.ur1.fun java # ubuntu20.04 安装 openjdk-17-jdk sudo apt install openjdk-17-jdk java -version javac -version which java参考 openjdk gradle换源 修改gradle-wrapper.properties distributionBaseGRADLE_USER_HOME distributionPathwrapper/dis…...

计算机网络——应用层(3)
计算机网络——应用层(3) 小程一言专栏链接: [link](http://t.csdnimg.cn/ZUTXU) 点对点(P2P)P2P网络一般用途优点缺点总结 套接字编程基本步骤UDP套接字TCP套接字基本步骤 二者对比 小程一言 我的计算机网络专栏,是自…...

配置ssh实现互相免密登陆
一、实验要求 通过两台linux主机 配置ssh 实现互相免密登陆 的操作 二、实验思路 免密登录我们可以理解为使用公钥登录,这里分别使用两台主机(client)和(server)作为实验主机。 首先让client免密登录server&#x…...

【UEFI基础】EDK网络框架(ARP)
ARP ARP协议说明 从这里开始涉及到的网络协议都是比较通用的了,在一般的TCP/IP四层模型中都能够看到这些内容,不过这里主要介绍的还是其在BIOS下的实现,但是在此之前还是需要先说明ARP的作用。 ARP的全称是Address Resolution Protocol&am…...

Linux进阶课:目录(文件夹)与文件操作
1、ls与cat的区别是是什么? 答:ls命令的含义是list,显示当前目录中内容。不加参数时它显示当前目录中除隐藏文件外的所有文件及目录的名字。 cat命令是linux下的一个文本输出命令,通常是用于查看某个文件的内容的。 2、[abc]这个…...

Flink自定义Source模拟数据流
maven依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.…...

[易语言]使用易语言部署工业级人脸检测模型
【框架地址】 https://github.com/ShiqiYu/libfacedetection 【算法介绍】 Libfacedetection是一个开源的计算机视觉库,主要用于实时的人脸检测。它利用深度学习技术,特别是卷积神经网络(CNN),实现了高精度的脸部定位…...

2024年海外推广怎么做?
要说如何做海外推广,绝大多数的外贸小伙伴都能说上一些,但是大部分人对于推广系统知识略知一二,没有构建一个系统化的知识框架。 海外推广的几大步骤 1.定策略 做海外推广前,我们需要制定一套营销策略,需要去定义一…...

Redis分布式锁--java实现
文章目录 Redis分布式锁方案:SETNX EXPIRE基本原理比较好的实现会产生四个问题 几种解决原子性的方案方案:SETNX value值是(系统时间过期时间)方案:使用Lua脚本(包含SETNX EXPIRE两条指令)方案:SET的扩展…...

好消息,Linux Kernel 6.7正式发布!
据有关资料显示,该版本是有史以来合并数最多的版本之一,包含 17k 个非合并 commit,实际合并的超过1K个。 那么该版本主要有哪边变化呢?下面我来一一列举一下: Bcachefs文件系统已被合并到主线内核,这是一款…...

【k8s】Kubernetes 声明式 API、命令式
1. 资源管理方式: 1>. 命令式对象管理∶直接使用命令去操作kubernetes资源 kubectl run nginx-pod --imagenginx:1.17.1 --port802>. 命令式对象配置∶通过命令配置和配置文件去操作kubernetes资源 kubectl create/patch -f nginx-pod.yaml3>. 声明式对…...

解锁营销新高度:幽灵鲨CRM推广平台线索对接功能详解
数字营销时代,线索对接是推动业务增长的关键。你是否为线索分布在不同的平台而来回切换?你是否为无法及时联系客户而错失商机?幽灵鲨CRM系统作为一款领先的客户关系管理解决方案,不仅实现了对主流推广平台的全面对接,更…...

uniapp 创建组件
组件:用于将某个功能的 HTML、CSS、JS 封装到一个文件中,提高代码的复用性和可维护性。 创建组件 一、在根目录中创建 components 文件夹,右键点击新建组件。 二、输入组件名称、选择默认模板、点击创建组件。 三、在组件中正常编写内容即可…...

Linux--部署 Tomcat 及其负载均衡
1.案例前置知识点 1)Tomcat简介 名称由来:Tomcat最初是由 Sun的软件构架师詹姆斯邓肯戴维森开发的。后来他帮助将其变 为开源项目,并由Sun贡献给Apache软件基金会。由于大部分开源项目OReilly都会出一本相关的 书,并且将其封面设…...