当前位置: 首页 > 知识库问答 >
问题:

如何为google pub sub gRPC调用配置代理凭据?

高墨一
2023-03-14

我正试图通过代理连接到谷歌云平台pub/sub。

使用Spring lib“org.springframework.cloud:Spring cloud gcp starter pubsub”,它使用google pub sub客户端,为了对订阅进行pull调用,它使用gRPC调用

为了设置代理,我可以使用GRPC_proxy_EXP环境变量,但我还需要通过此代理的凭据。

我尝试了几种方法,包括配置org。springframework。云gcp。pubsub。支持订阅工厂类似于此处https://medium.com/google-cloud/accessing-google-cloud-apis-though-a-proxy-fe46658b5f2a

@Bean
    fun inboundQuotationsChannelAdapter(
        @Qualifier("inboundQuotationsMessageChannel") quotationsChannel: MessageChannel,
        mpProperties: ConfigurationProperties,
        defaultSubscriberFactory: SubscriberFactory
    ): PubSubInboundChannelAdapter {

        Authenticator.setDefault(ProxyAuthenticator("ala","bala"))

        val proxySubscriberFactory: DefaultSubscriberFactory = defaultSubscriberFactory as DefaultSubscriberFactory
        proxySubscriberFactory.setCredentialsProvider(ProxyCredentialsProvider(getCredentials()))
        val headers = mutableMapOf(Pair("Proxy-Authorization", getBasicAuth()))
        proxySubscriberFactory.setChannelProvider(SubscriberStubSettings.defaultGrpcTransportProviderBuilder()
            .setHeaderProvider(FixedHeaderProvider.create(headers)).build())


        val proxySubscriberTemplate = PubSubSubscriberTemplate(proxySubscriberFactory)

        val adapter = PubSubInboundChannelAdapter(proxySubscriberTemplate, mpProperties.gcp.quotationSubscription)
        adapter.outputChannel = quotationsChannel
        adapter.ackMode = AckMode.MANUAL
        adapter.payloadType = ActivityStateChanged::class.java
        return adapter
    }


    @Throws(IOException::class)
    fun getCredentials(): GoogleCredentials {
        val httpTransportFactory = getHttpTransportFactory(
            "127.0.0.1", 3128, "ala", "bala"
        )
        return GoogleCredentials.getApplicationDefault(httpTransportFactory)
    }

    fun getHttpTransportFactory(
        proxyHost: String?,
        proxyPort: Int,
        proxyUsername: String?,
        proxyPassword: String?
    ): HttpTransportFactory? {
        val proxyHostDetails = HttpHost(proxyHost, proxyPort)
        val httpRoutePlanner: HttpRoutePlanner = DefaultProxyRoutePlanner(proxyHostDetails)
        val credentialsProvider: CredentialsProvider = BasicCredentialsProvider()
        credentialsProvider.setCredentials(
            AuthScope(proxyHostDetails.hostName, proxyHostDetails.port),
            UsernamePasswordCredentials(proxyUsername, proxyPassword)
        )
        val httpClient: HttpClient = ApacheHttpTransport.newDefaultHttpClientBuilder()
            .setRoutePlanner(httpRoutePlanner)
            .setProxyAuthenticationStrategy(ProxyAuthenticationStrategy.INSTANCE)
            .setDefaultCredentialsProvider(credentialsProvider)
            .setDefaultRequestConfig(
                RequestConfig.custom()
                    .setAuthenticationEnabled(true)
                    .setProxy(proxyHostDetails)
                    .build())
            .addInterceptorLast(HttpRequestInterceptor { request, context ->
                request.addHeader(
                    BasicHeader(
                        "Proxy-Authorization",
                        getBasicAuth()
                    )
                )
            })
            .build()
        val httpTransport: HttpTransport = ApacheHttpTransport(httpClient)
        return HttpTransportFactory { httpTransport }
    }

还尝试使用LogNet中的@GRpcGlobalInterceptorhttps://github.com/LogNet/grpc-spring-boot-starter

    @Bean
    @GRpcGlobalInterceptor
    fun globalServerInterceptor(): ServerInterceptor {
        return GrpcServerInterceptor(configurationProperties)
    }

    @Bean
    @GRpcGlobalInterceptor
    fun globalClientInterceptor(): ClientInterceptor {
        return GrpcClientInterceptor(configurationProperties)
    }

具有

class GrpcClientInterceptor(private val configurationProperties: ConfigurationProperties) :
    ClientInterceptor {

    private val proxyUsername = configurationProperties.http.proxy.username
    private val proxyPassword = configurationProperties.http.proxy.password
    private val proxyHeaderKey = Metadata.Key.of("Proxy-Authorization", Metadata.ASCII_STRING_MARSHALLER)

    private fun getBasicAuth(): String {
        val usernameAndPassword = "$proxyUsername:$proxyPassword"
        val encoded = Base64.getEncoder().encodeToString(usernameAndPassword.toByteArray())
        return "Basic $encoded"
    }

    override fun <ReqT, RespT> interceptCall(
        method: MethodDescriptor<ReqT, RespT>?,
        callOptions: CallOptions?, next: Channel
    ): ClientCall<ReqT, RespT>? {
        return object : SimpleForwardingClientCall<ReqT, RespT>(next.newCall(method, callOptions)) {
            override fun start(responseListener: Listener<RespT>?, headers: Metadata) {
                headers.put(proxyHeaderKey, getBasicAuth())
                super.start(object : SimpleForwardingClientCallListener<RespT>(responseListener) {
                    override fun onHeaders(headers: Metadata) {
                        super.onHeaders(headers)
                    }
                }, headers)
            }
        }
    }
}
class GrpcServerInterceptor(private val configurationProperties: ConfigurationProperties) :
    ServerInterceptor {

    private val proxyUsername = configurationProperties.http.proxy.username
    private val proxyPassword = configurationProperties.http.proxy.password

    override fun <ReqT : Any?, RespT : Any?> interceptCall(
        call: ServerCall<ReqT, RespT>?,
        headers: io.grpc.Metadata?,
        next: ServerCallHandler<ReqT, RespT>?
    ): ServerCall.Listener<ReqT> {
        val proxyHeaderKey = Metadata.Key.of("Proxy-Authorization", Metadata.ASCII_STRING_MARSHALLER)
        if (!headers!!.containsKey(proxyHeaderKey))
            headers!!.put(proxyHeaderKey, getBasicAuth())
        return next!!.startCall(call, headers)
    }

    private fun getBasicAuth(): String {
        val usernameAndPassword = "$proxyUsername:$proxyPassword"
        val encoded = Base64.getEncoder().encodeToString(usernameAndPassword.toByteArray())
        return "Basic $encoded"
    }
}

