---
title: GeoServer集群(JMS)
date: 2023-03-28
author: ac
tags:
- GeoServer
categories:
- GIS
---
> JMS集群部署方案来源于社区
### 1.地理服务器的限制
集群部署需要考虑的几个问题:
1. 数据目录,`GeoServer` 实例的内部配置默认持久化的XML文件都在数据目录中,如果每个实例都有自己的数据目录该如何保持一致?
> 以某种方式共享相同的数据目录,如通过修改`web.xml`文件,配置相同的`GEOSERVER_DATA_DIR`变量。或通过消息组件同步更改。
>
> 在集群环境中,数据存储在数据目录之外的共享位置或使用其他方式同步
2. 日志记录,默认情况下,`GeoServer` 的日志位置是相对于数据目录的,但是当多个 `GeoServer` 共享同一数据目录时,无论其位置如何,指示它们记录到不同位置至关重要。
> 这可以通过 `GEOSERVER_LOG_LOCATION `配置调整来实现,
3. Java2D 光栅器瓶颈,常见的 Java 安装带有两种不同的光栅化器(将矢量转换为光栅图像的组件)
Oracle JDK 有一个快速的光栅化器,但是在启用抗锯齿的情况下,在整个过程中一次只能光栅化一个形状。在并发环境中在服务器端生成图像时,工作线程大部分时间都被阻塞,因此应用程序根本无法扩展。一旦多个客户端请求生成图像,响应时间就会增加。
> 安装JAI扩展
### 2.配置方案
#### 2.1 `JMS`消息模型
> 基于`JMS`(Java Message Service)的`GeoServer`集群部署是社区提供的一个方法,该方法利用了消息中间件(MOM),实现了一种强大的主/从(master/slave)模式,让集群中的所有节点在其配置方面保持同步。
`JMS`是Java平台上有关面向消息中间件的技术规范,它便于消息系统中的Java应用程序今夕消息交换,并且通过提供标准的生产、发送、接受消息的接口,简化企业应用的开发。
`JMS`本身值定义了一系列的接口规范,是一种厂商无关的API,用来访问消息收发系统。
消息中间件一般有两种传递模式:
(1)发布-订阅模式(Pub/Sub):发布/订阅模型(Topic主题模型)
(2)P2P点对点模式:点对点模型(Queue队列模型)
**点对点模型**
> 点对点模型(Pointer-to-Pointer):即生产者和消费者之间的消息往来。

每个消息都被发送到特定的消息队列,接受者从队列中获取消息。队列保留消息,直到他们被消费或超时。
点对点的特点:
1. 每个消息只有一个消费者(一对一),消息一旦被消费,消息就不再在消息队列中;
2. 发送者和接收者之间在时间上没有依赖性,也就是说当发送者发送了消息之后,不管接收者有没有正在运行,它不会影响到消息被发送到队列;
3. 接收者在成功接收消息之后需向队列答应成功。
**发布/订阅模型**
包含三个角色:主题(Topic)、发布者(Publisher)、订阅者(Subscriber),多个发布者将消息发送到Topic,系统将这些消息投递到订阅此topic的订阅者。

发送者发送到topic的消息,只有订阅了topic的订阅者才会收到消息。topic实现类发布和订阅,当你发布一个消息,所有订阅这个的topic的服务都能得到这个消息,所以从1到N个订阅者都能得到这个消息的拷贝。
特点:
1. 每个消息可以有多个消费者;
2. 发布者和订阅者之间有时间上的依赖(先订阅主题,再来发送消息);
3. 订阅者必须保持运行的状态,才能接受发布者发布的消息。
示例:

#### 2.2 单主多从方案

