jabber服务器架构及配置

来源:互联网 发布:网络与信息期刊 编辑:程序博客网 时间:2024/05/17 02:32

备注:本文翻译自《Programming Jabber》一书的 Chapter 4. Server Architecture and Configuration 。

--------------------------------------------------------------------------------

An Overview of the Server Architecture/服务器架构总览


In order to understand the configuration directives and how they work, it is necessary to take a step back and look what the Jabber Server really is.

为了理解配置指令和他们是怎么运作的,有必要回顾一下看jabber服务器到底是什么。

jabberd and Components

The Jabber Server is a daemon jabberd that manages the flow of data between various components, components which collectively make up the Jabber service. There are different components, each of which perform different kinds of tasks, and there is a basic set of components that are required for a simple Jabber Server such as the one we configured and installed in the previous chapter.

jabber服务器是一个后台程序jabberd,管理在不同的组件之间数据流程,这些组件共同组成了jabber服务。不同的组件执行不同作业。并且有组件的基础组合来满足简单的jabber服务,比如我们在前面章节中配置安装的那个。

The following list shows what the basic Jabber components are and what services they provide. It's worth considering the original and most well-known application of Jabber—instant messaging—and a Jabber design feature (distributed server architecture) to put this list into context and make better sense of it.

下面的列表展示了什么是jabber的基础组件,他们提供什么服务。值得考虑的是最初的并且被广为人知的jabber应用-即时信息-和jabber的设计特性(分布式的服务架构),搞清楚它。

Session management
会话管理

We need to be able to manage users' sessions while they're connected to the server. The component that does this is called the Jabber Session Manager (JSM), and provides IM features such as message store and forward and roster management as well as managing sessions.

当用户连接到服务器时,我们需要能够管理他们的会话。实现这个的组件被称为jabber会话管理(jsm),在管理会话的同时还提供im特性比如信息保存、前传和花名册管理。

Client (to server) connections
客户端连接
This is the component that manages the connections between clients and the server. It is known internally as 'c2s'.

这是用来管理服务器和客户端连接的组件。在内部被称为'c2s'。

Server (to server) connections
服务器连接
If there's a requirement to send a message from a user on one Jabber server to a user on another Jabber server, we need a way for the servers to connect to each other. This component establishes and manages server-to-server connections, and is known internally as 's2s'.
如果存在发送来自jabber服务器上的用户信息到另一个jabber服务器上的用户的需求,我们需要将服务器彼此连接的方法。这个组件建立并且管理server-to-server的连接,在内部被称为's2s'。


Logging
日志
As in any server system, the ability to log events (error messages, notices, alerts and so on) is essential. The logging component allows us to effect such logging.

和任何服务器系统一样,记录事件(错误信息,提示,警告等等)的能力是基本的。日志组件容许我们实现这样的日志。

Data storage
数据存储

There will be some server-side storage requirements, for example, to hold authentication information and data such as last connect time; not to mention storage of rosters, personal details, and private data. The Data storage component does this for us. It is known internally as the 'xdb' component. xdb stands for XML Data Base.

存在一些服务器端的存储需求,例如,保持认证信息和数据如最后一次连接时间;不仅是花名册的保存,个人详细资料和私有数据。数据存储组件为我们实现这些。在内部被称为xdb组件。xdb代表XML Data Base。

Hostname resolution
Last but not least, we may need some way to resolve names of hosts that the Jabber server doesn't recognize as "local", as in the Server (to Server) Connection context. This component is known internally as 'dnsrv'.
最后但不是最不重要,我们可能需要一些方法来解决jabber服务器不能识别的主机名的问题,这个组件在内部被称为'dnsrv'。


Component types
组件类型

Figure 4-1 shows the relationship between jabberd and the components. These components are the engines that serve and process XML messages, providing their services, and jabberd is the backbone along which messages are routed.

图4-1展示了jabberd和组件之间的关系。这些组件是提供被处理xml信息的设备,提供他们的服务,而jabberd是信息路由的中枢。

