我正在尝试使用 Google 云 Pub/Sub 模拟器来测试我的 scala 应用程序。 文档指出以下内容 -
运行 env-init 命令确定并设置模拟器使用的环境变量。请注意,按照这些说明操作后,代码中的 Google Cloud Pub/Sub 客户端库将调用在本地实例中运行的 API,而不是生产 API。
但是当我发布消息或创建主题时,它会在云中执行,而不是在本地模拟器上执行。我已经使用打印
println(s"ENV: ${sys.env("PUBSUB_EMULATOR_HOST")}")
的 ENV: localhost:8085
确认环境变量设置正确。
我尝试强制库使用我的本地设置,如下所示
val settings = TopicAdminSettings.defaultBuilder()
.setChannelProvider(InstantiatingChannelProvider.newBuilder()
.setEndpoint("localhost:8085")
.setCredentialsProvider(TopicAdminSettings.defaultCredentialsProviderBuilder().build())
.build())
.build()
val topicAdminClient = TopicAdminClient.create(settings)
topicAdminClient.createTopic(topicName)
通过这种方式,我成功向本地设置发送请求,但这会导致以下错误 -
[pubsub] 6 14, 2017 2:49:11 午後 io.gapi.emulators.grpc.GrpcServer$3 operationComplete
[pubsub] INFO: Adding handler(s) to newly registered Channel.
[pubsub] 6 14, 2017 2:49:11 午後io.gapi.emulators.netty.HttpVersionRoutingHandler channelRead
[pubsub] INFO: Detected non-HTTP/2 connection.
[pubsub] 6 14, 2017 2:49:11 午後 io.gapi.emulators.netty.NotFoundHandler handleRequest
[pubsub] INFO: Unknown request URI: /bad-request
[pubsub] 6 14, 2017 2:49:35 午後 io.gapi.emulators.grpc.GrpcServer$3 operationComplete
[pubsub] INFO: Adding handler(s) to newly registered Channel.
[pubsub] 6 14, 2017 2:49:35 午後 io.gapi.emulators.netty.HttpVersionRoutingHandler channelRead
[pubsub] INFO: Detected non-HTTP/2 connection.
[pubsub] 6 14, 2017 2:49:35 午後 io.gapi.emulators.netty.NotFoundHandler handleRequest
[pubsub] INFO: Unknown request URI: /bad-request
我按如下方式启动模拟器 -
PC-12041:random kakaji$ sudo gcloud beta emulators pubsub start
Password:
Executing: /usr/local/google-cloud-sdk/platform/pubsub-emulator/bin/cloud-pubsub-emulator --host=localhost --port=8085
[pubsub] This is the Google Pub/Sub fake.
[pubsub] Implementation may be incomplete or differ from the real system.
[pubsub] 6 14, 2017 2:59:21 午後 com.google.cloud.pubsub.testing.v1.Main main
[pubsub] INFO: IAM integration is disabled. IAM policy methods and ACL checks are not supported
[pubsub] 6 14, 2017 2:59:21 午後 io.grpc.internal.ManagedChannelImpl <init>
[pubsub] INFO: [ManagedChannelImpl@77b52d12] Created with target localhost:8085
[pubsub] 6 14, 2017 2:59:21 午後 io.gapi.emulators.netty.NettyUtil applyJava7LongHostnameWorkaround
[pubsub] INFO: Unable to apply Java 7 long hostname workaround.
[pubsub] 6 14, 2017 2:59:21 午後 com.google.cloud.pubsub.testing.v1.Main main
[pubsub] INFO: Server started, listening on 8085
Google Cloud Pub/Sub 文档提到Java 和 C# 客户端库不会通过
PUBSUB_EMULATOR_HOST
自动连接到模拟器主机。
相反,您应该执行以下操作(摘自文档):
String hostport = System.getenv("PUBSUB_EMULATOR_HOST");
ManagedChannel channel = ManagedChannelBuilder.forTarget(hostport).usePlaintext().build();
CredentialsProvider credentialsProvider = NoCredentialsProvider.create();
// Publisher that connects to the emulator
TopicName topicName = TopicName.of("my-project-id", "my-topic-id");
// Set the channel and credentials provider when creating a `Publisher`.
// Similarly for Subscriber
Publisher publisher =
Publisher.newBuilder(topicName)
.setChannelProvider(channelProvider)
.setCredentialsProvider(credentialsProvider)
.build();
您可能需要检查是否设置了
PUBSUB_EMULATOR_HOST
,然后才在构建器上设置 NoCredentialsProvider
和自定义 ManagedChannel
。
根据我最近的经验(当我遇到问题中描述的相同问题时,我偶然发现了这个SO问题,并且我刚刚找到了适合我的解决方案)这段代码有效:
var channel = ManagedChannelBuilder
.forTarget("localhost:8681").usePlaintext().build();
var tc = GrpcTransportChannel.create(channel);
final var channelProvider = FixedTransportChannelProvider.create(tc);
publisher = Publisher.newBuilder(TopicName.of(projectId, pubSubTopic))
.setCredentialsProvider(credentialsProvider)
.setEndpoint("localhost:8681")
.setChannelProvider(channelProvider)
.setEnableMessageOrdering(true)
.build();
我还没有发现是否必须准确定义模拟器端点。就在发布者的构建器中吗?仅在 ManagedChannel 中?但代码按原样工作。