发布/订阅是GCP提供的不错的工具。 它非常方便,可以帮助您解决应用程序可能面临的消息传递难题。 实际上,如果您使用GCP,则可以使用托管消息解决方案。
如预期的那样,使用实际的发布/订阅解决方案需要一定的配额,因此对于
开发中,必须使用不会花钱的东西。
在这些情况下,您可以使用Pub / Sub 仿真器 。 要开始使用模拟器,您需要先安装它
gcloud components install pubsub-emulator
确实很方便,但是具有docker映像,因为它更便于携带。 不幸的是,没有来自Google Cloud的官方图片,但是您可以使用Docker Hub上可用的解决方案之一。
现在运行它
gcloud beta emulators pubsub start --project= test -project
之后,您的应用程序可以连接到发布/订阅模拟器。 默认端口为8085
我将以Java单元测试为例。
package org.gkatzioura.pubsub; import java.io.IOException; import java.nio.charset.Charset; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import com.google.api.gax.core.CredentialsProvider; import com.google.api.gax.core.NoCredentialsProvider; import com.google.api.gax.grpc.GrpcTransportChannel; import com.google.api.gax.rpc.FixedTransportChannelProvider; import com.google.api.gax.rpc.TransportChannelProvider; import com.google.cloud.pubsub.v1.Publisher; import com.google.cloud.pubsub.v1.SubscriptionAdminClient; import com.google.cloud.pubsub.v1.SubscriptionAdminSettings; import com.google.cloud.pubsub.v1.TopicAdminClient; import com.google.cloud.pubsub.v1.TopicAdminSettings; import com.google.cloud.pubsub.v1.stub.GrpcSubscriberStub; import com.google.cloud.pubsub.v1.stub.SubscriberStub; import com.google.cloud.pubsub.v1.stub.SubscriberStubSettings; import com.google.protobuf.ByteString; import com.google.pubsub.v1.ProjectSubscriptionName; import com.google.pubsub.v1.ProjectTopicName; import com.google.pubsub.v1.PubsubMessage; import com.google.pubsub.v1.PullRequest; import com.google.pubsub.v1.PullResponse; import com.google.pubsub.v1.PushConfig; import com.google.pubsub.v1.Subscription; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; public class LocalPubSubTest { private static final String PROJECT = "test-project" ; private static final String SUBSCRIPTION_NAME = "SUBSCRIBER" ; private static final String TOPIC_NAME = "test-topic-id" ; private static final String hostPort = "127.0.0.1:8085" ; private ManagedChannel channel; private TransportChannelProvider channelProvider; private TopicAdminClient topicAdmin; private Publisher publisher; private SubscriberStub subscriberStub; private SubscriptionAdminClient subscriptionAdminClient; private ProjectTopicName topicName = ProjectTopicName.of(PROJECT, TOPIC_NAME); private ProjectSubscriptionName subscriptionName = ProjectSubscriptionName.of(PROJECT, SUBSCRIPTION_NAME); private Subscription subscription; @Before public void setUp() throws Exception { channel = ManagedChannelBuilder.forTarget(hostPort).usePlaintext().build(); channelProvider = FixedTransportChannelProvider.create(GrpcTransportChannel.create(channel)); CredentialsProvider credentialsProvider = NoCredentialsProvider.create(); topicAdmin = createTopicAdmin(credentialsProvider); topicAdmin.createTopic(topicName); publisher = createPublisher(credentialsProvider); subscriberStub = createSubscriberStub(credentialsProvider); subscriptionAdminClient = createSubscriptionAdmin(credentialsProvider); subscription = subscriptionAdminClient.createSubscription(subscriptionName, topicName, PushConfig.getDefaultInstance(), 0); } @After public void tearDown() throws Exception { topicAdmin.deleteTopic(topicName); subscriptionAdminClient.deleteSubscription(subscription.getName()); channel.shutdownNow(); } @Test public void testLocalPubSub() throws Exception { final String messageText = "text" ; PubsubMessage pubsubMessage = PubsubMessage.newBuilder() .setData(ByteString.copyFrom(messageText, Charset.defaultCharset())) .build(); publisher.publish(pubsubMessage).get(); PullRequest pullRequest = PullRequest.newBuilder() .setMaxMessages(1) .setReturnImmediately( true ) // if messages are not available immediately return .setSubscription(subscription.getName()) .build(); PullResponse pullResponse = subscriberStub.pullCallable().call(pullRequest); String receiveMessageText = pullResponse.getReceivedMessages(0).getMessage().getData().toStringUtf8(); Assert.assertEquals(messageText, receiveMessageText); } private TopicAdminClient createTopicAdmin(CredentialsProvider credentialsProvider) throws IOException { return TopicAdminClient.create( TopicAdminSettings.newBuilder() .setTransportChannelProvider(channelProvider) .setCredentialsProvider(credentialsProvider) .build() ); } private SubscriptionAdminClient createSubscriptionAdmin(CredentialsProvider credentialsProvider) throws IOException { SubscriptionAdminSettings subscriptionAdminSettings = SubscriptionAdminSettings.newBuilder() .setCredentialsProvider(credentialsProvider) .setTransportChannelProvider(channelProvider) .build(); return SubscriptionAdminClient.create(subscriptionAdminSettings); } private Publisher createPublisher(CredentialsProvider credentialsProvider) throws IOException { return Publisher.newBuilder(topicName) .setChannelProvider(channelProvider) .setCredentialsProvider(credentialsProvider) .build(); } private SubscriberStub createSubscriberStub(CredentialsProvider credentialsProvider) throws IOException { SubscriberStubSettings subscriberStubSettings = SubscriberStubSettings.newBuilder() .setTransportChannelProvider(channelProvider) .setCredentialsProvider(credentialsProvider) .build(); return GrpcSubscriberStub.create(subscriberStubSettings); } }
而已。 现在您可以进行一些具有成本效益的单元测试!
翻译自: https://www.javacodegeeks.com/2019/09/pub-sub-local-emulator.html