(还直接在类级别尝试了注释——ofc它不起作用)

还尝试从https://github.com/yidongnan/grpc-spring-boot-starter/tree/v2.12.0.RELEASE使用@GrpcGlobalServerInterceptor@GrpcGlobalClientInterceptor,但此依赖项完全崩溃了应用程序

共有1个答案

司徒修能
2023-03-14

在这里,您可以找到一个关于如何从Java API文档中设置代理凭据以配置代理的示例;

public CloudTasksClient getService() throws IOException {
  TransportChannelProvider transportChannelProvider =
      CloudTasksStubSettings.defaultGrpcTransportProviderBuilder()
          .setChannelConfigurator(
              new ApiFunction<ManagedChannelBuilder, ManagedChannelBuilder>() {
                @Override
                public ManagedChannelBuilder apply(ManagedChannelBuilder managedChannelBuilder) {
                  return managedChannelBuilder.proxyDetector(
                      new ProxyDetector() {
                        @Nullable
                        @Override
                        public ProxiedSocketAddress proxyFor(SocketAddress socketAddress)
                            throws IOException {
                          return HttpConnectProxiedSocketAddress.newBuilder()
                              .setUsername(PROXY_USERNAME)
                              .setPassword(PROXY_PASSWORD)
                              .setProxyAddress(new InetSocketAddress(PROXY_HOST, PROXY_PORT))
                              .setTargetAddress((InetSocketAddress) socketAddress)
                              .build();
                        }
                      });
                }
              })
          .build();
  CloudTasksSettings cloudTasksSettings =
      CloudTasksSettings.newBuilder()
          .setTransportChannelProvider(transportChannelProvider)
          .build();
  return CloudTasksClient.create(cloudTasksSettings);
}

 

考虑到注释中说gRPC代理目前是实验性的。

 类似资料:
  • 我正在尝试使用OpenTelemetry代理从我用Scala编写的Akka应用程序中导出度量和跟踪,目的是使用OpenSearch中的数据。 我的应用程序的技术堆栈: Akka-2.6* 我已经将OpenTelemetry instrumentation运行时依赖项添加到构建中。sbt: 我正在属性文件中传递OpenTelem计配置: 我的代码中唯一其他相关的部分是属性文件: 我确实在OpenSe

  • 配置代理服务器能干嘛 NEI toolkit 提供了代理服务器的功能,帮助将接口代理到NEI官网或者特定的服务器上 将接口代理到NEI官网 开启该功能只需将server.config.js中的online设为true, 那么对Mock Server的所有请求都将会代理到NEI官网上,该模式也被称为在线模式。 启用在线模式可以减少执行nei update的操作,在频繁更改官网数据的情况下能够大幅加快

  • 本文向大家介绍如何将Nginx配置为WebSocket的反向代理,包括了如何将Nginx配置为WebSocket的反向代理的使用技巧和注意事项,需要的朋友参考一下 WebSocket是一种协议,提供了一种创建Web应用程序的方式,该应用程序支持客户端和服务器之间的实时双向通信。WebSocket使开发这些类型的应用程序变得更加容易。大多数现代浏览器都支持WebSocket,包括Firefox,In

  • 我能够在Scala代码上运行调试器,但不能再用IntelJ IDE Community Edition 2020.1.1(2020年4月)... 对于Scala-Play应用程序,它过去是直接的(只需启动sbt控制台,然后按下“绿色小bug按钮”,我想它类似于wood attach remote process下的“attach process” 现在我得到: 运行“调试sbt shell”时出错

  • 问题内容: 我想运行安装游览,但是找不到使用代理访问互联网的选项。我不仅仅为了旅游而需要它,而是为了总体上在Go中进行开发。 如何配置Go以使用代理。 问题答案: Go程序了解环境变量和,但这还不够,因为使用源代码管理器来检索代码。因此,您还必须为SCM设置HTTP代理设置。使用此为水银和这个 GIT中。 价值可以像。用户,密码和端口部分是可选的。是不应该通过代理服务器连接的服务器的逗号分隔列表。

  • 在Windows上,是否可以将Atom配置为使用系统默认代理,而不是在.apmrc文件中手动指定代理设置? 我最近开始使用atom-editor for Windows(Windows7 Pro),到目前为止我很喜欢它。我已经搜索了一段时间,试图让编辑能够连接到外部世界,但没有遇到任何成功。 我们的网络(我不是网络专家)配置为使用代理服务器(内部)访问Internet。在我的系统中,这是通过“自动