当前位置: 首页 > ActiveMQ in Action 读书笔记 > 正文

4.3 通过网络连接到ActiveMQ-Connecting to ActiveMQ over the network

The most common usage scenario is to run ActiveMQ as a standalone Java application.

This implies that clients (producer and consumer applications) will use some of the

network protocols to access the broker’s destinations. In this section, we’ll describe

available network protocols you can use to achieve client-to-broker communication.

 

在所有的应用场景中,最常见的是将ActiveMQ作为一个单独的Java应用程序来运行.这就是说,客户端

(消息生产者和消费者)需要使用一些网络协议一般连接到代理目的地.本节中,我们将介绍可用于实现

客户端到代理之间通信的网络协议.

 

We’ll start with default TCP connector, which is most widely used and provides optimal

performance. Next we’ll dig into the NIO connector, which also uses TCP network

protocol underneath, but additionally provides a bit better scalability than TCP connector

since it uses the NIO Java API. The UDP network protocol is often used on the

internet, so UDP connector is next on our list. UDP protocol introduces some performance

advantages, sacrificing reliability compared to the TCP protocol.

 

TCP连接器是默认的连接器,应用最广泛并且提供最好的性能,我们从讨论TCP连接开始.接下来深入了解NIO连接器,

NIO连接器在底层也是使用TCP协议,但相比TCP协议具有更好的可伸缩性,因为NIO协议使用了NIO的Java API.

UDP协议常用于因特网,所以之后我们接着讨论UDP连接器.UDP协议相比TCP协议,因为牺牲了一些可靠性而获得了一些

性能提升.

 

The same applies to appropriate ActiveMQ connectors, so a UDP connector can offer some performance

advantages over the TCP connector, but it’s still not often used because of

the unreliability it introduces (as explained in more detail later). The SSL connector

can be used to establish a secure connection to the broker, and finally we’ll show you

how to communicate with the broker using HTTP. Of course, in every section we’ll

discuss the pros and cons of every protocol. Therefore, you may want to consider

reading just the subsections that interest you at the moment and then move along to

other chapters. Table 4.1 contains a summarization of the connectors with a brief

description.

 

这些协议的相关特性同样适用于相应的ActiveMQ连接器,因此UDP连接器相比TCP连机器可以提供一些

性能提升,但是UDP协议仍然不常用,因为牺牲了一些可靠性(后面将介绍一些相关细节).SSL连接器可以

建立到代理的安全连接,最后我们将介绍如何使用HTTP协议与代理通信.当然,在每个章节中我们都会

讨论使用不同协议的各种连接器的优缺点.因此,你可以只阅读你感兴趣的章节,然后直接跳到其他章.

表格4.1是各种连接器特性的简要概述.

 

Now, let’s start with the default TCP protocol.

现在让我们从默认的TCP协议开始

 

Table 4.1 Summary of network protocols used for client-broker communication

 

Protocol                Description

协议                    描述

TCP           Default network protocol for most use cases.

TCP协议       大多数应用场景中使用的默认网络协议

 

NIO           Consider NIO protocol if you need to provide better scalability for connections from producers

and consumers to the broker.

NIO协议       当消息生产者和消费者到代理的连接,需要有更好的可扩展性时可以使用NIO协议.

 

UDP           Consider UDP protocol when you need to deal with the firewall between clients and the

broker.

UDP协议       当客户端和代理之间的连接需要穿越防火墙时,可以使用UDP协议.

 

SSL           Consider SSL when you want to secure communication between clients and the broker.

SSL协议       当客户端和代理之间需要安全连接时,可以使用SSL协议.

 

HTTP(S)       Consider HTTP(S) when you need to deal with the firewall between clients and the broker.

HTTP(S)       当客户端和代理之间的连接需要穿越防火墙时,可以也使用HTTP(S)协议.

 

VM            Although not a network protocol per se, consider VM protocol when your broker and clients

communicate with a broker that is embedded in the same Java Virtual Machine (JVM).

VM协议        虽然VM本身不是一个网络协议, 但是当客户端和代理在同一个Java虚拟机(VM)中运行时,他们之间需要通信

时,可以使用VM协议.

 

4.3.1 Transmission Control Protocol (TCP)

