跳到主要内容

消息服务

SolacePubSub+ Go 消息 API 提供了 MessagingService 接口,便于连接到事件代理。MessagingService 接口处理与 PubSub+ 事件代理交互的所有功能。要创建一个 MessagingService 实例,你必须首先使用 ServicePropertyMap 配置连接到事件代理所需的信息,包括主机详细信息和认证方案。

创建属性映射

ServicePropertyMap(通过 PubSub+ Go API 中包含的 config 包访问)可以有多个属性,但 ServicePropertyMap 必须包含键 config.TransportLayerPropertyHostconfig.ServicePropertyVPNNameServicePropertyMap 被传递给 MessagingServiceBuilder 以配置连接到事件代理的连接。使用 config 包可以在 ServicePropertyMap 中配置以下五类属性:

  • config.ServiceProperty(用于 VPN 属性,必填)
  • config.TransportLayerProperty(用于 HOST 属性,必填)
  • config.AuthenticationProperty
  • config.ClientProperty
  • config.TransportLayerSecurityProperty

更多信息,请参阅 PubSub+ Go 消息 API 参考

以下代码展示了如何使用 ServicePropertyMap 通过基本认证建立与事件代理的连接:

package main

import (
"fmt"
"os"
"os/signal"
"strconv"
"time"

"solace.dev/go/messaging"
"solace.dev/go/messaging/pkg/solace/config"
"solace.dev/go/messaging/pkg/solace/resource"
)

// 配置参数
brokerConfig := config.ServicePropertyMap{
config.TransportLayerPropertyHost: "tcps://messaging.solace.cloud:55443",
config.ServicePropertyVPNName: "MyVPN",
config.AuthenticationPropertySchemeBasicPassword: "MyPassword123",
config.AuthenticationPropertySchemeBasicUserName: "MyUsername",
}

如果你正在运行示例代码,可以通过 JSON 文件将配置传递给客户端应用程序。以下示例代码展示了如何使用 UnmarshalJSON() 函数解析 JSON 数据并用它创建 ServicePropertyMap

var configMap config.ServicePropertyMap
data,err := os.ReadFile("/path/to/config.json") // ReadFile 读取指定文件并返回内容
error := json.Unmarshal(data, &configMap) // 解析 JSON 编码的数据并将其存储在第二个参数指向的值中
if error != nil {
panic(error)
}
// 使用 FromConfigurationProvider(configMap) 在创建 MessagingService 实例时使用 JSON 数据

端到端负载压缩

PubSub+ Go API 可以执行端到端负载压缩,以实现以下目标:

  • 提高消息吞吐量
  • 减少带宽使用
  • 提高应用程序的性能

尽管端到端负载压缩会增加单个 PubSub+ API 的工作量,但它可以实现更快的消息发布和接收聚合速率。PubSub+ 事件代理提供了传输消息压缩功能,可以压缩整个消息,具体请参阅 流压缩连接。然而,当你发送和接收大消息时,压缩整个消息会使事件代理的工作量增加,从而导致吞吐量降低。如果你的应用程序需要发送和接收大消息,我们建议你使用端到端负载压缩以提高性能。

压缩消息负载时的注意事项

  • 仅使用一种消息压缩方式
    我们建议仅使用一种压缩方式,要么通过事件代理的流压缩连接,要么通过 API 的端到端负载压缩。多次压缩相同的消息会浪费资源,通常也不会使消息大小进一步减小。

  • 不要对小消息使用端到端负载压缩
    端到端负载压缩最适合几兆字节大小的消息。Solace 不建议对小消息使用消息负载压缩,因为端到端负载压缩实际上可能会增加小消息的大小。

  • 升级发布者和接收者应用程序
    接收者应用程序只有在 API 支持消息负载压缩且已更新到最低支持版本时,才会自动解压缩任何压缩的消息负载。如果你的接收者应用程序不支持消息负载压缩,可能会导致潜在的错误或异常。请确保你的发布者和接收者应用程序都已更新到负载压缩的最低支持版本。有关版本支持信息,请参阅 PubSub+ 消息 API 功能支持

  • 端到端负载压缩的限制
    端到端负载压缩目前不支持 PubSub+ 缓存。端到端负载压缩与以下内容不兼容:

    • SolCache
    • 非 SMF 协议,例如 AMQP、HTTP、Kafka 和 MQTT

    如果你的应用程序使用了上述任何内容,我们建议你不要使用端到端负载压缩。

