在Spring Cloud Gateway中通过service-name同步调用微服务

wnvonmuf  于 2024-01-05  发布在  Spring
关注(0)|答案(1)|浏览(182)

我有一个云API网关相关的实现参考this构建。
在那里,我通过AuthenticationFilter调用该网关内的身份验证服务。

  • 云网关-服务:7130
  • 咨询服务:9898
  • 联系电话:0712 - 8888888
    application.yml
  1. server:
  2. port: 7130
  3. eureka:
  4. client:
  5. serviceUrl:
  6. defaultZone: http://localhost:8083/eureka
  7. spring:
  8. application:
  9. name: CLOUD-GATEWAY-SERVICE
  10. cloud:
  11. gateway:
  12. routes:
  13. - id: mtoken-exchange-service
  14. uri: lb://EXCHANGE-SERVICE
  15. predicates:
  16. - Path=/employee/**
  17. filters:
  18. - name: AuthenticationFilter
  19. args:
  20. role: ROLE_ADMIN
  21. - id: mtokens-authentication-service
  22. uri: lb://AUTHENTICATION-SERVICE
  23. predicates:
  24. - Path=/auth/**

字符串

  • Sping Boot 版本:3.1.1
  • Spring Cloud版本:2022.0.3
  • Java版本:17

目前,我使用RestTemplate来实现这一点;但我也尝试了Feign和Webclient。
当我使用下面提到的主机和端口访问时,它可以工作。(这里我使用它而没有@LoadBalanced注解)

  1. template.getForObject("http://localhost:7130/auth/validate?token=<Bearer_Token>&role=ROLE_ADMIN", Boolean.class);
  2. template.getForObject("http://localhost:9898/auth/validate?token=<Bearer_Token>&role=ROLE_ADMIN", Boolean.class);


但是,当我尝试使用下面提到的服务名称访问时,它会因未知主机异常而失败。

  1. template.getForObject("http://CLOUD-GATEWAY-SERVICE/auth/validate?token=<Bearer_Token>&role=ROLE_ADMIN", Boolean.class);
  2. template.getForObject("http://AUTHENTICATION-SERVICE/auth/validate?token=<Bearer_Token>&role=ROLE_ADMIN", Boolean.class);


然后,正如在这篇[https://stackoverflow.com/questions/37159662/microservices-resttemplate-unknownessexception]文章中提到的,我用@LoadBalanced注解了RestTemplate。但在那之后,它抛出了下面的错误。当我使用Feign或Webclient同步调用servces时,也遇到了同样的问题。

  1. 2023-10-30T05:19:59.789+05:30 INFO 10856 --- [ main] c.javatechie.SwiggyGatewayApplication : Started SwiggyGatewayApplication in 3.752 seconds (process running for 4.03)
  2. java.lang.IllegalStateException: block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-nio-3
  3. at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:83)
  4. at reactor.core.publisher.Mono.block(Mono.java:1710)
  5. at org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient.choose(BlockingLoadBalancerClient.java:163)
  6. at org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient.execute(BlockingLoadBalancerClient.java:74)
  7. at org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor.intercept(LoadBalancerInterceptor.java:56)
  8. at org.springframework.http.client.InterceptingClientHttpRequest$InterceptingRequestExecution.execute(InterceptingClientHttpRequest.java:87)
  9. at org.springframework.http.client.InterceptingClientHttpRequest.executeInternal(InterceptingClientHttpRequest.java:71)
  10. at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48)
  11. at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:66)
  12. at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:862)
  13. at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:764)
  14. at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:378)
  15. at com.javatechie.filter.AuthenticationFilter.lambda$apply$0(AuthenticationFilter.java:42)

RestTemplateConfiguration

  1. @Configuration
  2. class RestTemplateConfiguration {
  3. @Bean
  4. @LoadBalanced
  5. public RestTemplate restTemplate() {
  6. return new RestTemplate(new BufferingClientHttpRequestFactory(new HttpComponentsClientHttpRequestFactory()));
  7. }
  8. }


在这个类似云网关的应用程序中,是否可以使用RestTemplate或Feignclient或Webclient等通过服务名称同步调用服务?

0wi1tuuw

0wi1tuuw1#

最后,我注意到,由于WebFlux是响应式的,我需要这样做。所以,我做了以下更改,现在它工作得很好。

1.添加负载均衡依赖

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-loadbalancer</artifactId>
  4. </dependency>

字符串

2.添加WebClient配置。

  1. @Configuration
  2. class WebClientConfig {
  3. @Bean
  4. @LoadBalanced
  5. public WebClient.Builder loadBalancedWebClientBuilder() {
  6. return WebClient.builder();
  7. }
  8. }

3.通过WebClient使用service-name调用外部微服务,如下所示

  1. import jakarta.ws.rs.core.HttpHeaders;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.cloud.gateway.filter.GatewayFilter;
  4. import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
  5. import org.springframework.stereotype.Component;
  6. import org.springframework.web.reactive.function.client.WebClient;
  7. @Component
  8. public class AuthenticationFilter extends AbstractGatewayFilterFactory<AuthenticationFilter.Config> {
  9. private WebClient webClient;
  10. public AuthenticationFilter() {
  11. super(Config.class);
  12. }
  13. @Autowired
  14. public AuthenticationFilter(WebClient.Builder webClientBuilder) {
  15. super(Config.class);
  16. this.webClient = webClientBuilder.build();
  17. }
  18. @Override
  19. public Config newConfig() {
  20. return new Config();
  21. }
  22. @Override
  23. public GatewayFilter apply(Config config) {
  24. return (exchange, chain) -> {
  25. String authHeader = exchange.getRequest().getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
  26. if (authHeader != null && authHeader.startsWith("Bearer ")) {
  27. authHeader = authHeader.substring(7);
  28. }
  29. String expectedRole = config.role;
  30. String authServiceUrl = "http://YOUR-APPLICATION-SERVICE-NAME";
  31. return this.webClient
  32. .get()
  33. .uri(authServiceUrl + "/auth/doOp?token=" + authHeader + "&role=" + expectedRole)
  34. .retrieve()
  35. .bodyToMono(Boolean.class)
  36. .flatMap(response -> {
  37. // Do further operations on microservice response if needed
  38. return chain.filter(exchange);
  39. })
  40. .onErrorResume(throwable -> {
  41. throw new RuntimeException("un authorized access to application");
  42. });
  43. };
  44. }
  45. public static class Config {
  46. private String role;
  47. public String getRole() {
  48. return role;
  49. }
  50. public void setRole(String role) {
  51. this.role = role;
  52. }
  53. }
  54. }


我在这里分享了一个示例项目:https://github.com/namalfernandolk/cloud-gateway-demo.git

展开查看全部

相关问题