4.3.1 传输控制协议(TCP)

 

Transmission Control Protocol (TCP) is today probably as important to humans as electricity.

As one of the fundamental internet protocols, we use it for almost all of our

online communication. It’s used as an underlying network protocol for a wide range

of internet services such as email and the web, for example.

 

如今,传输控制协议对于人类的重要性堪比电能.作为因特网的一个基础协议,传输控制协议几乎已被用于所有的

在线通讯中.传输控制协议作为底层协议用于在整个因特网服务中,比如email服务和网页服务.

 

Hopefully you are already familiar with the basics of TCP, but let’s start our discussion

of TCP by quoting from the specification, RFC 793 (http://mng.bz/Bns2):

The Transmission Control Protocol (TCP) is intended for use as a highly reliable host-to-host

protocol between hosts in packet-switched computer communication networks, and in

interconnected systems of such networks.

 

很幸运,TCP协议的基础知识,你已经很了解了,所以让我从讨论TCP协议的一段规范(RFC 793 (http://mng.bz/Bns2))开始:

TCP协议是一种主机间的高可用的通信协议,该协议使用数据包交换数据实现主机网络间通信,同时该协议也适用于

于和此类主机网络类似的网络系统通信.

 

Since the broker and client applications are network hosts trying to communicate in a

reliable manner, it’s easy to see why TCP is an ideal network protocol for a JMS implementation.

So it shouldn’t come as a surprise that the TCP transport connector is the

most frequently used ActiveMQ connector.

 

考虑到代理和客户端都是网络主机,它们尝试以一种可靠的方式实现彼此间通信.

因而,TCP协议自然而然的成为JMS实现中一种理想的通信协议.

这样,TCP传输连接器作为ActiveMQ连接器中最常用的连接器也就不足为怪了.

 

Before exchanging messages over the network, we need to serialize them to a suitable

form. Messages must be serialized in and out of a byte sequence to be sent over

the wire using what’s known as a wire protocol. The default wire protocol used in

ActiveMQ is called OpenWire. The protocol specification can be found on the

ActiveMQ website (http://mng.bz/u2eT). The OpenWire protocol isn’t specific to

the TCP network transport and can be used with other network protocols. Its main

purpose is to be efficient and allow fast exchange of messages over the network.

Furthermore,a standardized and open protocol such as OpenWire allows native

ActiveMQ clients to be developed for various programming environments. This topic

and a description of other wire level protocols available for ActiveMQ are covered in

chapter 9.

 

通过网络交换消息之前,我们需要将消息序列化成一种合适的格式.ActiveMQ的消息必须被序列化成字节

序列,以便通过线协议发送.ActiveMQ中默认的线协议是OpenWire.可以从(http://mng.bz/u2eT)查看

该线协议规范.OpenWire协议并非用于TCP网络传输,同时也可以用于其他的网络协议中.使用OpenWire协议

的主要目的是提高传输效率以及允许消息在网络中高速交换.并且,类似于OpenWire的这种标准的开放协议

允许在多种编程环境中使用原生的ActiveMQ客户端.第九章中将详细讨论该主题以及ActiveMQ可用的其他”线协议”.

 

As we’ve seen in previous sections, a default broker configuration starts the TCP

transport listening for client connections on port 61616. The TCP connector URI uses

the following syntax:

tcp://hostname:port?key=value&key=value

Please note that the bold portion of the URI denotes the required part. Any key/value

pairs to the right of the question mark are optional and separated by an ampersand.

We won’t discuss all transport options for appropriate protocols in this section or

the sections that follow. This kind of material is best presented via the online reference

pages. An up-to-date reference for the TCP connector can be found on the

ActiveMQ website (http://mng.bz/ngU2).

 

在前面章节中,我们已经看到,使用默认的配置,代理将启动TCP传输连接在61616端口监听客户端连接.

TCP连接器的URI语法如下:

tcp://hostname:port?key=value&key=value

请注意tcp://hostname:port部分是必须的,而问号后面的键值对都是可选的,键值对之间通过&符号分割.

在本节以后后面章节中,我们不打算讨论每种连接协议的所有选项,这部分的相关材料在线文档中有

详细说明,ActiveMQ网站中http://mng.bz/ngU2页面是最新的TCP连接器的在线文档.

 

The following configuration snippet provides an example of using the TCP connector

in the ActiveMQ configuration file:

下面的代码片段是ActiveMQ配置文件中使用TCP配置连接器的一个示例:

<transportConnectors>

<transportConnector name=”tcp” uri=”tcp://localhost:61616?trace=true”/>

</transportConnectors>

 

Note that the trace option has been added to the transport connector URI. This

option instructs the broker to log all commands sent over this connector and can be

helpful for debugging purposes. We have it here as an example of a transport tuning

feature using a transport option. For more information on using the trace option for

debugging, see chapter 14.

 

注意,上面的URI配置中使用了trace参数.这个参数配置为true,说明代理会为每个发送到代理的命令记录日志,

这样对调试很有用.使用trace参数作为一个例子,说明了如何通过URI参数调整传输连接器的行为.

更多的使用trace参数调试的内容请看第十四章内容.

 

IMPORTANT After changing the configuration file, ActiveMQ must be

restarted for the changes to take effect.

The previous section outlined the use of this protocol in the client applications to

connect to the broker. Just for reference, the following example shows how to run the

consumer using the TCP transport connector:

重要: 在修改了配置文件后,必须重启ActiveMQ以便修改能够生效.

前面章节中说明的客户端如何使用TCP协议连接到代理.下面的命令(仅供参考)说明了如何使用TCP传输连接器

运行consumer类.

$ mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Consumer -Dexec.args=”tcp://localhost:61616 CSCO ORCL”

 

ORCL 65.71 65.78 up

ORCL 66.07 66.14 up

ORCL 65.93 65.99 down

CSCO 23.30 23.33 up

 

Some of the benefits of the TCP transport connector include the following:

 Efficiency—Since this connector uses the OpenWire protocol to convert messages

to a stream of bytes (and back), it’s very efficient in terms of network

usage and performance.

 Availability—TCP is one of the most widespread network protocols and has been

supported in Java from the early days, so it’s almost certainly supported on your

platform of choice.

 Reliability—The TCP protocol ensures that messages won’t be lost on the network

(due to glitches, for example).

 

下面是TCP传输连接器的一些优点:

高效性 – 因为TCP连接器使用OpenWire协议将消息转换成字节流(同时也使用OpenWire协议将字节流转换为消息),

所以,网络应用性能十分高效.

高可用性 – TCP协议是应用最为广泛的网络协议,并且Java刚出现时就支持该协议,所以你选择的平台几乎一定支持

该协议.

高可靠性 – TCP协议保证网络中传输的消息不会丢失(比如,使用TCP协议,不会因干扰而造成消息丢失).

 

Now let’s explore some alternatives to the TCP transport connector.

 

下面将探讨TCP连接器之外的其他连接器.

 

4.3.2 New I/O API protocol (NIO)

4.3.2 基于新I/O API的协议

 

The New I/O (NIO) API was introduced in Java SE 1.4 to supplement the existing (standard)

I/O API used in Java until then. Despite the prefix new in its name, NIO was never

meant to be a replacement for the traditional Java I/O API. Its purpose was to provide

an alternative approach to network programming and access to some low-level I/O

operations of modern operating systems. The most prominent features of NIO are

selectors and nonblocking I/O programming, allowing developers to use the same

resources to handle more network clients and generally heavier loads on their servers.

 

From a client perspective, the NIO transport connector is practically the same as the

standard TCP connector, in terms of its use of TCP as the underlying network protocol

and OpenWire as the message serialization protocol. The only difference is under the

covers with the implementation of the transport, where the NIO transport connector

is implemented using the NIO API. This makes the NIO transport connector more suitable

in situations where

 

Java SE 1.4中引入了新I/O API(以下简称NIO),作为之前Java已有的I/O API的补充.尽管被冠以”新”这个前缀,NIO并不是

Java传统I/O API 的替代品.NIO的出现旨在为Java网络编程和现代操作系统底层操作提供一种新方法.

NIO最突出的特性莫过于选择器和非阻塞的I/O编程,

因此允许开发者使用相同的资源服务于更多的网络客户端,并使服务器可以承受更大的负载.

 

 You have a large number of clients you want to connect to the broker—Generally, the

number of clients that can connect to the broker is limited by the number of

threads supported by the operating system. Since the NIO connector

implementation starts fewer threads per client than the TCP connector, you

should consider using NIO in case TCP doesn’t meet your needs.

 

 You have a heavy network traffic to the broker—Again, the NIO connector generally

offers better performance than the TCP connector (in terms of using less

resources on the broker side), so you can consider using it when you find that

the TCP connector doesn’t meet your needs.

 

从客户端的角度来看,使用NIO传输连接器和使用标准的TCP连接器一样,因为NIO传输连接器底层也是使用TCP协议,

同样也是使用OpenWire作为消息序列化协议.NIO传输连接器和TCP连接器的唯一区别是连接器的实现方式,

NIO连接器使用NIO API实现,因此NIO传输连接器适用于下面两种情况:

(1)连接到代理的客户端的数量巨大(当然,能连接到代理的客户端的数量还受到操作系统的支持的最大线程数限制)

NIO连接器为每个客户端连接启动的线程较少,因而你可以考虑使用NIO连接器以防TCP不能满足需求.

(2)连接到代理的网络传输十分拥堵.这种情况下,NIO连接器相对于TCP连接器也可以提供更好的性能(因为在代理端,

NIO连接器使用更少的资源).

 

At this point it’s important to note that performance tuning of ActiveMQ isn’t just

related to choosing the right connector. Many other aspects of ActiveMQ can be

tuned, including the use of a network of brokers topology (see chapter 10) and setting

various options for brokers, producers, and consumers (see chapter 13).

 

这里,有必要说明的是,ActiveMQ性能调优绝不仅限于选择正确的连接器. ActiveMQ还有很多其他

性能相关的参数可以调整,包括代理所在网络的拓扑结构(参见第10章)以及代理,消息生产者和

消息消费者的各种参数(参见第13章).

 

The URI syntax for the NIO connector is practically the same as that of the TCP

connector URI syntax. The only difference is the use of the nio scheme instead of tcp,

as shown:

nio://hostname:port?key=value

Now take a look at the configuration snippet. The NIO part is in bold.

Listing 4.3 Configuring the NIO transport connector

<transportConnectors>

<transportConnector name=”tcp” uri=”tcp://localhost:61616?trace=true” />

<transportConnector name=”nio” uri=”nio:localhost:61618?trace=true” />

</transportConnectors>

 

NIO连接器的URI语法和TCP连接器的URI语法基本上是相同的,唯一的区别是NIO连接器

使用nio主题替代tcp主题,例如:

nio://hostname:port?key=value

情况下面的配置代码片段:

Listing 4.3 Configuring the NIO transport connector

<transportConnectors>

<transportConnector name=”tcp” uri=”tcp://localhost:61616?trace=true” />

<transportConnector name=”nio” uri=”nio:localhost:61618?trace=true” />

</transportConnectors>

 

 

Now run the stock portfolio example, but this time you’ll connect the publisher and

consumer using different transport connectors. As figure 4.3 shows, the publisher will

send messages using the NIO transport connector, whereas the consumer will receive

those messages using the TCP transport connector.

 

现在,可以再次运行stock portfolio这个例子,但是这次我们将使用不同的传输连机器,以便连接publisher

和consumer.如图4.3所示,publisher将使用NIO传输连接器发送消息,而consumer接受消息时,使用TCP传输

连接器.

 

To achieve this, the stock portfolio publisher should be run using the following

command:

$ mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Publisher -Dexec.args=”nio://localhost:61618 CSCO ORCL”

Sending: {price=65.713356601409, stock=JAVA, offer=65.779069958011, up=true}

on destination: topic://STOCKS.JAVA

Sending: {price=66.071605671946, stock=JAVA, offer=66.137677277617, up=true}

on destination: topic://STOCKS.JAVA

Sending: {price=65.929035001620, stock=JAVA, offer=65.994964036622, up=false}

on destination: topic://STOCKS.JAVA

Note that the nio scheme is used in the connection URI to specify the NIO connector.

The consumer should use the TCP connector as shown below:

$ mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Consumer -Dexec.args=”tcp://localhost:61616 CSCO ORCL”

ORCL 65.71 65.78 up

ORCL 66.07 66.14 up

ORCL 65.93 65.99 down

CSCO 23.30 23.33 up

 

 

After both the consumer and producer are started, you’ll notice that messages are

exchanged between applications as expected. The fact that they are using different

connectors to communicate with the broker plays no role in this exchange.

 

为此,需要使用下面的命令来运行stock portfolio的publisher:

$ mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Publisher -Dexec.args=”nio://localhost:61618 CSCO ORCL”

Sending: {price=65.713356601409, stock=JAVA, offer=65.779069958011, up=true} on destination: topic://STOCKS.JAVA

Sending: {price=66.071605671946, stock=JAVA, offer=66.137677277617, up=true} on destination: topic://STOCKS.JAVA

Sending: {price=65.929035001620, stock=JAVA, offer=65.994964036622, up=false} on destination: topic://STOCKS.JAVA

 

注意,传输连接器的URI中使用了nio主题,consumer应该使用TCP连接器,命令如下:

$ mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Consumer -Dexec.args=”tcp://localhost:61616 CSCO ORCL”

ORCL 65.71 65.78 up

ORCL 66.07 66.14 up

ORCL 65.93 65.99 down

CSCO 23.30 23.33 up

 

当consumer和producer都启动以后,应用程序之间会按照预期的那样交换消息.它们使用不同传输连接器

与代理进行通讯,却不会影响消息交换.

 

4.3.3 User Datagram Protocol (UDP)

4.3.3 用户数据报协议

 

User Datagram Protocol (UDP) along with TCP make up the core of internet protocols.

The purpose of these two protocols is identical—to send and receive data packets

(datagrams) over the network. But there are two main differences between them:

 TCP is a stream-oriented protocol, which means that the order of data packets is

guaranteed. There’s no chance for data packets to be duplicated or arrive out

of order. UDP, on the other hand, doesn’t guarantee packet ordering, so a

receiver can expect data packets to be duplicated or arrive out of order.

 TCP also guarantees reliability of packet delivery, meaning that packets won’t be lost

during the transport. This is ensured by maintaining an active connection

between the sender and receiver. On the contrary, UDP is a connectionless protocol,

so it can’t make such guarantees.

 

用户数据报协议和TCP协议都是因特网的核心协议.二者都用于网络中发送和接收消息,但它们之间

也有非常多的区别:

TCP协议是面向流的协议,这个是指TCP协议保证数据包的顺序不会改变.因此,数据包不会重复,

并且会按顺序到达目标.而UDP协议不保证数据包的顺序,因此接受方可能会受到重复的或次序

错乱的数据包.

TCP协议还保证消息分发的可靠性,这就意味着消息在传输过程中不会丢失.这样可以保持消息

发送方和接收方直接的活动连接.与之相反,UDP协议是无连接协议,不能保证消息发送方和接收

方之间的连接.

 

As a result of these differences, TCP is used in applications that require reliability

(such as email), whereas UDP usually finds it place in applications that require fast

data transfers and can handle occasional packet loss (such as VoIP or online gaming).

You can use the UDP protocol to connect to ActiveMQ by using the UDP transport

connector. The URI syntax of this connector is pretty much the same as for the TCP

connector. The only difference is the use of the udp scheme, as shown in the following

snippet:

udp://hostname:port?key=value

The complete reference of the UDP protocol can be found at the ActiveMQ website

(http://mng.bz/1i4g).

 

鉴于二者之间的差异,TCP协议适用于对可靠性有要求的应用(比如email),而UDP协议适用于对消息快速传输

有要求的应用,UDP协议还可以处理偶然性的消息丢失(比如VoIP或者在线游戏).使用UDP传输连接器就可以采用

UDP协议连接到ActiveMQ.UDP连接器的URI语法基本上和TCP连接器的URI的一样,两者之间唯一的区别是UPD连接器的

URI需要使用upd主题,配置代码片段如下:

udp://hostname:port?key=value

关于UPD协议完整的规范请访问ActiveMQ的站点(http://mng.bz/1i4g).

 

Comparing the TCP and UDP transports.

比较TCP连接器和 UDP连接器

 

When considering the TCP and the UDP transports, questions arise that compare

these two protocols. When should you use the UDP transport instead of the TCP

transport? There are basically two such situations where the UDP transport offers an

advantage:

 The broker is located behind a firewall that you don’t control and you can

access it only over UDP ports.

 You’re using time-sensitive messages and you want to eliminate network transport

delay as much as possible.

 

But there are also a couple of pitfalls regarding the UDP connector:

 Since UDP is unreliable, you can end up losing some of the messages, so your

application should know how to deal with this situation.

 Network packets transmitted between clients and brokers aren’t just messages,

but can also contain so-called control commands. If some of these

control commands are lost due to UDP unreliability, the JMS connection

could be endangered.

 

当比较TCP连接器和 UDP连接器时,问题转换为比较TCP和UDP这两个协议.什么使用应该使用UDP连接器

代替TCP连接器?大体上说,在下面两种情况下,应该使用UDP连接器:

(1)你要连接的代理在一个防火墙内,而你没有这个防火墙的控制器,你只能通过UDP端口连接到代理.

(2)你使用的时效性敏感的消息,你需要尽可能的减少消息在网络传输中的延迟.

考虑到UDP协议是不可靠协议,使用UPD连接器也有一些缺陷:

(1)因为UPD协议是不可靠的,所以有些消息可能会丢失,因而你的应用程序需要能够处理这种消息丢失问题.

(2)客户端和代理之间传输的网络数据包不仅仅是消息,有些数据包还包含了所谓的控制命令.如果这些控制命令

因为UDP协议的不可靠性而丢失,JMS连接可能会遭到破坏.

 

Now let’s configure ActiveMQ to use both TCP and UDP transports on different ports.

现在,让我们配置ActiveMQ,以便在不同的端口使用TCP和UDP传输连接器.

Here’s an example of such a configuration; the UDP part is in bold:

下面是配置UDP连接器的代码片段:

<transportConnectors>

<transportConnector name=”tcp” uri=”tcp://localhost:61616?trace=true”/>

<transportConnector name=”udp” uri=”udp://localhost:61618?trace=true” />

</transportConnectors>

 

Note that there are two separate transport connectors on different ports.

注意,上面的代码片段在不同的端口各配置了一个连接器.

 

To run a stock portfolio publisher using the UDP protocol, use the following

command:

$ mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Publisher -Dexec.args=”udp://localhost:61618 CSCO ORCL”

Sending: {price=65.713356601409, stock=JAVA, offer=65.779069958011, up=true} on destination: topic://STOCKS.JAVA

Sending: {price=66.071605671946, stock=JAVA, offer=66.137677277617, up=true} on destination: topic://STOCKS.JAVA

Sending: {price=65.929035001620, stock=JAVA, offer=65.994964036622, up=false} on destination: topic://STOCKS.JAVA

The consumer can be run using the TCP protocol with the following command:

$ mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Consumer -Dexec.args=”tcp://localhost:61616 CSCO ORCL”

ORCL 65.71 65.78 up

ORCL 66.07 66.14 up

ORCL 65.93 65.99 down

CSCO 23.30 23.33 up

As expected, the behavior of the overall system is the same as it was in the original

example when only the TCP transport connector was used. This is due to the fact

that the reliability of a local network is typically very good and there is generally no

packet loss.

 

使用UDP协议运行stock portfolio的publisher,可使用下面的命令:

$ mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Publisher -Dexec.args=”udp://localhost:61618 CSCO ORCL”

Sending: {price=65.713356601409, stock=JAVA, offer=65.779069958011, up=true} on destination: topic://STOCKS.JAVA

Sending: {price=66.071605671946, stock=JAVA, offer=66.137677277617, up=true} on destination: topic://STOCKS.JAVA

Sending: {price=65.929035001620, stock=JAVA, offer=65.994964036622, up=false} on destination: topic://STOCKS.JAVA

使用TCP协议运行consumer,可使用下面的命令:

$ mvn exec:java -Dexec.mainClass=org.apache.activemq.book.ch4.Consumer -Dexec.args=”tcp://localhost:61616 CSCO ORCL”

ORCL 65.71 65.78 up

ORCL 66.07 66.14 up

ORCL 65.93 65.99 down

CSCO 23.30 23.33 up

正如预期的那样,实例中整个系统