openfire 的 component

本文探讨了将消息系统与OpenFire集成的三种方法,并详细分析了各自的优缺点。最终选择了第三种方案,即通过外部Component的方式连接并实现多机负载均衡,解决了大规模部署下消息传递的问题。

    

转自:http://blog.chinaunix.net/space.php?uid=540802&do=blog&id=138854

     我们的消息交换系统要有一个向 OPENFIRE 发送数据的接口,做为我们系统消息传入软交换系统的入口。看了不少源码,总结出有三个解决方案:

1、增加一个 module,启动一个 WEBSERVICE 接口,然后向 internal component 里增加一个子域名,实现一个component 接口的消息处理类,用于答复自有消息。当自有消息发过来时,把发送人设置为此子域名,然后把消息交给 RoutingTable 去处理;消息回复时就可以直接发回到 component 里了。

2、自己在 JETTY 中启动一个 WEBSERVICE 接口,接收我们系统,在 WEB 容器中调用 RoutingTable 发送数据。这种方式当回复消息时只能在 RoutingTable 中硬编码,把特定消息交给一个特殊程序去处理。

3、我们系统以外部 component 方式连接到 component 上,在 RoutingTable 中注册一个子域,以 component 协议给openfire 系统发消息。消息回复是 RoutingTable 会自动发给这个 component



以上三种方中,第2种对系统改造大,对原系统的侵入也大,不予采用。第一种方式和第二种差不多,都是以模块方式接入,但第一种需要另外开发 webservice 接口。第二种需要写一个 component。开发量差不多。

再经过我们查找资料发现,在 openfire 源码库有已经写好的外部 component 的示例程序,名字叫 tinder,在openfire SVN 中就可以下载到。

再根据我们的需求比较13方案。我们的系统有40多台机器做为消息来源,这些机器是对等的,也就是它们必须为同一子域。消息有两种类型,IQ  messageIQ 必须哪台机器发的请求,答复还要再回到这台机器上去。Message 的请求可以回复到任意一台机器。

于是查看两个方案是否能满足此需求,改造量有多大。读代码和测试中发现,方案1不能原生实现此功能,必须自己实现这种特殊的需求,比如给40多台消息来源机每台起一个名字,在消息回复时根据名字发到不同的机器;方案3本来以为连接必须注册为一个唯一域名,后来读代码发现,在 component 登录时就可以指定是否支持多连接,也就是多个component 共用一个域名,openfire 在有消息发给此子域时,会自动选择不同的 componet 发送。这样的话 IQ 的回复那不胡乱找个机器回复了!?

经过测试发现,OPENFIRE  IQ 回复没有乱回,而是会回到发送IQ的那台机器。很是奇怪。读代码发现,原来它在收到 IQ 消息时会把 IQ 的消息 ID 保存一个列表,当有 IQ 回复时,会根据 ID 查找是哪个连接发的请求,回复消息再发还给它。真不错。那我们的需求就全部解决了。

方案3成了我们的正式解决方案。

