☰
XCAP协议详解与OpenXCAP部署运维实战
2026/10/2 2:55:28 网站建设 项目流程

最近帮朋友排查一个语音核心网的小故障,现象很典型:所有人注册都正常,呼叫也能通,但软终端上的状态列表全部灰掉,联系人不显示在线。SIP抓包看了一圈,SUBSCRIBE、NOTIFY都有,SBC和AS日志里也找不到有效报错,最后问题落在一个平时根本没人关注的组件上——Xcap服务。磁盘满,进程还在,但所有XCAP文档读出来都是空。这台服务器默默运行了两年多,没人给它做过磁盘告警。这次之后我专门把Xcap的部署和使用重新梳理了一遍,整理成这篇东西,希望对做IMS、RCS、VoIP或者统一通信运维的朋友有帮助。

这里先说明一下,标题里写的Xcap,指的就是XML Configuration Access Protocol,行业里习惯把实现该协议的服务端也直接叫做Xcap。它不负责承载媒体面,也不参与SIP信令转发,但Presence、RCS、策略管理和联系人同步全都依赖它。你如果搭过IMS实验环境,或维护过FreeSWITCH、Kamailio附近的Presence业务,后面这些内容可以直接照着试。

1. 先搞清楚Xcap到底管什么:一套藏在SIP背后的“配置数据服务”

1.1 XCAP不是什么神秘网关,而是HTTP上的XML配置接口

XCAP的全称是XML Configuration Access Protocol,标准定义在RFC 5875里。你可以把它理解成:用HTTP方法(PUT、GET、DELETE)去读写XML格式的用户配置数据。为什么需要它?因为SIP终端和业务服务器之间,除了要传呼叫信令、Presence事件,还需要同步联系人列表、授权策略这类“配置”。

举一个白话场景。办公软终端上的联系人分组、某人能看到谁在线、谁能看我的状态,这些信息不能放在终端本地,因为终端一换就丢了,也不能放在Presence Server内部,因为别的网元也想知道。XCAP就是把这些数据集中存起来,并提供一个统一接口。SIP终端可以写自己的配置,Presence Server、RLS、SCIM这些服务可以按需读取。换句话说,XCAP解决的是SIP生态里“用户业务配置怎么写、怎么同步”的问题。

用大白话打个比方:XCAP像是公司走廊里一块公共白板。HR(终端用户)负责往白板上贴内容,行政部(Presence Server)、门卫(SCIM)、项目经理(RLS)都要看这块白板来决定怎么安排工作。白板本身不负责开会、不负责发布通知,但如果白板没了,大家就都不知道今天谁值班。

1.2 运维中真正会碰到XCAP的五个场景

XCAP在日常运维里很少被单独提起,但下面几个问题,追根溯源基本都会指向它:

  • 终端联系人列表无法同步:软终端配置了“从服务器获取联系人”,但分组一直是空的。
  • Presence状态不更新:某个人明明在线,其他人订阅后看到的却是“离线”或“未知”。
  • 授权策略不生效:用户设置了“只允许特定分组看我的状态”,但实际所有人还是能看到。
  • RLS服务报错:Resource List Server需要从XCAP读取“某用户订阅了哪些列表”,读不到就导致批量Presence订阅失败。
  • 呼叫策略下发异常:部分网元通过XCAP动态获取用户的业务属性,比如呼叫转移设置,读不到就按默认策略处理,用户会觉得“功能坏了”。

这几个场景都有个共同特点:SIP信令本身是通的,REGISTER、SUBSCRIBE都能拿到200,但业务结果不对。这种“信令通、业务不通”的问题,排起来最费劲,而XCAP往往是最后一个被想到的。

1.3 先建立AUID、XUI和路径的心智模型

XCAP排查绕不开三个概念:AUID、XUI、文档路径。

  • AUID(Application Unique ID)表示一类XML文档,比如resource-lists是联系人资源列表,pres-rules是Presence授权规则,rls-services是RLS服务配置。
  • XUI(XCAP User Identifier)表示用户,通常就是sip:alice@example.com这样的URI,也有可能是tel:+8613800138000这种号码格式。
  • 文档路径确定了具体操作哪一份XML文件,一般路径形式是:/xcap-root/{auid}/users/{xui}/{filename}

