Skip to content

Commit

Permalink
perf($Starter): support WebClient load balancer
Browse files Browse the repository at this point in the history
  • Loading branch information
johnnymillergh committed Sep 14, 2021
1 parent ebb26ce commit 19dea14
Show file tree
Hide file tree
Showing 21 changed files with 101 additions and 86 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
@RequiredArgsConstructor
public class AuthCenterRemoteApi {
private static final String SERVICE_NAME = "auth-center";
private final WebClient.Builder webClientBuilder;
private final WebClient webClient;

/**
* Gets user by login token.
Expand All @@ -46,8 +46,7 @@ public class AuthCenterRemoteApi {
* @return the user by login token
*/
public Mono<GetUserByLoginTokenResponse> getUserByLoginToken(@PathVariable String loginToken) {
return webClientBuilder
.build()
return this.webClient
.get()
.uri(String.format("http://%s/user-remote-api/users/{loginToken}", SERVICE_NAME), loginToken)
.retrieve()
Expand All @@ -63,15 +62,14 @@ public Mono<GetUserByLoginTokenResponse> getUserByLoginToken(@PathVariable Strin
* @return the role list by user id
*/
public Mono<List<GetRoleListByUserIdSingleResponse>> getRoleListByUserId(@NotNull Long userId) {
return webClientBuilder
.build()
return this.webClient
.get()
.uri(String.format("http://%s/role-remote-api/roles/{userId}", SERVICE_NAME), userId)
.retrieve()
.bodyToMono(ResponseBodyBean.class)
.map(ResponseBodyBean::getData)
.map(data -> JSONUtil.toList(JSONUtil.parseObj(data).getJSONArray("roleList"),
GetRoleListByUserIdSingleResponse.class));
GetRoleListByUserIdSingleResponse.class));
}

/**
Expand All @@ -81,8 +79,7 @@ public Mono<List<GetRoleListByUserIdSingleResponse>> getRoleListByUserId(@NotNul
* @return the response body bean
*/
public Mono<List<GetPermissionListByRoleIdListResponse.Permission>> getPermissionListByRoleIdList(@Valid GetPermissionListByRoleIdListPayload payload) {
return webClientBuilder
.build()
return this.webClient
.get()
.uri(uriBuilder -> uriBuilder
.host("auth-center")
Expand All @@ -105,8 +102,7 @@ public Mono<List<GetPermissionListByRoleIdListResponse.Permission>> getPermissio
*/
@GetMapping("/jwt-remote-api/parse")
public Mono<ParseJwtResponse> parse(@NotBlank String authorization) {
return webClientBuilder
.build()
return this.webClient
.get()
.uri("http://auth-center/jwt-remote-api/parse")
.headers(httpHeaders -> httpHeaders.set(HttpHeaders.AUTHORIZATION, authorization))
Expand Down
2 changes: 2 additions & 0 deletions api-gateway/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ management:

logging:
config: classpath:logback-configuration/logback-${spring.profiles.active}.xml
level:
org.springframework.cloud.client.loadbalancer.reactive: DEBUG

maf:
project-property:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.jmsoftware.maf.reactivespringcloudstarter.configuration.MafConfiguration;
import com.jmsoftware.maf.reactivespringcloudstarter.configuration.MafProjectProperty;
import com.jmsoftware.maf.reactivespringcloudstarter.configuration.WebClientConfiguration;
import com.jmsoftware.maf.reactivespringcloudstarter.configuration.WebFluxConfiguration;
import com.jmsoftware.maf.reactivespringcloudstarter.controller.CommonController;
import com.jmsoftware.maf.reactivespringcloudstarter.filter.AccessLogFilter;
Expand All @@ -15,12 +16,10 @@
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.web.reactive.function.client.WebClient;

import javax.annotation.PostConstruct;

Expand All @@ -39,7 +38,8 @@
})
@Import({
RedisConfiguration.class,
WebFluxConfiguration.class
WebFluxConfiguration.class,
WebClientConfiguration.class
})
public class MafReactiveAutoConfiguration {
@PostConstruct
Expand Down Expand Up @@ -79,11 +79,4 @@ public CommonController commonController(CommonService commonService) {
log.warn("Initial bean: '{}'", CommonController.class.getSimpleName());
return new CommonController(commonService);
}

@Bean
@LoadBalanced
public WebClient.Builder loadBalancedWebClientBuilder() {
log.warn("Initial bean: '{}'", WebClient.Builder.class.getSimpleName());
return WebClient.builder();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;

import javax.annotation.PostConstruct;
Expand All @@ -28,7 +27,6 @@
@Data
@Slf4j
@Validated
@Component
@ConfigurationProperties(prefix = "maf.configuration")
public class MafConfiguration {
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;

import javax.validation.constraints.NotBlank;
Expand All @@ -16,7 +15,6 @@
*/
@Data
@Validated
@Component
@SuppressWarnings("jol")
@ConfigurationProperties(prefix = "maf.project-property")
public class MafProjectProperty {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package com.jmsoftware.maf.reactivespringcloudstarter.configuration;

import io.netty.channel.ChannelOption;
import io.netty.handler.timeout.ReadTimeoutHandler;
import io.netty.handler.timeout.WriteTimeoutHandler;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.http.client.reactive.ReactorResourceFactory;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.netty.resources.ConnectionProvider;
import reactor.netty.resources.LoopResources;

/**
* Description: WebClientConfiguration, change description here.
*
* @author Johnny Miller (锺俊), email: johnnysviva@outlook.com, date: 9/14/2021 3:38 PM
**/
@Slf4j
@RequiredArgsConstructor
public class WebClientConfiguration {
/**
* Load balanced web client builder.
*
* @return the web client builder
* @see
* <a href='https://spring.io/blog/2020/03/25/spring-tips-spring-cloud-loadbalancer#the-code-loadbalanced-code-annotation'>Spring Tips: Spring Cloud Loadbalancer</a>
* @see
* <a href='https://piotrminkowski.com/2018/05/04/reactive-microservices-with-spring-webflux-and-spring-cloud/'>Reactive Microservices with Spring WebFlux and Spring Cloud</a>
*/
@Bean
@LoadBalanced
public WebClient.Builder loadBalancedWebClientBuilder() {
log.warn("Initial bean: '{}'", WebClient.Builder.class.getSimpleName());
return WebClient.builder();
}

@Bean
public ReactorResourceFactory reactorResourceFactory() {
ReactorResourceFactory factory = new ReactorResourceFactory();
factory.setUseGlobalResources(false);
factory.setConnectionProvider(ConnectionProvider.create("web-client-connection-provider"));
factory.setLoopResources(LoopResources.create("web-client-loop"));
return factory;
}

/**
* Configure web client.
*
* @param reactorResourceFactory the reactor resource factory
* @return the web client
* @see
* <a href='https://spring.getdocs.org/en-US/spring-cloud-docs/spring-cloud-commons/cloud-native-applications/spring-cloud-commons:-common-abstractions/loadbalanced-webclient.html#loadbalanced-webclient'>Spring WebFlux <code>WebClient</code> as a Load Balancer Client</a>
*/
@Bean
public WebClient webClient(WebClient.Builder loadBalancedWebClientBuilder,
ReactorResourceFactory reactorResourceFactory) {
return loadBalancedWebClientBuilder
.clientConnector(new ReactorClientHttpConnector(reactorResourceFactory, client -> client
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10)
.option(ChannelOption.TCP_NODELAY, true)
.doOnConnected(doOnConnected -> {
doOnConnected.addHandlerLast(new ReadTimeoutHandler(10));
doOnConnected.addHandlerLast(new WriteTimeoutHandler(10));
})))
.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.jmsoftware.maf.reactivespringcloudstarter.configuration;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.config.ResourceHandlerRegistry;
import org.springframework.web.reactive.config.WebFluxConfigurer;

/**
Expand All @@ -12,17 +10,5 @@
* @author Johnny Miller (锺俊), email: johnnysviva@outlook.com
* @date 2/17/20 5:16 PM
**/
@Configuration
public class WebFluxConfiguration implements WebFluxConfigurer {
/**
* Add resource handlers for serving static resources.
*
* @author Johnny Miller (锺俊), e-mail: johnnysviva@outlook.com
* @date 2/17/20 5:19 PM
* @see ResourceHandlerRegistry registry
*/
// @Override
// public void addResourceHandlers(ResourceHandlerRegistry registry) {
// registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
// }
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
Expand All @@ -21,7 +20,6 @@
* @author Johnny Miller (锺俊), email: johnnysviva@outlook.com, date: 12/24/2020 10:56 AM
**/
@Slf4j
@Component
@RequiredArgsConstructor
public class AccessLogFilter implements WebFilter, Ordered {
private final MafConfiguration mafConfiguration;
Expand All @@ -31,8 +29,8 @@ public class AccessLogFilter implements WebFilter, Ordered {
@SuppressWarnings("NullableProblems")
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
for (String ignoredUrl : mafConfiguration.flattenIgnoredUrls()) {
if (antPathMatcher.match(ignoredUrl, request.getURI().getPath())) {
for (String ignoredUrl : this.mafConfiguration.flattenIgnoredUrls()) {
if (this.antPathMatcher.match(ignoredUrl, request.getURI().getPath())) {
return chain.filter(exchange);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import lombok.val;
import org.springframework.boot.web.context.WebServerInitializedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.InputStreamReader;
Expand All @@ -27,7 +26,6 @@
**/
@Slf4j
@Getter
@Component
@RequiredArgsConstructor
public class IpHelper implements ApplicationListener<WebServerInitializedEvent> {
private static final String DEVELOPMENT_ENVIRONMENT = "development";
Expand All @@ -52,7 +50,7 @@ public void onApplicationEvent(WebServerInitializedEvent event) {
* @date 2019-05-03 16:05
*/
public String getBaseUrl() {
return "http://" + this.getPublicIp() + ":" + serverPort + mafProjectProperty.getContextPath();
return "http://" + this.getPublicIp() + ":" + this.serverPort + this.mafProjectProperty.getContextPath();
}

/**
Expand All @@ -61,7 +59,7 @@ public String getBaseUrl() {
* @return public IP
*/
public String getPublicIp() {
if (mafProjectProperty.getEnvironment().contains(DEVELOPMENT_ENVIRONMENT)) {
if (this.mafProjectProperty.getEnvironment().contains(DEVELOPMENT_ENVIRONMENT)) {
return this.getInternetIp();
}
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

import java.time.Instant;
Expand All @@ -22,7 +21,6 @@
* @author 钟俊(zhongjun), email: zhongjun@toguide.cn, date: 2/10/2021 10:07 AM
**/
@Slf4j
@Component
@RequiredArgsConstructor
public class SpringBootStartupHelper implements DisposableBean {
private static final String LINE_SEPARATOR = System.lineSeparator();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
Expand All @@ -29,7 +28,6 @@
* <a href='https://blog.csdn.net/echizao1839/article/details/102660649'>Spring boot 之 spring-boot-starter-cache (整合 Redis)</a>
**/
@Slf4j
@Configuration
@EnableCaching
@RequiredArgsConstructor
@ConditionalOnClass({RedisConnectionFactory.class})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

import java.util.List;

Expand All @@ -16,7 +15,6 @@
* <a href='https://docs.spring.io/spring-data/redis/docs/current/reference/html/#redis:write-to-master-read-from-replica'>Spring Data Redis - Write to Master, Read from Replica</a>
**/
@Data
@Configuration
@ConfigurationProperties(prefix = "redis")
public class RedisMasterSlaveReplicationProperties {
private RedisInstance master;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import org.springframework.boot.web.context.WebServerInitializedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import java.net.*;
import java.util.Enumeration;
Expand All @@ -22,7 +21,6 @@
**/
@Slf4j
@Getter
@Component
@RequiredArgsConstructor
public class IpHelper implements ApplicationListener<WebServerInitializedEvent> {
private static final String DEVELOPMENT_ENVIRONMENT = "development";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

import java.time.Instant;
Expand All @@ -22,7 +21,6 @@
* @author 钟俊(zhongjun), email: zhongjun@toguide.cn, date: 2/10/2021 10:07 AM
**/
@Slf4j
@Component
@RequiredArgsConstructor
public class SpringBootStartupHelper implements DisposableBean {
private static final String LINE_SEPARATOR = System.lineSeparator();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.multipart.MultipartFile;

Expand All @@ -31,7 +30,6 @@
**/
@Slf4j
@Validated
@Component
@RequiredArgsConstructor
@SuppressWarnings("unused")
public class MinioHelper {
Expand Down
Loading

0 comments on commit 19dea14

Please sign in to comment.