在 PubSub+ Go API 中压缩消息负载

你的发布者应用程序可以在发布消息之前压缩任何消息的负载。要压缩消息负载,你必须设置 ServicePropertyPayloadCompressionLevel,这告诉 API 你希望启用端到端负载压缩。负载压缩级别属性可以设置为 0 到 9 的整数:

  • 0 — 禁用负载压缩。这是默认设置。
  • 1 - 9 — 启用负载压缩。1 是最低压缩级别,数据吞吐量最快;9 是最高压缩级别,数据吞吐量最慢。

你应该根据网络和性能需求调整负载压缩级别。以下代码片段展示了如何在代理属性字典中设置 ServicePropertyPayloadCompressionLevel

serviceProps := config.ServicePropertyMap{
// 设置其他服务属性
config.ServicePropertyPayloadCompressionLevel: "9", // 启用最大压缩级别的负载压缩
}

建立与事件代理的连接

当必要的属性已设置并存储在 ServicePropertyMap 中时,你可以使用 messaging 包调用 NewMessagingServiceBuilder() 函数。此函数返回一个 MessagingServiceBuilder 实例,你可以在该实例上调用 Build() 函数以返回一个 MessagingService 实例。MessagingService 实例允许 API 建立与事件代理的连接。以下是用于创建必要的 MessagingService 实例的常用函数列表:

  • messaging.NewMessagingServiceBuilder()
  • WithAuthenticationStrategy(AuthenticationStrategy authenticationProvider)
  • FromConfigurationProvider(provider config.ServicePropertiesConfigurationProvider)
  • Build()

更多信息,请参阅 PubSub+ Go 消息 API 参考

创建 MessagingService 实例后,你可以调用其 Connect() 函数以连接到事件代理。

以下示例代码展示了如何创建一个简单的 MessagingService 实例并将其连接到事件代理:

messagingService, err := messaging.NewMessagingServiceBuilder().      // 返回一个 solace.MessagingServiceBuilder 实例
FromConfigurationProvider(brokerConfig). // 示例配置提供者是 ServicePropertyMap
WithTransportSecurityStrategy(config.NewTransportSecurityStrategy(). // 配置指定的传输安全策略
WithCertificateValidation(false, true, "./trust_store", "")). // 只支持 .pem 文件。确保目录中包含所需的 .pem 文件
WithAuthenticationStrategy(config.BasicUserNamePasswordAuthentication("myUsername", "myPassword123")). // 配置指定的认证配置
Build() // 根据提供的配置创建并返回构建的 MessagingService 实例
if err != nil {
panic(err)
}

if err := messagingService.Connect(); err != nil { // 连接消息服务到事件代理。此函数会阻塞,直到连接尝试完成。
panic(err)
}

通过代理连接到主机事件代理

你可以通过 HTTP 或 SOCKS5 代理服务器建立与私有网络中事件代理的连接。这允许你为外部代理服务器设置一个防火墙例外,因此任何通过代理服务器认证的客户端都可以访问你的事件代理。代理服务器消除了为每个连接客户端设置防火墙例外的需要。

要通过 HTTP 或 SOCKS 协议版本 5 代理服务器连接到事件代理,主机属性 config.TransportLayerPropertyHost 必须包含标准连接到事件代理所需的参数,但它还必须包含一个 ProxyService 字符串:

brokerConfig := config.ServicePropertyMap{
config.TransportLayerPropertyHost: "[Protocol:]Host[:Port][%ProxyService]",
// ...
}

其中:

ProxyService — 用于连接到事件代理的代理服务器。代理服务字符串格式指定为:

[ProxyProtocol]://[username:password@]proxyHost[:proxyPort]