排障时如果发现404,先不要怀疑网络,先对着路径看:AUID是否写错、XUI里的域名是否小写、文件名是否写成了index.xml而不是index。这类低级错位占了实际排障中很大比例。

2. 选型不纠结:为什么我选了OpenXCAP这套开源实现

2.1 市面上能用的XCAP服务端其实不多

XCAP不像Web服务器那样遍地开花,做开源的就那么几个。我简单列一下我实际接触过的方案:

方案类型适用场景备注
OpenXCAPJava/Tomcat,开源实验环境、中小规模、学习部署简单,功能满足标准场景
Kamailio xcap_clientC模块,非完整服务器配合外部XCAP服务读取列表相当于客户端库,不算服务端
FreeSWITCH mod_xml_curl集成能力动态读取配置不能独立承担XCAP存储
商业SCIM/AS内置设备内置运营商级方案通常跟着IMS全套走,单独拆不出来

如果你不需要运营商级别的并发和容灾,我强烈建议用OpenXCAP。它虽然老,但代码量小,逻辑简单,出错时看日志非常直观。反观商业设备,XCAP功能被封装在SCIM里面,出了问题你连它的数据库长什么样都看不到,排障基本靠提单。

2.2 OpenXCAP的组成:Tomcat加MySQL,再加一个可选LDAP

OpenXCAP是Java项目,发布时间比较早,依赖结构也很传统:一个Servlet容器负责接收HTTP请求,一个数据库负责存XML文档,一套认证模块负责校验用户身份。我实际部署中的推荐组合是:

  • JDK 8或11
  • Tomcat 8.5以上(9也可以)
  • MySQL 5.7或8.0(MariaDB我也试过,基本兼容)
  • OpenLDAP(可选,如果没有就用数据库里的用户表做认证)

数据流是这样的:客户端(软终端、AS、SBC)通过HTTP PUT/GET访问Tomcat上的XCAP应用,应用解析请求后把XML文档写入MySQL,读取时再从MySQL查出来。身份校验在数据库或LDAP里完成。这个架构非常符合“配置数据服务”的定位,不涉及媒体流,也不会成为SIP链路的一部分。

2.3 部署前先画一个拓扑,别把服务的边界搞混

我见过不少人把XCAP服务部署在信令服务器上,和Kamailio塞在一起,最终出问题谁也说不清。我的建议是单独一台虚拟机或者容器,理由有三个:

  • XCAP的HTTP流量虽然不大,但日志量和数据库操作会对同机上的SIP转发造成轻微干扰。
  • XCAP服务重启时不能带着SIP核心一起重启,分开部署能降低故障半径。
  • 排障时需要独立抓包,如果混在一台机器上,抓包结果会和SIP流量混在一起,看半天看不明白。

拓扑上,我建议XCAP服务器和MySQL分开,至少做远程数据库访问;认证如果接LDAP,LDAP可以放在企业统一认证区。对外只开放一个HTTP/HTTPS端口,比如8080或8443,数据库端口不要对业务网暴露。

3. 一步一步搭出第一个Xcap服务:从零到HTTP 200

3.1 安装基础依赖:JDK、Tomcat、MySQL

下面以Ubuntu 22.04为例。命令很常规,但几个版本坑我提前说一下。

sudo apt update sudo apt install -y openjdk-11-jdk tomcat9 mysql-server sudo systemctl enable --now tomcat9 mysql

安装完先确认Java版本和Tomcat版本:

java -version sudo /usr/share/tomcat9/bin/version.sh

这里有一个常见坑:Tomcat9默认用Java 11启动,如果你环境里装了多个JDK版本,Tomcat可能因为找不到JAVA_HOME起不来。建议在/etc/default/tomcat9里显式指定:

JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64

MySQL初始化完成后,创建XCAP专用库和账号:

sudo mysql
CREATE DATABASE xcap DEFAULT CHARACTER SET utf8; CREATE USER 'xcap'@'%' IDENTIFIED BY 'C0mplexPass'; GRANT ALL PRIVILEGES ON xcap.* TO 'xcap'@'%'; FLUSH PRIVILEGES;

