我有一个 Spring Boot 应用程序(最近为 HTTPS + 自签名证书启用了它),它在 Eureka 中注册并在 Eureka 仪表板中可见。

我们有一个 Zuul 过滤器层,它获取用户请求,然后将其传递给 Spring Boot 应用程序。在可以通过 HTTP 访问该应用程序之前,这一切正常。但是,一旦我启用了 HTTPS,zuul 路由就会失败。

这是我的 yaml 文件中的 Zuul 路由配置。 我的 Zuul Route 配置是否应该对启用 HTTPS 的 URL/App 进行任何特殊配置?

zuul:
  routes:
    ms:
       path: /app/**
       stripPrefix: true

    ms:
      ribbon:
        ServerListRefreshInterval: 1000
        ConnectTimeout: 20000
        ReadTimeout: 20000

这是异常堆栈跟踪(显示 Zuul 正在尝试路由到 HTTP URL,而不是 HTTPS url)
Caused by: com.netflix.hystrix.exception.HystrixRuntimeException: msRibbonCommand failed and no fallback available.
    at com.netflix.hystrix.AbstractCommand$20.call(AbstractCommand.java:816) ~[hystrix-core-1.4.0-RC6.jar:na]
    at com.netflix.hystrix.AbstractCommand$20.call(AbstractCommand.java:798) ~[hystrix-core-1.4.0-RC6.jar:na]
    at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$1.onError(OperatorOnErrorResumeNextViaFunction.java:76) ~[rxjava-core-0.20.7.jar:na]
    at rx.internal.operators.OperatorDoOnEach$1.onError(OperatorDoOnEach.java:70) ~[rxjava-core-0.20.7.jar:na]
    at rx.internal.operators.OperatorDoOnEach$1.onError(OperatorDoOnEach.java:70) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$ThrowObservable$1.call(Observable.java:10493) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$ThrowObservable$1.call(Observable.java:10483) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable.unsafeSubscribe(Observable.java:8591) ~[rxjava-core-0.20.7.jar:na]
    at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$1.onError(OperatorOnErrorResumeNextViaFunction.java:77) ~[rxjava-core-0.20.7.jar:na]
    at rx.internal.operators.OperatorMap$1.onError(OperatorMap.java:48) ~[rxjava-core-0.20.7.jar:na]
    at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:318) ~[hystrix-core-1.4.0-RC6.jar:na]
    at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:310) ~[hystrix-core-1.4.0-RC6.jar:na]
    at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable.unsafeSubscribe(Observable.java:8591) ~[rxjava-core-0.20.7.jar:na]
    at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$1.onError(OperatorOnErrorResumeNextViaFunction.java:77) ~[rxjava-core-0.20.7.jar:na]
    at rx.internal.operators.OperatorDoOnEach$1.onError(OperatorDoOnEach.java:70) ~[rxjava-core-0.20.7.jar:na]
    at rx.internal.operators.OperatorMap$1.onError(OperatorMap.java:48) ~[rxjava-core-0.20.7.jar:na]
    at com.netflix.hystrix.AbstractCommand$HystrixObservableTimeoutOperator$3.onError(AbstractCommand.java:995) ~[hystrix-core-1.4.0-RC6.jar:na]
    at rx.internal.operators.OperatorDoOnEach$1.onError(OperatorDoOnEach.java:70) ~[rxjava-core-0.20.7.jar:na]
    at rx.internal.operators.OperatorDoOnEach$1.onError(OperatorDoOnEach.java:70) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$ThrowObservable$1.call(Observable.java:10493) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$ThrowObservable$1.call(Observable.java:10483) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable.unsafeSubscribe(Observable.java:8591) ~[rxjava-core-0.20.7.jar:na]
    at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$1.onError(OperatorOnErrorResumeNextViaFunction.java:77) ~[rxjava-core-0.20.7.jar:na]
    at rx.internal.operators.OperatorMap$1.onError(OperatorMap.java:48) ~[rxjava-core-0.20.7.jar:na]
    at com.netflix.hystrix.HystrixCommand$1.call(HystrixCommand.java:301) ~[hystrix-core-1.4.0-RC6.jar:na]
    at com.netflix.hystrix.HystrixCommand$1.call(HystrixCommand.java:293) ~[hystrix-core-1.4.0-RC6.jar:na]
    at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable.unsafeSubscribe(Observable.java:8591) ~[rxjava-core-0.20.7.jar:na]
    at com.netflix.hystrix.AbstractCommand$1.call(AbstractCommand.java:388) ~[hystrix-core-1.4.0-RC6.jar:na]
    at com.netflix.hystrix.AbstractCommand$1.call(AbstractCommand.java:368) ~[hystrix-core-1.4.0-RC6.jar:na]
    at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable.unsafeSubscribe(Observable.java:8591) ~[rxjava-core-0.20.7.jar:na]
    at com.netflix.hystrix.AbstractCommand$ObservableCommand$1.call(AbstractCommand.java:1097) ~[hystrix-core-1.4.0-RC6.jar:na]
    at com.netflix.hystrix.AbstractCommand$ObservableCommand$1.call(AbstractCommand.java:1093) ~[hystrix-core-1.4.0-RC6.jar:na]
    at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable.subscribe(Observable.java:8680) ~[rxjava-core-0.20.7.jar:na]
    at rx.internal.operators.BlockingOperatorToFuture.toFuture(BlockingOperatorToFuture.java:55) ~[rxjava-core-0.20.7.jar:na]
    at rx.observables.BlockingObservable.toFuture(BlockingObservable.java:420) ~[rxjava-core-0.20.7.jar:na]
    at com.netflix.hystrix.HystrixCommand.queue(HystrixCommand.java:385) ~[hystrix-core-1.4.0-RC6.jar:na]
    at com.netflix.hystrix.HystrixCommand.execute(HystrixCommand.java:339) ~[hystrix-core-1.4.0-RC6.jar:na]
    at org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.forward(RibbonRoutingFilter.java:130) ~[spring-cloud-netflix-core-1.0.0.RELEASE.jar:1.0.0.RELEASE]
    ... 82 common frames omitted
Caused by: com.netflix.client.ClientException: null
    at com.netflix.client.AbstractLoadBalancerAwareClient.executeWithLoadBalancer(AbstractLoadBalancerAwareClient.java:123) ~[ribbon-loadbalancer-2.0-RC13.jar:na]
    at com.netflix.client.AbstractLoadBalancerAwareClient.executeWithLoadBalancer(AbstractLoadBalancerAwareClient.java:81) ~[ribbon-loadbalancer-2.0-RC13.jar:na]
    at org.springframework.cloud.netflix.zuul.filters.route.RibbonCommand.forward(RibbonCommand.java:129) ~[spring-cloud-netflix-core-1.0.0.RELEASE.jar:1.0.0.RELEASE]
    at org.springframework.cloud.netflix.zuul.filters.route.RibbonCommand.run(RibbonCommand.java:103) ~[spring-cloud-netflix-core-1.0.0.RELEASE.jar:1.0.0.RELEASE]
    at org.springframework.cloud.netflix.zuul.filters.route.RibbonCommand.run(RibbonCommand.java:1) ~[spring-cloud-netflix-core-1.0.0.RELEASE.jar:1.0.0.RELEASE]
    at com.netflix.hystrix.HystrixCommand$1.call(HystrixCommand.java:298) ~[hystrix-core-1.4.0-RC6.jar:na]
    ... 125 common frames omitted
Caused by: org.apache.http.client.ClientProtocolException: null
    at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:867) ~[httpclient-4.3.6.jar:4.3.6]
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:115) ~[httpclient-4.3.6.jar:4.3.6]
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57) ~[httpclient-4.3.6.jar:4.3.6]
    at com.sun.jersey.client.apache4.ApacheHttpClient4Handler.handle(ApacheHttpClient4Handler.java:170) ~[jersey-apache-client4-1.11.jar:1.11]
    at com.sun.jersey.api.client.Client.handle(Client.java:648) ~[jersey-client-1.13.jar:1.13]
    at com.sun.jersey.api.client.WebResource.handle(WebResource.java:680) ~[jersey-client-1.13.jar:1.13]
    at com.sun.jersey.api.client.WebResource.access$200(WebResource.java:74) ~[jersey-client-1.13.jar:1.13]
    at com.sun.jersey.api.client.WebResource$Builder.post(WebResource.java:568) ~[jersey-client-1.13.jar:1.13]
    at com.netflix.niws.client.http.RestClient.execute(RestClient.java:621) ~[ribbon-httpclient-2.0-RC13.jar:na]
    at com.netflix.niws.client.http.RestClient.execute(RestClient.java:527) ~[ribbon-httpclient-2.0-RC13.jar:na]
    at com.netflix.niws.client.http.RestClient.execute(RestClient.java:92) ~[ribbon-httpclient-2.0-RC13.jar:na]
    at com.netflix.client.AbstractLoadBalancerAwareClient$1.call(AbstractLoadBalancerAwareClient.java:109) ~[ribbon-loadbalancer-2.0-RC13.jar:na]
    at com.netflix.loadbalancer.reactive.LoadBalancerCommand$3$1.call(LoadBalancerCommand.java:303) ~[ribbon-loadbalancer-2.0-RC13.jar:na]
    at com.netflix.loadbalancer.reactive.LoadBalancerCommand$3$1.call(LoadBalancerCommand.java:287) ~[ribbon-loadbalancer-2.0-RC13.jar:na]
    at rx.internal.operators.OperatorMap$1.onNext(OperatorMap.java:54) ~[rxjava-core-0.20.7.jar:na]
    at rx.internal.util.ScalarSynchronousObservable$1.call(ScalarSynchronousObservable.java:41) ~[rxjava-core-0.20.7.jar:na]
    at rx.internal.util.ScalarSynchronousObservable$1.call(ScalarSynchronousObservable.java:30) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable.unsafeSubscribe(Observable.java:8591) ~[rxjava-core-0.20.7.jar:na]
    at rx.internal.operators.OperatorConcat$ConcatSubscriber.subscribeNext(OperatorConcat.java:163) ~[rxjava-core-0.20.7.jar:na]
    at rx.internal.operators.OperatorConcat$ConcatSubscriber.onNext(OperatorConcat.java:128) ~[rxjava-core-0.20.7.jar:na]
    at rx.internal.operators.OperatorConcat$ConcatSubscriber.onNext(OperatorConcat.java:65) ~[rxjava-core-0.20.7.jar:na]
    at rx.internal.operators.OperatorMap$1.onNext(OperatorMap.java:54) ~[rxjava-core-0.20.7.jar:na]
    at com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:185) ~[ribbon-loadbalancer-2.0-RC13.jar:na]
    at com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:180) ~[ribbon-loadbalancer-2.0-RC13.jar:na]
    at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable.unsafeSubscribe(Observable.java:8591) ~[rxjava-core-0.20.7.jar:na]
    at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber$1.call(OperatorRetryWithPredicate.java:112) ~[rxjava-core-0.20.7.jar:na]
    at rx.schedulers.TrampolineScheduler$InnerCurrentThreadScheduler.enqueue(TrampolineScheduler.java:85) ~[rxjava-core-0.20.7.jar:na]
    at rx.schedulers.TrampolineScheduler$InnerCurrentThreadScheduler.schedule(TrampolineScheduler.java:65) ~[rxjava-core-0.20.7.jar:na]
    at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber.onNext(OperatorRetryWithPredicate.java:77) ~[rxjava-core-0.20.7.jar:na]
    at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber.onNext(OperatorRetryWithPredicate.java:45) ~[rxjava-core-0.20.7.jar:na]
    at rx.internal.util.ScalarSynchronousObservable$1.call(ScalarSynchronousObservable.java:41) ~[rxjava-core-0.20.7.jar:na]
    at rx.internal.util.ScalarSynchronousObservable$1.call(ScalarSynchronousObservable.java:30) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:173) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable$2.call(Observable.java:166) ~[rxjava-core-0.20.7.jar:na]
    at rx.Observable.subscribe(Observable.java:8680) ~[rxjava-core-0.20.7.jar:na]
    at rx.observables.BlockingObservable.blockForSingle(BlockingObservable.java:452) ~[rxjava-core-0.20.7.jar:na]
    at rx.observables.BlockingObservable.single(BlockingObservable.java:348) ~[rxjava-core-0.20.7.jar:na]
    at com.netflix.client.AbstractLoadBalancerAwareClient.executeWithLoadBalancer(AbstractLoadBalancerAwareClient.java:102) ~[ribbon-loadbalancer-2.0-RC13.jar:na]
    ... 130 common frames omitted
Caused by: org.apache.http.ProtocolException: The server failed to respond with a valid HTTP response
    at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:151) ~[httpclient-4.3.6.jar:4.3.6]
    at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:57) ~[httpclient-4.3.6.jar:4.3.6]
    at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:261) ~[httpcore-4.4.jar:4.4]
    at org.apache.http.impl.AbstractHttpClientConnection.receiveResponseHeader(AbstractHttpClientConnection.java:283) ~[httpcore-4.4.jar:4.4]
    at org.apache.http.impl.conn.DefaultClientConnection.receiveResponseHeader(DefaultClientConnection.java:251) ~[httpclient-4.3.6.jar:4.3.6]
    at org.apache.http.impl.conn.AbstractClientConnAdapter.receiveResponseHeader(AbstractClientConnAdapter.java:223) ~[httpclient-4.3.6.jar:4.3.6]
    at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:272) ~[httpcore-4.4.jar:4.4]
    at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:124) ~[httpcore-4.4.jar:4.4]
    at org.apache.http.impl.client.DefaultRequestDirector.tryExecute(DefaultRequestDirector.java:685) ~[httpclient-4.3.6.jar:4.3.6]
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:487) ~[httpclient-4.3.6.jar:4.3.6]
    at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:863) ~[httpclient-4.3.6.jar:4.3.6]

更新 :
添加 isRibbon 安全属性后,此错误消失了,现在我有了 new error

最佳答案

自从我玩这个已经有一段时间了,因为由于无法通过代理传递用户证书的限制,我们最终无法使用它。但是,您 asked for my help ,所以我会尝试分享我所做的工作。

我能够在充当边缘服务器的 ZUUL 和后端服务之间运行 2 向 SSL,同时在它们自己的 VM 中运行(即在每个服务上执行 mvn spring-boot:run)。

这是我的 Zuul Conifg:

info:
  component: Zuul Server

endpoints:
  restart:
    enabled: true
  shutdown:
    enabled: true
  health:
    sensitive: false

zuul:
  routes:
    ui: /**
    api: /api/**

logging:
  level:
    ROOT: INFO
    org.springframework.web: DEBUG

server:
  port: 8443
  ssl:
      key-store: classpath:dev/localhost.jks
      key-store-password: yourpassword
      keyStoreType: JKS
      keyAlias: localhost
      clientAuth: want
      trust-store: classpath:dev/localhost.jks

ribbon:
    IsSecure: true

边缘服务器本身没有什么有趣的:
@SpringBootApplication
@Controller
@EnableAutoConfiguration
@EnableZuulProxy
public class ZuulEdgeServer {
    public static void main(String[] args) {
        new SpringApplicationBuilder(ZuulEdgeServer.class).web(true).run(args);
    }
}

现在在我的其他服务中,我的 application.yml 文件中有以下内容:
server:
  port: 8444
  ssl:
      key-store: classpath:dev/localhost.jks
      key-store-password: yourpassword
      keyStoreType: JKS
      keyAlias: localhost
      clientAuth: want
      trust-store: classpath:dev/localhost.jks

eureka:
  instance:
    nonSecurePortEnabled: false
    securePortEnabled: true
    securePort: ${server.port}
    homePageUrl: https://${eureka.instance.hostname}:${server.port}/
    secureVirtualHostName: ${spring.application.name}

我的 Eureka Config 没有太多,但以防万一:
server:
  port: 8761

eureka:
  client:
    registerWithEureka: false
    fetchRegistry: false
  server:
    waitTimeInMsWhenSyncEmpty: 0

我的 bootstrap.yml 在大多数应用程序中看起来像这样:
spring:
  application:
    name: eureka
  cloud:
    config:
      uri: ${vcap.services.${PREFIX:}configserver.credentials.uri:http://user:password@localhost:8888}

我主要发现在同一容器中运行应用程序时,我需要其中的 spring.application.name 来解决冲突。

如果我没记错的话,上面的重要部分是:

zuul 配置中的
  • ribbon.isSecure = true
  • eureka.instance.securePortEnabled = true 和后端服务中的 securePort

  • 我不记得 secureVirtualHostName 是否重要。

    希望这些信息可以帮助你!

    关于netflix - Zuul 路由到 HTTPS url 时出错,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32478146/

    10-13 05:14