其中:

  • ProxyProtocol — 用于与代理服务器通信的协议。有效值为:
    • socks5 — 使用 SOCKS 协议版本 5 (RFC 1928, IETF 标准文档) 连接到服务器。
    • httpc — 使用 HTTP Connect 协议 (RFC 2817, IETF 标准文档) 连接到服务器。
  • username:password@ — 如果代理服务器需要认证,则可以在代理主机之前指定用户名和密码。
  • proxyHost — 代理服务器的 IP 地址(或主机名)。
  • proxyPort — 用于连接的端口。如果未指定端口号,则 SOCKS5 默认为 1080 端口,HTTP Connect 默认为 3128 端口。

示例:

以下示例展示了如何通过代理服务器连接到事件代理。

  • 192.168.160.28%socks5://192.168.1.1 — 通过位于 192.168.1.1 的 SOCKS5 代理服务器连接到位于 192.168.160.28 的事件代理。
  • 192.168.160.28%httpc://192.168.1.1 — 通过位于 192.168.1.1 的 HTTP-Connect 代理服务器连接到位于 192.168.160.28 的事件代理。
  • tcps:solace.company.com%socks5://User:PassWord@proxy.company.com:13128 — 使用 SSL over TCP 通过位于 proxy.company.com 的 SOCKS5 代理服务器连接到位于 solace.company.com 的事件代理,端口为 13128。使用用户名 User 和密码 PassWord 认证代理服务器。
  • http://192.168.160.28:44444%httpc://proxy.company.com:11050 — 使用 HTTP 连接到位于 192.168.160.28 的事件代理,端口为 44444。通过位于 proxy.company.com 的代理服务器连接,端口为 11050。

使用传输层安全

传输层安全(TLS)允许在 PubSub+ Go API 和 PubSub+ 事件代理之间进行加密认证和数据传输。PubSub+ Go API 支持 TLS 1.0、TLS 1.1 和 TLS 1.2 版本的传输层安全。推荐使用最新版本的 TLS。还支持安全套接字层(SSL)协议版本 3(SSLv3),但除非需要向后兼容,否则不推荐使用 SSL。

你可以使用 WithTransportSecurityStrategy()config 包来配置要使用的 TLS 连接属性,或者是否完全禁用证书验证。当你使用 TLS 时,必须始终在设置 config.TransportLayerPropertyHost 属性时使用安全 TCP 协议(tcpshttps),例如:

brokerConfig := config.ServicePropertyMap{
config.TransportLayerPropertyHost: "tcps://messaging.solace.cloud:55443",
config.ServicePropertyVPNName: "MyVPN",
}

我们建议在配置消息服务时使用证书验证。PubSub+ Go API 的 config 包提供了以下函数用于配置证书验证:

  • WithCertificateValidation(ignoreExpiration bool, validateServerName bool, trustStoreFilePath string, trustedCommonNameList string)
    • ignoreExpiration — 设置为 true 时,接受已过期的证书。
    • validateServerName — 设置为 true 时,不接受与主机名不匹配的证书。
    • trustStoreFilePath — 信任存储文件的位置。信任存储文件必须是 PEM 格式。如果传递空字符串,则不会设置文件路径。
    • trustedCommonNameList — 用于与服务器证书匹配的可接受通用名称的逗号分隔列表。空字符串将不匹配任何名称。

以下示例代码展示了在使用 TLS 时客户端应用程序的推荐安全设置:

messagingService0, err := messaging.NewMessagingServiceBuilder().
FromConfigurationProvider(brokerConfig).
WithTransportSecurityStrategy(
config.NewTransportSecurityStrategy(). // 创建默认的传输安全策略。可以通过调用配置函数覆盖属性。
WithCertificateValidation(false, true, "./trust_store", ""). // 配置 TLS 证书验证。默认情况下,会执行验证。
WithExcludedProtocols( // 指定不使用的 SSL 或 TLS 协议列表。
config.TransportSecurityProtocolTLSv1, // 排除过时的协议 TLSv1、TLSv1_1 和 SSLv3。
config.TransportSecurityProtocolTLSv1_1,
config.TransportSecurityProtocolSSLv3)).
WithAuthenticationStrategy(config.BasicUserNamePasswordAuthentication("myUserName123", "myPassword123")).
Build()