Figure 4-1. jabberd and the components

                             +---+
                             |   |
            +-------------+  | <----- jabberd backbone
            | Client (to  |  |   |                       
            | server)     |==|   |                 
            | connections |  |   |  +-------------+
            +-------------+  |   |  | Session     |
                             |   |==| management  |
            +-------------+  |   |  |             |
            | Logging     |  |   |  +-------------+
            |             |==|   |
            |             |  |   |  +-------------+
            +-------------+  |   |  | Server (to  |
                             |   |==| server)     |
            +-------------+  |   |  | connections |
            | Data        |  |   |  +-------------+
            | storage     |==|   |
            |             |  |   |  +-------------+
            +-------------+  |   |  | Hostname    |
                             |   |==| resolution  |
            +.............+  |   |  |             |
            :             :  |   |  +-------------+
            : ...         :==|   |
            :             :  :   :
            +.............+  :   :
                             :   :
                             +---+
As seen in Figure 4-1, the jabberd backbone acts as the central artery or "hub", managing the "peripheral" components that are attached to it. The management of these components encompasses controlling and overseeing how they connect and coordinating the flow of data between them. Certain types of components receive only certain types of data. There is a distinction made between three different types of component:

如图4-1中看到的,jabberd中枢担当中央动脉或“集线器”,管理附加的“外围”组件。这些组件的管理包括控制和检查组件的连接,调整组件件的数据流程。特定类型的组件仅接收特定类型的数据。三种不同的组件类型是有差别的

log

xdb

service

The different component types handle different types of data packets. Each packet is in the form of a distinct, fully-formed XML fragment and is identified by the outermost element name in the XML fragment. This element name is matched up to a particular component type.
不同类型的组件处理不同类型的数据包。每个包由不同的,完整构造的xml片段组成,通过在xml片段中最外层的元素名称来标志。这个元素名称匹配特殊的组件类型。

log components
log components handle <log/> packets; you can guess that these are the components that provide logging services.
日志组件处理<log/>包。你可以猜到是这些组件提供日志服务。

On receipt of a <log/> data packet a logging component will (hopefully) do something useful with it, like write it to a file or to STDERR.
当收到<log/>数据包时,日志组件将做一些有效的处理,比如写到文件或者STDERR

The <log/> packet shown in Example 4-1 is being used to record the successful connection and authentication of user dj, on yak, using the Jabber client JabberIM.
在例4-1中展示的<log/>包是用于记录jak服务器上使用jabber 客户端软件JabberIM的用户dj的成功连接和认证。

Example 4-1. A <log/> packet

<log type='record' from='dj@yak'>login ok 192.168.0.1 JabberIM</log>

xdb components
xdb组件
xdb components handle <xdb/> packets. The <xdb/> packets carry data and storage/retrieval requests to and from the xdb components which provide the Data Storage services.
xdb组件处理<xdb/>包。<xdb/>运送数据并且存储或取回到或从提供数据存储服务的xdb组件的请求。

On receipt of an <xdb/> data packet an xdb component will retrieve data from or write data to a storage system such as a collection of flat files or an RDBMS.
当接收到<xdb/>包,xdb组件将取出数据或写数据到存储系统比如文件集合或一个RDBMS。

The <xdb/> packet shown in Example 4-2 is carrying a request from the session manager to retrieve the preferences stored in a private namespace for the user dj (on Jabber server yak by the Jabber client JabberIM).
在例4-2中展示的<xdb/>携带这样一个请求:来自会话管理者,目的是获取存储在dj用户的私有命名空间的参数

Example 4-2. An <xdb/> data packet

<xdb type='get' to='dj@yak' from='sessions' ns='jabberim:prefs' id='5'/>

service components
服务组件

service components handle the three main building blocks on which the Jabber functionality is based (the <message/>, <presence/>, and <iq/> packets). You can find out more about these building blocks in Part II of this book.

服务组件处理这三个主要结构,jabber的功能是基于这三个(<message/>,<presence/>和<iq/>包)的。