提示:XCAP里存的都是XML文本,字符集必须用utf8或utf8mb4。用过latin1的同事应该都遇到过生僻字联系人存不进去的情况。

3.2 部署WAR包与初始化表结构

OpenXCAP发布的是一个WAR包,可以直接丢到Tomcat的webapps目录下。我把xcap.war放到/var/lib/tomcat9/webapps/,Tomcat会自动解压成/var/lib/tomcat9/webapps/xcap/。

启动前需要初始化数据库表结构。项目自带的xcap.sql文件通常位于解压目录下的WEB-INF/classes或文档目录里,执行导入:

mysql -uxcap -p xcap < /var/lib/tomcat9/webapps/xcap/WEB-INF/classes/xcap.sql

导入后可以快速验证一下表是否建好:

mysql -uxcap -p xcap -e "show tables;"

正常会看到类似users、documents、resource_lists等表。如果一张表都没有,大概率是SQL文件路径找错了,或者MySQL当前用户名权限不够。

3.3 修改配置文件:四个关键项决定你能不能用

OpenXCAP的配置主要集中在WEB-INF/classes下的几个properties文件里。我总结四个必改项:

  • 数据库连接串:把localhost改成实际MySQL地址,注意加useSSL=false,否则MySQL 8会报证书校验错误。
  • 数据库账号密码:和上面创建的账号保持一致。
  • XCAP根目录标识:通常是/xcap/root,要和客户端URL前缀一致。
  • 认证方式:我建议先配成database模式,不用一上来就接LDAP,等整条链路通了再切。

示例片段(不同小版本字段命名会有差异,关键是找到相应关键字):

xcap.db.url=jdbc:mysql://127.0.0.1:3306/xcap?useSSL=false&characterEncoding=utf8 xcap.db.user=xcap xcap.db.password=C0mplexPass xcap.root=/xcap/root xcap.auth.backend=database

改完配置记得重启Tomcat:

sudo systemctl restart tomcat9

3.4 启动后的健康检查:别看到8080端口就以为成功

启动后不要急着连业务,先做三个验证:

# 1. 确认Tomcat进程活着 systemctl status tomcat9 # 2. 确认应用端口监听 ss -tlnp | grep 8080 # 3. 访问XCAP根路径 curl -i http://127.0.0.1:8080/xcap/root

第三条命令非常关键。如果返回HTTP 200,说明应用已经挂上;如果出现404,多半是WAR包没解压成功,看/var/lib/tomcat9/logs/catalina.out有没有异常;如果是500,一般是数据库连接失败,优先检查配置里的账号密码和MySQL的网络权限。

我第一次部署时卡在500上很久,最后发现是MySQL的bind-address默认绑定127.0.0.1,远程连不上。改成0.0.0.0,并确认防火墙放行3306后才正常。

4. 用curl完成“增删改查”:XCAP用户文档的实际操作

4.1 第一个PUT:创建用户Presence规则

装好服务后,最直接的验证就是往XCAP里写一份用户文档。以下用curl做一个标准操作,把resource-lists文档写到用户alice名下。

curl -X PUT \ -u alice:password \ -H "Content-Type: application/xcap-el+xml" \ --data '<?xml version="1.0" encoding="UTF-8"?> <resource-lists xmlns="urn:ietf:params:xml:ns:resource-lists"> <list name="team"> <entry uri="sip:bob@example.com"/> <entry uri="sip:carol@example.com"/> </list> </resource-lists>' \ http://127.0.0.1:8080/xcap/root/resource-lists/users/sip:alice@example.com/index

这里有几个细节值得说明:

  • 请求头Content-Type必须匹配AUID对应的MIME类型,resource-lists对应的是application/xcap-el+xml。类型给错了,服务端会返回415。
  • -u alice:password是HTTP Basic认证。OpenXCAP默认接受Basic和Digest两种方式,但有些终端只支持Digest,联调时要先确认。
  • URL里的sip:alice@example.com必须URL编码吗?不必须,Tomcat通常能自动处理@符号,但如果你用的是tel:号码,里面的+号建议编码成%2B,否则容易解析歧义。

4.2 GET查询、DELETE删除、版本号处理

写成功后,用GET验证:

curl -u alice:password \ http://127.0.0.1:8080/xcap/root/resource-lists/users/sip:alice@example.com/index

返回的应该就是刚才PUT进去的XML原文。服务端还会在响应头里带上Etag,这是文档版本号。XCAP协议支持用If-Match、If-None-Match做并发控制。

实际场景里两个人同时改同一份文档的情况很多,比如用户在用网页改联系人列表,同时终端也在同步配置。这时候一定要用Etag控制。流程是:先GET拿到Etag,再PUT时带上If-Match: "版本号",如果服务器上文档已经被别人改了,版本号对不上,PUT就会失败,客户端可以提示“配置冲突,请刷新后重试”。

删文档就是普通DELETE:

curl -X DELETE -u alice:password \ http://127.0.0.1:8080/xcap/root/resource-lists/users/sip:alice@example.com/index

4.3 文档命名空间和MIME type容易错在哪

XCAP排障绕不开“命名空间不匹配”这个坑。XML里的xmlns必须与AUID严格对应,比如resource-lists的命名空间是urn:ietf:params:xml:ns:resource-lists,pres-rules是urn:ietf:params:xml:ns:pres-rules。写错一个单词,服务端可能拒收,或者更坑的是存储成功,但读出来的客户端解析不了。

另外MIME类型也是重灾区。下面是一张常用的对应表,建议收藏:

AUIDMIME Type
resource-listsapplication/xcap-el+xml
rls-servicesapplication/rls-services+xml
pres-rulesapplication/auth-policy+xml
xcap-capsapplication/xcap-caps+xml

如果客户端总报“格式错误”,先抓包看它请求时的Content-Type和XML内容,往往一眼就能发现是类型写成了text/xml,或者命名空间少了个s。

5. 联调最容易翻车的几个点:从HTTP 409到404

5.1 认证模式:Digest、Basic、LDAP三者的取舍

XCAP客户端五花八门,有的软终端只发Digest,有的AS只支持Basic,还有的网关会在内部把登录账号映射成SIP URI后再请求XCAP。部署时我建议:

  • 先用Basic + 数据库用户跑通全链路。
  • 接口要面向公网或不可信网络时,再切到Digest或启用HTTPS。
  • 如果企业已有LDAP,可以把OpenXCAP的认证切到LDAP后端,但注意LDAP返回的用户名和XUI不一定一致,需要配映射关系。

实际维护中见过一个典型问题:在OpenXCAP里配了LDAP后,用户用终端同步联系人列表,第一次成功、第二次就一直401。后来发现是LDAP账号被锁策略限制,连续多次认证失败后会临时锁定。这个不是XCAP的问题,但排查时很容易往协议上靠,浪费大半天。

5.2 URI路径:全局目录和用户目录是两套写法

XCAP文档分为全局文档和用户文档。全局文档路径长这样:

/xcap/root/resource-lists/global/index

用户文档路径长这样:

/xcap/root/resource-lists/users/{xui}/index

运维配错最多的就是把global和users/{xui}混用。比如管理员想给所有用户下发一个公共联系人列表,写成了/users/global/index,服务端会认为用户名为global,导致配置只对一个人生效。

我也见过反向的问题:业务网元读取某个用户的列表时,用了全局路径,最后所有人看到的是同一份联系人列表,测试时发现A用户能看见B用户的私人号码,这个就是大事故了。所以路径规则一定写进运维手册里。

5.3 HTTP错误码对照:看到4xx先别慌

错误码含义优先排查方向
401认证失败账号密码、LDAP锁定、认证模式不匹配
403禁止访问用户对全局文档没有写权限,或XUI归属不对
404文档不存在AUID拼写、XUI大小写、路径global/users写错
409冲突XML节点已存在,或Etag版本不匹配
415不支持的媒体类型Content-Type和AUID不对应
500服务器内部错误数据库连接、SQL异常、磁盘满

遇到409的时候不要当成“服务器坏了”,先查文档是不是已经被写过。XCAP的语义是“如果目标节点不存在则创建,重复创建会冲突”,这是协议规定,不是缺陷。

5.4 案例复盘:联系人状态列表不显示的一次完整排查

顺着一个实际案例把这些点串起来。现场环境是:FreeSWITCH集群做语音业务,AS节点做Presence,终端联系人列表由XCAP下发。