还有许多函数可以帮助你使用 WithTransportSecurityStrategy() 函数配置 TLS 连接。以下是三个常用的配置 TLS 连接的函数:

  • WithCipherSuites() — 可以配置在协商 TLS 连接时使用的密码套件列表。你可以配置 PubSub+ Go API 仅使用一组更强的密码,以确保客户端应用程序和事件代理之间的连接更加安全。

密码套件是通过 TLS 握手加密通信的有用方法,可以提高通过事件代理连接的应用程序之间的安全性。更详细的解释和支持的密码套件列表,请参阅 密码套件

以下代码示例展示了如何使用 WithCipherSuites() 函数:

messagingService00, err := messaging.NewMessagingServiceBuilder().
FromConfigurationProvider(brokerConfig).
WithTransportSecurityStrategy(
config.NewTransportSecurityStrategy().
WithCipherSuites("CipherSuite1, CipherSuite2"). // 配置要使用的密码套件的逗号分隔列表。
WithAuthenticationStrategy(config.ClientCertificateAuthentication("certFile", "keyFile", "keyPassword")).
Build()
  • WithExcludedProtocols() — 你可能不希望使用某些协议与微服务连接。例如,你可能不想使用旧版协议。使用此函数指定不使用的安全套接字层(SSL)和传输层安全(TLS)协议。以下示例代码展示了如何排除特定协议:
messagingService00, err := messaging.NewMessagingServiceBuilder().
FromConfigurationProvider(brokerConfig).
WithTransportSecurityStrategy(
config.NewTransportSecurityStrategy().
WithExcludedProtocols(config.TransportSecurityProtocolTLSv1). // 指定不使用的 SSL 或 TLS 协议列表。
WithAuthenticationStrategy(config.ClientCertificateAuthentication("certFile", "keyFile", "keyPassword")).
Build()
  • WithoutCertificateValidation() — 此函数配置你的 TLS 连接不验证服务器证书。

仅在开发环境中使用此函数。我们建议你永远不要在生产环境中使用此函数,因为它会创建安全漏洞。

以下示例代码展示了如何使用 WithoutCertificateValidation() 函数:

messagingService, err := messaging.NewMessagingServiceBuilder().
FromConfigurationProvider(brokerConfig).
WithTransportSecurityStrategy(
config.NewTransportSecurityStrategy().
WithoutCertificateValidation(). // 配置 TLS 不验证远程代理上配置的服务器证书。
WithAuthenticationStrategy(config.ClientCertificateAuthentication("certFile", "keyFile", "keyPassword")).
Build()

你还可以使用 ServicePropertyMap 中的 TransportLayerSecurityProperty 配置 TLS 连接的各个方面。TLS 连接可以通过 config.TransportLayerSecurityProperty 中的各种字段进行配置。我们建议你使用默认设置(设置为 true 并启用),以确保以下属性的安全连接:

  • config.TransportLayerSecurityPropertyCertRejectExpired
  • config.TransportLayerSecurityPropertyCertValidateServername
  • config.TransportLayerSecurityPropertyCertValidated

有关函数和属性的更多信息,请参阅 PubSub+ Go 消息 API 参考

认证

PubSub+ Go 消息 API 支持多种认证方案或策略供你选择。你选择的方案可能取决于连接客户端需要提供的凭据。每个 MessagingService 实例只能使用一种认证方案。你可以选择以下认证方案之一:

  • 基本认证
  • Kerberos 认证
  • 客户端证书认证
  • OAuth 2.0 认证

基本认证

基本认证是默认的客户端认证方案,允许客户端使用客户端用户名和密码认证事件代理。要指定基本认证,创建一个 MessagingService 实例,并将以下内容作为 WithAuthenticationStrategy() 函数的参数:

  • config.BasicUserNamePasswordAuthentication("myUsername", "myPassword")

详细信息,请参阅 Go 消息 API 参考

以下示例代码展示了如何使用基本认证:

messagingService, err
:= messaging.NewMessagingServiceBuilder(). // 返回一个 solace.MessagingServiceBuilder 实例。
FromConfigurationProvider(brokerConfig). // 示例配置提供者是 ServicePropertyMap。
WithAuthenticationStrategy(config.BasicUserNamePasswordAuthentication("myUsername", "myPassword123")). // 配置指定的认证配置。
Build() // 根据提供的配置创建并返回构建的 MessagingService 实例。

Kerberos 认证

PubSub+ Go API 提供了对 Kerberos 认证的支持。使用此功能连接需要你在代理上加载一个 Kerberos Keytab(参阅 管理事件代理文件),并且必须为 Kerberos 认证客户端连接的消息 VPN 配置并启用 Kerberos 认证。

调用 WithAuthenticationStrategy() 函数并传递以下参数:

  • config.KerberosAuthentication(serviceName string) 如果不需要服务名称,可以传递空字符串作为 serviceName 参数。

更多详细信息,请参阅 Go 消息 API 参考

以下示例代码展示了如何使用 Kerberos 进行认证:

messagingService, err := messaging.NewMessagingServiceBuilder().              // 返回一个 solace.MessagingServiceBuilder 实例。
FromConfigurationProvider(brokerConfig). // 示例配置提供者是 ServicePropertyMap。
WithAuthenticationStrategy(config.KerberosAuthentication("serviceName")). // 配置指定的认证配置。
Build() // 根据提供的配置创建并返回构建的 MessagingService 实例。

客户端证书认证

要使用客户端证书认证方案,需要执行以下步骤:

  • 配置主机事件代理以使用 TLS 连接(参阅 使用传输层安全)。
  • 你的应用程序必须通过 TLS 连接到代理。
  • 在应用程序连接使用的消息 VPN 上启用客户端证书验证。
  • 客户端证书必须存在于密钥库文件中,并通过以下方式配置:
    • config.ClientCertificateAuthentication(certificateFile, keyFile, keyPassword string)
    • 如果 certificateFilekeyFile 在同一个文件中,则为每个参数指定相同的文件路径。
    • certificateFilekeyFile 必须是 PEM 格式。
    • 如果私钥没有密码,为 keyPassword 使用空字符串。

更多详细信息,请参阅 PubSub+ Go 消息 API 参考

以下示例代码展示了如何配置客户端证书认证:

messagingService, err := messaging.NewMessagingServiceBuilder().              // 返回一个 solace.MessagingServiceBuilder 实例。
FromConfigurationProvider(brokerConfig). // 示例配置提供者是 ServicePropertyMap。
WithTransportSecurityStrategy(config.NewTransportSecurityStrategy(). // 配置指定的传输安全策略。
WithCertificateValidation(false, true, "./trust_store.pem", "")). // 只支持 .pem 文件。确保目录中存储了 .pem 文件。
WithAuthenticationStrategy(config.ClientCertificateAuthentication("certFile", "keyFile", "keyPassword")). // 配置指定的认证配置。
Build() // 根据提供的配置创建并返回构建的 MessagingService。

OAuth 2.0 认证

OAuth 2.0 是一种开放标准,用于访问授权和授权委托。它通常用于允许网站或应用程序访问其他网站上的用户信息,而无需提供敏感凭据。OAuth 认证方案允许通过授权服务器向第三方客户端颁发的令牌访问 PubSub+ 事件代理上的消息 VPN。要使用 OAuth 2.0 认证,配置主机事件代理以使用 TLS 连接(参阅 使用传输层安全),并确保你的应用程序通过 TLS 连接到事件代理。更多详细信息,请参阅 OAuth 认证

PubSub+ Go API 支持发送到事件代理的不同字段:

  • accessToken — 一个 String,用于应用程序请求数据访问。
    和/或
  • idToken — 一个 String,用于 Open ID Connect (OIDC) 连接。
  • issuerIdentifier — (可选)一个 String,用于标识适当的 OAuth 配置文件。

OAuth 认证需要使用以下函数启用 accessTokenidToken 或两者:

  • config.OAuth2Authentication(accessToken string, oidcIDToken string, issuerIdentifier string)
    必须提供 accessTokenoidcIDToken 中的一个。如果不需要任何参数,可以传递空字符串。

更多详细信息,请参阅 PubSub+ Go 消息 API 参考

以下示例代码展示了如何使用 OpenID Connect (OIDC) 的 OAuth 认证:

/* 配置服务访问以使用 Open ID Connect 认证,使用 ID 令牌和可选的访问令牌。 */
messagingService, err := messaging.NewMessagingServiceBuilder(). // 返回一个 solace.MessagingServiceBuilder 实例。
FromConfigurationProvider(brokerConfig). // 示例配置提供者是 ServicePropertyMap。
WithTransportSecurityStrategy(config.NewTransportSecurityStrategy(). // 配置指定的传输安全策略。
WithCertificateValidation(false, true, "./trust_store", "")). // 只支持 .pem 文件。确保目录中包含所需的 .pem 文件。
WithAuthenticationStrategy(config.OAuth2Authentication("accessToken", "oidcIDToken", "")). // 配置指定的认证配置。
Build() // 根据提供的配置创建并返回构建的 MessagingService 实例。
/* 配置服务访问以使用 OAuth 2 认证,使用访问令牌和可选的发行者标识符。 */
messagingService, err := messaging.NewMessagingServiceBuilder(). // 返回一个 solace.MessagingServiceBuilder 实例。
FromConfigurationProvider(brokerConfig). // 示例配置提供者是 ServicePropertyMap。
WithTransportSecurityStrategy(config.NewTransportSecurityStrategy(). // 配置指定的传输安全策略。
WithCertificateValidation(false, true, "./trust_store", "")). // 只支持 .pem 文件。确保目录中包含所需的 .pem 文件。
WithAuthenticationStrategy(config.OAuth2Authentication("accessToken", "", "issuerIdentifier")). // 配置指定的认证配置。
Build() // 根据提供的配置创建并返回构建的 MessagingService 实例。

刷新过期的 OAuth 令牌

默认情况下,事件代理会在令牌过期时断开客户端连接(参阅 令牌过期时断开连接)。当客户端会话被断开时,客户端应用程序会根据 RECONNECTION_ATTEMPTS 属性使用相同的 OAuth 令牌尝试重新连接多次。如果由于令牌过期无法重新建立连接,客户端应用程序必须重新创建会话及其所有订阅。

要更新 OAuth 令牌,请使用 UpdateProperty(property config.ServiceProperty, value interface{}) 方法,这允许你在创建 MessagingService 实例后设置可修改的服务属性。第一个参数是以下字符串之一,第二个参数是令牌:

  • solace.messaging.authentication.oauth2.access-token 用于更新过期的访问令牌。
  • solace.messaging.authentication.oauth2.oidc-id-token 用于更新过期的 ID 令牌。

可修改的服务属性可能不会立即更新,可能需要在下一次重新连接尝试时才会更新。

刷新过期令牌可能发生在以下情况:

  • 客户端应用程序已连接。在这种情况下,客户端会联系认证服务器刷新令牌,并在下次 API 连接到事件代理时修改会话以使用更新后的令牌。
  • 客户端应用程序正在重新连接。重新连接事件包括一个诊断子代码。如果该子代码为 Login Failure,则可能表明你的令牌已过期。在这种情况下,API 会尝试使用过期的令牌重新连接。客户端随后会联系认证服务器刷新令牌,并在下次 API 尝试重新连接到事件代理时修改会话以使用更新后的令牌。

一般来说,如果客户端应用程序能够意识到潜在的令牌过期,并在过期之前刷新令牌,会更好。

当客户端应用程序的会话重新连接时,Go API 会重新应用客户端应用程序的直接订阅。如果由于刷新令牌导致 ACL 发生变化,事件代理可能会拒绝这些订阅。