In addition, the service component also handles the <route/> packets, which are used internally by jabberd to move packets around between components. For example, the Session Management component is the component that usually handles client authentication. It receives any incoming authorization requests received by and passed on from the Client (to Server) Connections component. However, it may be that the administrator has configured the Jabber server to use a different (third party) component, developed by another group or company, to handle the authorizations. In this case the request is routed from one component (Session Management) to another (the third-party authorization component).

另外,服务组件还处理<route/>包,jabber内部使用它来在组件之间转移包。例如,会话管理组件是常用来处理客户端认证的组件。它接受任何客户端组件接受并转发过来的引入的认证请求。而且,管理员有可能配置jabber服务器使用不同的其他任何组织或公司开发的(第三方)组件,来处理认证。在这种情况下,请求被从一个组件(会话管理)路由到其他(第三方认证组件)。

So unlike the log and xdb components, which handle data packets whose element names match the component type (<log/> and <xdb/>), the service component is an umbrella component designed to handle packets with different element names.

因此,和log和xdb组件不同,他们处理和他们组件名称(<log/>和<xdb/>)匹配的数据包,服务组件是一个umbrella(伞,庇护?)组件,设计用于处理不同元素名称的包。

Example 4-3 shows two typical service packets.

Example 4-3 展示两种典型的服务包

Example 4-3. Two service packets


<route to='dj@yak/81F2220' from='15@c2s/80EE868'>
  <presence>
    <status>Online</status>
  </presence>
</route>

<message id="jim_id_7" to="sabine@merlix" type="chat">
  <x xmlns="jabber:x:event">
    <composing/>
  </x>
  <thread>3A378DF2B70F6A53A9C317CF526C6B7A</thread>
  <body>Hi there</body>
</message>

The first is an internal <route/> packet, which is carrying a <presence/> packet from the Client (to Server) Connections component, identified by the 'c2s' part of the from attribute, to the Session Management component (where the session identifier 81F2220 [1] is significant in the to attribute.). [2]

第一个是一个内部<route/>包,带有一个来自从被from属性标志的客户连接组件,到会话管理(这里会话标记符81F2220对to属性来说非常重要)的<presence/>包。

The second is a <message/> packet, which contains the message itself ("Hi there") as well as other information (a message event and a conversation thread identifier; these are examined in detail in Part II of the book).

第二个是一个<message/>包,包含消息本身("Hi there"),也带有其他信息(一个消息事件和一个会话线程标志符)。

It isn't necessarily the case, however, that all xdb components will handle all <xdb/> packets, or all service components will handle all <presence/> packets. The configuration, described later in this chapter, determines how the components announce themselves and state their readiness to receive and handle packets.

这并不是说,所有xdb组件处理所有的<xdb/>包,或者所有服务组件处理所有的<presence/>包。配置决定了组件是怎样申明自身并规定组件自身为接收和处理包做的准备。

Delivery trees
The phrase "delivery tree" is often used in Jabber terminology to signify a component or components that handle certain types of packet. The path a packet makes as it descends the collection of decision branches that guide it to the component or components that will handle it. For example, an 'xdb type component' is sometimes referred to as an xdb Delivery Tree. Considering the division of components into different types that handle different packet types is perhaps easier to visualize as a tree, as shown in Figure 4-2.

术语"delivery tree"通常在jabber术语中用于表示处理确定类型包的组件或组件们。The path a packet makes as it descends the collection of decision branches that guide it to the component or components that will handle it。例如,xdb类型的组件用于表示xdb Delivery Tree。形象化成树可以更容易的将处理不同包类型的组件区分成不同的类型。

Figure 4-2. The Jabber Delivery Tree

                     |
   +-------+-----------------------------+
   |       |                             |                   component
  log     xdb                         service                  types
   |       |                             |
   |       |          +----------+----------+----------+
   |       |          |          |          |          |      packets
 <log/>  <xdb/>  <message/> <presence/>   <iq/>    <route/>   handled


The Jabber Delivery Tree shows which component types can handle what sorts of packets in the Jabber world.