用户反馈:手机端联系人分组能显示,但所有成员在线状态都是灰色的。

排查链路:

  1. 先抓SIP:终端发起SUBSCRIBE,AS返回200 OK,信令层面没有异常。
  2. 再看AS侧日志:AS向XCAP服务器请求用户列表时,URL是/xcap/root/resource-lists/users/sip:alice@example.com/index,返回404。
  3. 直接用curl复现这个请求,确实404。
  4. 检查XCAP数据库,发现这个目录下只有一个用户:sip:alice@example.com,问题出在客户端实际请求时把域名写成了大写SIP:Alice@Example.com,数据库里以小写存储,大小写匹配失败。
  5. 统一配置项,把XUI统一规范成小写后,再GET返回200,Presence恢复。

这个案例看起来低级,但在真实环境里非常多。XUI本质上就是字符串,按RFC应该不区分大小写,但很多实现直接拿字符串做数据库主键,导致大小写被区别对待。运维层面能做的最有效动作,就是在终端配置文件里统一参数格式,并定期巡检XCAP数据库里的用户数据。

6. 上线之后的运维“小账本”:备份、监控、容灾经验

6.1 除了数据库备份,配置文件也要留底

XCAP的数据核心在MySQL里的documents表,这是绝对要备份的。我习惯每天凌晨做一次全量mysqldump,保留最近7天,每周再导出一份离线归档。

mysqldump -uxcap -p xcap > /backup/xcap_$(date +%F).sql

但大部分人只备份了数据库,没有备份OpenXCAP的配置文件。部署时用到的xcap.properties、ldap.properties、WAR包版本号建议一起纳入配置管理系统。没有这些文件,即使数据库完整,换一台机器也起不来服务。

6.2 监控指标:HTTP状态码比TCP连接数有用得多

XCAP是HTTP服务,监控指标应该围绕HTTP来定。我在生产环境里主要盯四个:

  • 4xx比例:突然走高,大概率是认证配置或路径写错。
  • 5xx比例:突然走高,多半是数据库连接池耗尽或磁盘问题。
  • P95响应时延:正常应该在几十毫秒以内,如果超过500毫秒,先查MySQL慢查询。
  • 数据库连接数:OpenXCAP是个老项目,连接池配置通常不大,连接数满了服务直接不可用。

另外强烈建议给磁盘空间加一个更激进的告警阈值,比如使用率80%就告警,不要等到95%。上面提到的磁盘满导致Presence全灰的故障,就是被默认的95%告警拖累的,等知会到人已经晚了。

6.3 高可用和容灾思路:无状态应用加有状态数据库

OpenXCAP本身几乎是无状态的应用,部署两个节点放在负载均衡后面完全可行。请求落到哪个节点都无所谓,真正的状态都在MySQL里。所以扩展方案很清晰:

  • 两个XCAP应用节点,外置LB做流量分发。
  • MySQL做主从复制,主库故障时手动把VIP切到从库。
  • 全局配置不能分片,所有用户目录保持单副本逻辑。

如果预算允许,把XCAP的数据库放到已有的数据库集群里,省掉单独维护一套MySQL的工作。

6.4 一条私藏经验:每周做一次“真实用户演练”

最后分享一个我坚持了很久的土办法:每周从监控系统里抽一个测试用户,用脚本自动完成“PUT一份联系人列表、GET再校验、DELETE清理”三个动作。整个流程30秒,但能同时验证数据库读写、认证、路径配置、磁盘、网络五个维度。

这套脚本看起来很简单,却救过我两次。一次是数据库只读权限被误改,服务端一直返回200但根本没写入;另一次是负载均衡策略把PUT请求分发到了只读节点,测试一跑就暴露了。对比下来,比盯着Dashboard的可用率指标可靠得多。

Xcap这种服务,平时在架构图里经常被画在角落里,很容易被忽略,但它的状态直接决定Presence、联系人、策略这些用户能感知的功能好不好用。希望这篇梳理能帮你省掉一些排查时间。真正遇到问题的时候,记得先看HTTP状态码,再查数据库,最后才怀疑协议本身,顺序对了,排障速度能快很多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询