图1:单主 - 具有私有数据目录和外部 MOM 的多从集群
它由3个不同的参与者组成:
- `GeoServer Masters`:主服务器接受对内部配置的更改(通过用户界面或Rest接口),将其保存在自己的数据目录中,但也通过MOM将它们转发给副本;
- `GeoServer Slaves`:复制副本不应用于从REST或用户界面更改其配置,因为它们被配置为注入主服务器通过MOM分发的配置更改。每个副本都有自己的数据目录,它负责保持与主副本的数据目录保持一致。如果一个副本再次启动时出现故障,他可能会收到一堆JMS消息,以使其配置与主副本的配置一致。
- 消息中间件(MOM,这里使用`ActiveMQ`):MOM用于使主服务器Masters和副本Slaves 以持久的方式交换消息,有时我们会使用术语**Broker**作为*MOM 的同义词*。
#### 2.3 P2P和共享数据目录方案
> **一个节点可以同时是主节点和从节点,从而允许对等设置。**
一般来说,所有节点都可以同时是Master和Slave,但是,如上所述,最好将负载均衡器配置为使用故障转移进行配置更改(GUI或REST),以防频繁更改配置预计。在下图中,描述了具有 P2P 布局和共享数据目录的设置。

图2:P2P 和共享数据目录
### 3. 安装集群扩展
#### 3.1 软件准备
本次采用`war`包的形式,使用`Tomcat`进行部署,环境是windows(先练练手)。
> 插件下载:[Index of geoserver](https://build.geoserver.org/geoserver/)

下载两个包:
- `geoserver-2.22-SNAPSHOT-activeMQ-broker-plugin.zip`
- `geoserver-2.22-SNAPSHOT-jms-cluster-plugin.zip`
其中`activeMQ-broker-plugin` 是一个实际上独立的最小 `ActiveMQ MOM` web 应用程序,打包为 WAR 文件,准备好放入 web 容器(例如,Tomcat)中。
集群**插件**将所有功能添加到 `GeoServer` 以作为主服务器或从服务器工作。
另外准备好版本一致的`GeoServer`以及一个Tomcat:
- `geoserver-2.22.2-war.zip`
- `apache-tomcat-9.0.68`

将Tomcat复制4份,一份用来单独部署`ActiveMQ`,后3份用来部署`geoserver`,将`jms`插件的jar包解压到`jms-cluster-plugin`,创建共享目录`cluster_data_dir`;
#### 3.2 修改端口
修改tomcat的端口号:
> 注意:要也修改shutdown服务的端口,不然会端口冲突(8006-8096,8007-8097,8008-8098)
```xml
...
...
```
#### 3.3 部署MQ
基于`JMS`的`GeoServer`集群部署首先需要运行一个`ActiveMQ`实例,可以单独部署在一个Tomcat中。
将`activemqBroker-2.22-SNAPSHOT.war`放到Tomcat的`webapp`目录下并启动,修改解压后的`webapps\activemqBroker-2.22-SNAPSHOT\WEB-INF\classes\applicationContext.xml`文件,将uri地址改为本机的IP,:
```yaml
activemq.transportConnectors.server.uri=tcp://127.0.0.1:61666?maximumConnections=1000&wireFormat.maxFrameSize=104857600&jms.useAsyncSend=true&transport.daemon=true
```
然后重新启动:
```shell
PListStoreImpl - PListStore:[D:\tools\geoserver_cluster\apache-tomcat-9.0.68\bin\.\tmp] started
PListStoreImpl - PListStore:[D:\tools\geoserver_cluster\apache-tomcat-9.0.68\bin\.\tmp] started
BrokerService - Apache ActiveMQ 5.15.11 (broker-1, ID:LAPTOP-POKOTMS2-51732-1684309292191-0:1) is starting
BrokerService - Apache ActiveMQ 5.15.11 (broker-1, ID:LAPTOP-POKOTMS2-51732-1684309292191-0:1) is starting
TransportServerThreadSupport - Listening for connections at: tcp://127.0.0.1:61666?maximumConnections=1000&wireFormat.maxFrameSize=104857600&jms.useAsyncSend=true&transport.daemon=true
TransportServerThreadSupport - Listening for connections at: tcp://127.0.0.1:61666?maximumConnections=1000&wireFormat.maxFrameSize=104857600&jms.useAsyncSend=true&transport.daemon=true
TransportConnector - Connector openwire started
TransportConnector - Connector openwire started
NetworkConnector - Network Connector DiscoveryNetworkConnector:NC:BrokerService[broker-1] started
NetworkConnector - Network Connector DiscoveryNetworkConnector:NC:BrokerService[broker-1] started
BrokerService - Apache ActiveMQ 5.15.11 (broker-1, ID:LAPTOP-POKOTMS2-51732-1684309292191-0:1) started
BrokerService - Apache ActiveMQ 5.15.11 (broker-1, ID:LAPTOP-POKOTMS2-51732-1684309292191-0:1) started
BrokerService - For help or more information please see: http://activemq.apache.org
BrokerService - For help or more information please see: http://activemq.apache.org
ContextLoader - Root WebApplicationContext: initialization completed in 1371 ms
```
#### 3.4 部署jms插件
跟安装其它 `GeoServer` 扩展一样,您可以通过以下方式安装 Active Clustering Extension:
1. 将`geoserver.war`放到Geo8096、Geo8097、Geo8098的webapp中启动;
2. 将 `jms-cluster-plugin` JAR 放到Geoserver的WEB-INF\lib 目录中,如:\apache-tomcat-9.0.68-Geo8096\webapps\geoserver\WEB-INF\lib
3. 修改Tomcat的catalina.bat,添加环境变量设置:
- `GEOSERVER_DATA_DIR`:共享目录地址
- `CLUSTER_CONFIG_DIR`:集群配置目录
- `GEOSERVER_LOG_LOCATION`:日志记录文件
```shell
rem set TITLE=Tomcat.Cluster#1.Server#1 [%DATE% %TIME%]
rem ---------------------------------------------------------------------------
setlocal
set "CLUSTER_CONFIG_DIR=D:\tools\geoserver_cluster\cluster_data_dir\cluster\8096"
set "GEOSERVER_DATA_DIR=D:\tools\geoserver_cluster\cluster_data_dir"
set "GEOSERVER_LOG_LOCATION=D:\tools\geoserver_cluster\cluster_data_dir\logs\8096.log"
rem Suppress Terminate batch job on CTRL+C
if not ""%1"" == ""run"" goto mainEntry
...
```
4. 重新启动 `GeoServer`
> **必须为组成集群的每个地理服务器实例**执行这些步骤,而不管实例将扮演的角色(主或从)。每个实例的集群配置目录和日志文件不要一样。
#### 3.5 配置集群
登陆`GeoServer`,在首页找到`Cluster Setings`,修改配置如下:

将每个`GeoServer`都设置为既是主节点也是从节点,`Replica connection`一定要启动,用于同步配置。
### 4. 集群验证
在8096上发布shp文件,可以预览wms服务,在预览的地址栏上直接修改端口为8097,也可以访问到服务,说明节点之间的服务有同步。
### 5.负载均衡
使用nginx进行配置以支持负载均衡
- 对upstream进行配置实现负载均衡
```shell
upstream local_tomcat {
ip_hash; //支持session,使其能够访问同一个地址
server 127.0.0.1:8096 max_fails=1 fail_timeout=1000; //geoserver地址
server 127.0.0.1:8097 max_fails=1 fail_timeout=1000; //geoserver地址
server 127.0.0.1:8098 max_fails=1 fail_timeout=1000; //geoserver地址
}
```
- 对location进行配置,跳转到正确的网址
```shell
server {
listen 8090;
location /geoserver/ {
proxy_pass http://local_tomcat/geoserver/
}
}
```
### 参考文章
[1] geoserver集群-jms https://zhuanlan.zhihu.com/p/103706150
[2] 基于JMS的集群https://www.osgeo.cn/geoserver-user-manual/community/jms-cluster/index.html