`Openfire` 是一个非常流行的开源 **实时通信(IM)服务器**,它基于 **XMPP 协议**(原名 Jabber),非常适合用于构建企业级即时通讯系统、在线客服、群聊、单聊等应用。 你提到的这个“在线客服”页面正是使用了 XMPP 协议(通过 `strophe.js` 连接 BOSH 接口),而 **Openfire 完全支持这种接入方式**。下面我们详细分析如何用 Openfire 作为后端来运行和接入你的这套客服系统。 --- ## ✅ 一、Openfire 简介 | 特性 | 说明 | |------|------| | 协议支持 | 原生支持 XMPP 协议 | | 管理界面 | 提供 Web 管理后台(默认端口 `9090`) | | 数据库 | 支持嵌入式数据库(HSQLDB)、MySQL、PostgreSQL | | 扩展性 | 插件丰富(如:消息归档、REST API、文件传输等) | | 部署 | Java 编写,跨平台,支持 Windows/Linux/macOS | | 安全 | 支持 TLS 加密、SASL 认证、用户权限管理 | > ⚙️ 官网地址:[https://www.igniterealtime.org/projects/openfire/](https://www.igniterealtime.org/projects/openfire/) --- ## 🛠️ 二、部署 Openfire 服务(以 Linux 为例) ### 步骤 1:安装 Java 环境 ```bash sudo apt update sudo apt install openjdk-8-jre -y ``` ### 步骤 2:下载并解压 Openfire ```bash wget https://www.igniterealtime.org/downloadServlet?filename=openfire/openfire_4_7_0.tar.gz -O openfire.tar.gz tar -xzf openfire.tar.gz -C /opt/ ``` ### 步骤 3:启动服务 ```bash /opt/openfire/bin/openfire start ``` 访问管理后台: 👉 http://your-server-ip:9090 按照向导完成设置(数据库、管理员账号等) --- ## 🔧 三、配置 Openfire 支持 Web 客户端连接(BOSH/WebSocket) 你的前端使用的是 `strophe.js`,它是通过 **BOSH** 或 **WebSocket** 与 XMPP 服务器通信的。 ### ✅ 开启 BOSH(默认已开启) 路径:Openfire 后台 → Server → Server Settings → HTTP Binding 确保启用: - [x] Enable HTTP Binding (BOSH) - 默认接口:`http://your-domain.com:7070/http-bind` > 你的 JS 中应设置: ```js var BOSH_SERVICE = 'http://your-domain.com:7070/http-bind'; ``` ### ✅ (可选)开启 WebSocket(推荐用于现代浏览器) 路径:Openfire 后台 → Server → Server Settings → HTTP Binding → WebSocket 启用: - [x] Enable WebSocket URL 示例:`ws://your-domain.com:7070/ws` > 注意:生产环境建议配合 Nginx + HTTPS/WSS 使用。 --- ## 👤 四、创建用户:客服 & 用户账号 ### 1. 创建客服账号(在 Openfire 后台) 登录 Openfire 管理后台 → Users/Groups → Create New User 例如: - Username: `kefu1` - Password: `123456` - Full Name: `客服小张` - Domain: `yourdomain.com`(即 JID 为 `kefu1@yourdomain.com`) ### 2. 用户账号动态生成(由 PHP 页面传入) 当访客点击“联系客服”时,PHP 应为其创建临时用户名或绑定当前用户 ID。 示例: ```php $from = "user_" . session_id() . "@yourdomain.com"; $password = generate_token(); // 后端验证后允许登录 ``` > 💡 建议使用 Openfire 的 **External Component** 或 **REST API 插件** 动态注册/认证用户。 --- ## 🔐 五、安全加固建议 ### 方案 1:使用 REST API 插件进行用户认证控制 安装插件:**[Rest API Plugin](https://github.com/igniterealtime/openfire-restAPI)** 功能: - 动态创建用户 - 修改密码 - 查询状态 - Token 化认证(避免前端暴露真实密码) #### 示例:通过 API 创建临时用户 ```bash curl -X POST "http://localhost:9090/plugins/restapi/v1/users" \ -H "accept: application/json" \ -H "Content-Type: application/json" \ -u admin:admin_password \ -d '{ "username": "user_123", "password": "temp_pass_123", "name": "Guest User", "email": "guest@example.com" }' ``` 然后将 `user_123@yourdomain.com` 和 `temp_pass_123` 返回给前端用于登录。 --- ### 方案 2:自定义身份验证模块(高级) 可以开发 Openfire 的 Authentication Provider,对接你的主站数据库,实现免密登录或 token 登录。 --- ## 📡 六、前端连接 Openfire(Strophe.js 示例) ```html <script src="js/jquery-1.6.2.min.js"></script> <script src="js/strophe.js"></script> <script> var BOSH_SERVICE = 'http://your-domain.com:7070/http-bind'; var connection = null; function log(msg) { $('#log').append('<p>' + msg + '</p>'); } function onConnect(status) { if (status === Strophe.Status.CONNECTING) { log('正在连接...'); } else if (status === Strophe.Status.CONNFAIL) { log('连接失败'); } else if (status === Strophe.Status.DISCONNECTED) { log('已断开'); } else if (status === Strophe.Status.CONNECTED) { log('连接成功!开始接收消息...'); // 注册消息处理器 connection.addHandler(onMessage, null, 'message', 'chat'); } } function onMessage(msg) { var from = msg.getAttribute('from'); var to = msg.getAttribute('to'); var elems = msg.getElementsByTagName('body'); if (elems.length > 0) { var body = elems[0]; var text = Strophe.getText(body); insertOtherMessage(text, from); $("#scroll_div").scrollTop($(".scroll_inner").height()); } return true; } function sendMessage(toJid, message) { var msg = $msg({ to: toJid, type: 'chat', from: $('#from').val() }).c('body').t(message).up() .c('active', {xmlns: 'http://jabber.org/protocol/chatstates'}); connection.send(msg.tree()); } $(document).ready(function () { var fromJid = $('#from').val(); var password = $('#password').val(); connection = new Strophe.Connection(BOSH_SERVICE); connection.connect(fromJid, password, onConnect); // 发送按钮事件 $('#btn_send').click(function () { var msg = $('#editor').val().trim(); if (!msg) return; sendMessage($('#to').val(), msg); insertUserMessage(msg); $('#editor').val(''); }); // 回车发送 $('#editor').keypress(function (e) { if (e.which === 13 && !e.shiftKey) { e.preventDefault(); $('#btn_send').click(); } }); }); </script> ``` --- ## 🔄 七、消息模板插入函数补充 ```javascript function insertUserMessage(content) { var template = $('#from_html').html(); var timeStr = new Date().toLocaleTimeString([], {hour:'2-digit', minute:'2-digit'}); var html = template .replace(/from_name/g, $('#username').val()) .replace(/send_time/, timeStr) .replace(/msg_content/, $('<div>').text(content).html()) // 转义 XSS .replace(/script_from_id/, 'msg_' + Date.now()); $(html).appendTo('.scroll_inner'); } function insertOtherMessage(content, fromJid) { var template = $('#to_html').html(); var name = fromJid.split('@')[0].replace('kefu', '客服'); var timeStr = new Date().toLocaleTimeString([], {hour:'2-digit', minute:'2-digit'}); var html = template .replace(/to_name/g, name) .replace(/send_time/, timeStr) .replace(/msg_content/, $('<div>').text(content).html()) .replace(/script_to_id/, 'msg_' + Date.now()); $(html).appendTo('.scroll_inner'); } ``` --- ## ✅ 八、生产环境优化建议 | 项目 | 建议 | |------|------| | 域名 | 绑定正式域名,如 `im.yourshop.com` | | HTTPS | 使用 Let's Encrypt 证书,Nginx 反向代理 | | WebSocket | 替代 BOSH,降低延迟 | | 消息存档 | 安装 `monitoring` 插件记录聊天历史 | | 高可用 | 集群部署多个 Openfire 实例 + ZooKeeper | | 监控 | 集成 Prometheus + Grafana 监控连接数 | --- ## 📦 九、常用插件推荐 | 插件 | 功能 | |------|------| | **REST API** | 外部系统调用用户管理 | | **Monitoring** | 存储消息历史、离线消息 | | **Fastpath** | 完整的 Web 客服系统(排队、转接、评价) | | **SIP Phone** | 视频语音通话 | | **Clustering** | 支持多节点集群 | > 插件下载地址:[https://www.igniterealtime.org/projects/openfire/plugins.jsp](https://www.igniterealtime.org/projects/openfire/plugins.jsp) --- ## ✅ 总结:Openfire 是否适合你的客服系统? ✅ **非常适合!** | 优势 | 说明 | |------|------| | 即开即用 | 不需要自己实现 XMPP 协议 | | 支持 Web 接入 | 完美兼容 strophe.js | | 易于管理 | 图形化后台,无需命令行 | | 社区活跃 | 文档齐全,问题容易解决 | | 可扩展性强 | 插件机制完善 | --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值