Jabber Delivery Tree展示了在jabber世界中,不同类型的组件处理什么类型的包。

Component Connection Methods
组件连接方法

The notion of components providing distinct services and being coordinated by a central mechanism (jabberd) suggests a certain amount of independence and individuality—a plug-in architecture—and that is what Jabber is. The components described earlier, and others too, are "plugged in" to the Jabber backbone according to the requirements of the server.

组件提供不同的服务和组件被核心机构(jabberd)调整的概念提出一个特定数量的独立而个性化(插件)的体系,而jabber正是这样做的。前面描述的组件还有其他的组件一样,为了服务器的需要而被插入到jabber的backbone中枢。

The idea is that once you have the basic services like Session Management, Client (to Server) Connectivity and Data Storage, you plug in whatever you need to suit the server's requirements. For example if you need conferencing facilities, you can plug in the Conferencing component. If you need user directory facilities, you can plug in the Jabber User Directory (JUD) component. If you need a bridge to the Yahoo! Instant Messaging system, you can plug in the Yahoo! Transport component. [3] Indeed, you can write your own components to provide services that are not available off the shelf and plug those in too.

也就是说,一旦你有类似会话管理、客户连接和数据存储的基本服务,你可以插入到你需要满足服务器需要的地方。例如,如果你需要会议工具,你可以插入会议组件。如果你需要用户目录工具,你可以插入jabber的jdu组件。如果你需要桥接到yahoo!即时消息系统,你可以插入Yahoo!组件。实际上,你还可以写你自己的组件来提供架构没有实现的服务,然后插入他们。

So, how are components 'plugged in' to the Jabber server backbone? [4] Well, there are three methods:

然而,组件是怎么插入到jabber的服务中枢的呢?下面有三个方法:

Library load
库加载

TCP sockets
tcp套接字

STDIO
标准io

Let's examine each one in turn.

我们按顺序考察他们。

library load
The core components of a Jabber Server providing IM services are connected using the library load method. This simply means that the component sources are compiled into shared object (.so) libraries and loaded into the main Jabber process (jabberd).

jabber服务器中提供im服务的核心组件是使用库加载方法连接的。这表示组件的缘代码被编译成shared object (.so)libraries 并被jabber的主程序(jabberd)加载。

The components are written specially with the Jabber backbone in mind and contain standard registration routines that utilize functions in the core Jabber libraries. These routines are used to bind the component relationship with jabberd (for example there is a 'heartbeat' mechanism through which the components are monitored) and to specify packet receipt requirements. [5]

为适应jabber的中枢,组件使用mind(专门?)而contain(包含?)的利用核心jabber库的功能的标准注册程序特别编写。这些程序被用于绑定组件和jabberd的关系(例如存在heartbeat机制,用于监控组件),并用于指定包的接收条件。

The library load method is represented in the configuration by the <load/> tag, which wraps the library (or libraries) that should be loaded. Example 4-4 and Example 4-5 show excerpts from the standard jabber.xml configuration file where we can see components being plugged in using the library load method.

在配置中,<load/>标签用户描述库加载方法,限制哪个或哪些库应该被装载。例4-4 和例4-5摘自标准的jabberv.xml配置文件中,在这里我们可以看到组件被使用库加载方法插入。

Example 4-4 shows the Client (to Server) Connections (c2s) component, which has been written and compiled as a .so library, being connected using the library load method.

例4-4展示编写并被编译成.so库并被使用库加载方法连接的客户连接组件(c2s)

Example 4-4. Loading of the c2s component with library load


<load>
  <pthsock_client>./pthsock/pthsock_client.so</pthsock_client>
</load>

In this example, we see the "simpler" form of the <load/> tag: inside the tag we have:
在这个例子中,我们看到<load/>标签的“简单”形式:其中有:

<pthsock_client>./pthsock/pthsock_client.so</pthsock_client>

which specifies two things:
这个说明了两个东西:

Which library to load (./pthsock/pthsock_client.so).
1.要加载哪个库(./pthsock/pthsock_client.so)

The name of the component registration routine that should be called by jabberd once the library has been loaded. The name of the routine is the name given to the tag that wraps the library filename; in this example it's pthsock_client(), denoted by <pthsock_client/>.

2.当库被加载后被jabber命名的组件注册routine(程序?)的名字。routine的名字由限制库文件名的标签给出,在这里例子是pthsock_client(),由<pthsock_client/>指明。

Example 4-5 shows multiple .so libraries being loaded when a component is connected; the form of the <load/> tag is slightly more involved.

例4-5展示当一个组件被连接时加载多个.so库;<load/>标签的形式稍微有些棘手:

Example 4-5. Loading of the jsm component with library load
例4-5 使用库加载jsm组件

<load main="jsm">
  <jsm>./jsm/jsm.so</jsm>
  <mod_echo>./jsm/jsm.so</mod_echo>
  <mod_roster>./jsm/jsm.so</mod_roster>
  <mod_time>./jsm/jsm.so</mod_time>
  <mod_vcard>./jsm/jsm.so</mod_vcard>
  <mod_last>./jsm/jsm.so</mod_last>
  <mod_version>./jsm/jsm.so</mod_version>
  <mod_announce>./jsm/jsm.so</mod_announce>
  <mod_agents>./jsm/jsm.so</mod_agents>
  <mod_browse>./jsm/jsm.so</mod_browse>
  <mod_admin>./jsm/jsm.so</mod_admin>
  <mod_filter>./jsm/jsm.so</mod_filter>
  <mod_offline>./jsm/jsm.so</mod_offline>
  <mod_presence>./jsm/jsm.so</mod_presence>
  <mod_auth_plain>./jsm/jsm.so</mod_auth_plain>
  <mod_auth_digest>./jsm/jsm.so</mod_auth_digest>
  <mod_auth_0k>./jsm/jsm.so</mod_auth_0k>
  <mod_log>./jsm/jsm.so</mod_log>
  <mod_register>./jsm/jsm.so</mod_register>
  <mod_xml>./jsm/jsm.so</mod_xml>
</load>

Here we see multiple libraries being loaded to form the Session Management (the JSM) component, known as "jsm".

这里我们看到多个库被加载来构成jsm组件,这就是知名的jsm。

What happens is this:
这里发生了什么:


jabberd loads the library in the tag that's pointed to by the main="" attribute of the <load/> tag; in this example it's the library ./jsm/jsm.so:

jabberd加载被<load/>中的main属性指定的标签中的库;这个例子中是库./jsm/jsm.so:

<jsm>./jsm/jsm.so</jsm>

jabberd then invokes the registration routine called jsm()
然后jabberd调用被称为jsm()的注册程序

jsm loads the rest of the modules defined within the <load/> tag (mod_echo, mod_roster, mod_time, and so on), invoking each module's registration routine (mod_echo(), mod_roster(), mod_time(), and so on) as they're loaded.

jsm加载<load/>标签中定义的其他模块(mod_echo, mod_roster, mod_time等),加载后再调用每个模块的注册routine(mod_echo(), mod_roster(), mod_time()等)。

In case you're wondering, all the modules that belong to the jsm are actually compiled into a single .so library - which is why all the .so references in this example are the same.

万一你感到疑惑,属于这个jsm的所有模块实际上被编译到一个单独的.so库,这就是为什么这里例子中所有的.so引用都一样。

TCP sockets
Another method for connecting components to the Jabber backbone uses a TCP sockets connection. This means that a component connected in this way can reside on the same or a different server to the one running jabberd. So instead of being loaded directly into the jabberd backbone, TCP sockets-connected components exist and run as separate entities and can be started and stopped independently. [6]

将组件连接到jabber中枢的另一个方式是使用tcp连接。这意味着在这种方式下连接的组件可以是在jabber运行的相同或不同的服务器上。因此与直接被加载到jabberd中枢不同,使用tcp套接字连接的组件可以作为分隔的身体存在并运行,并且可以独立启动和停止。

The configuration syntax for defining a connection point for a component that is going to connect to the backbone via TCP sockets looks like this: [7]

指定一个准备通过tcp套接字连接到中枢组件的连接点的配置语法形式如下:

<accept>
  <ip>127.0.0.1</ip>
  <port>9001</port>
  <secret>shhh</secret>
</accept>

As <load/> is to the library load method, so <accept/> is to the TCP sockets method.
<load/>对应库加载方法,<accept/> 对应tcp套接字方法。

The <accept/> tag usually has three child tags - <ip/>, <port/> and <secret/>. [8] Specify an IP address and port to which the component will connect; if you want the socket to be network interface independent, you can write <ip/> (an empty tag) to listen on your specified port on all (INADDR_ANY) IP addresses. The <secret/> tag is used in the handshake when the component connects to the backbone, so that it can be authenticated.

<accept/>套接字通常拥有三个字标签-<ip/>, <port/> 和 <secret/>,指定将要连接的组件的ip地址和端口。如果需要socket成为不受约束的网络接口,你可以写成<ip/>(空标签)在所有(INADDR_ANY)ip地址上监听你指定的端口。<secret/>标签用于在组件连接中枢的握手中做认证。

More information on connecting components with <accept/> can be found in Part II.
 

STDIO
The TCP sockets component connect method is used to connect an external component to the Jabber backbone via a socket connection through which streamed XML documents are exchanged. There is another way for components to connect and exchange XML document streams with the Jabber backbone—using the STDIO connection method.

tcp套接字组件连接方法被用于通过可以交换被“流”化的xml文档的套接字连接来将一个外部组件传输被“流”化的xml文档到jabber中枢。这里还有一种其他方法用于组件和jabber中枢的连接和xml文档流的交换-使用STDIO连接方法。

While the TCP sockets method requires external components to be independently started and stopped, the STDIO method represents a mechanism whereby the jabberd process starts the external component itself. The component to start is specified inside an <exec/> tag. Example 4-6 shows how the STDIO method is specified in the configuration.

不同于tcp套接字方法要求外部组件可以独立启动和停止,STDIO方法描述了这样的机制,可以让jabberd进程自行启动外部组件。启动的组件在<exec/>标签中被指明。例4-6展示了STDIO方式在配置中是怎么说明的:

Example 4-6. Invoking an external component with STDIO
例4-6 用STDIO调用外部组件

<exec>/path/to/component.py -option a -option b</exec>

Here we see that the component is a Python program and is being passed some switches at startup.
这里我们看到,组件是一个Python程序,启动时被传递了一些参数。

So where's the socket connection in this method? There isn't one. The XML documents are exchanged through standard I/O (STDIO). The component writes XML fragments to STDOUT, and these are received on the Jabber backbone. The component receives XML fragments destined for it on STDIN, fragments which are written out from the Jabber backbone.

但是这个方法中socket连接在哪里?没有。xml文档是通过标准的i/o(STDIO)来交换的。组件将xml片段写到STDOUT,jabber中枢接收。组件通过STDIN接收发往自己xml片段,这些片段来自jabber中枢。

Just as a component connected using the TCP sockets method sends an opening document fragment, the component connected with this STDIO method sends an opening document fragment to initiate a connection and conversation:

就像通过tcp套接字连接的组件发送一个开放的文档片段,通过STDIO方式连接的组件发送开发的文档片段来初始化连接和会话。

<?xml version="1.0"?>
<stream:stream xmlns:stream="http://etherx.jabber.org/streams"
               xmlns="jabber:component:exec"
               to="component.name">

Notice how the namespace that describes this type of conversation is:
注意描述回话类型的命名空间是什么:

jabber:component:exec

No secret is required in this case because it is assumed that the component can be trusted if it is specified in the configuration and execution is initiated by jabberd itself.

这种情况下不需要加密,因为已经假设在配置文件中指定并被jabberd自己发送执行的组件是可信任的。
 

原创粉丝点击