聊聊springboot jest autoconfigure

go4it發表於2019-04-20

本文主要研究一下springboot jest autoconfigure

JestProperties

spring-boot-autoconfigure-2.1.4.RELEASE-sources.jar!/org/springframework/boot/autoconfigure/elasticsearch/jest/JestProperties.java

@ConfigurationProperties(prefix = "spring.elasticsearch.jest")
public class JestProperties {

	/**
	 * Comma-separated list of the Elasticsearch instances to use.
	 */
	private List<String> uris = new ArrayList<>(
			Collections.singletonList("http://localhost:9200"));

	/**
	 * Login username.
	 */
	private String username;

	/**
	 * Login password.
	 */
	private String password;

	/**
	 * Whether to enable connection requests from multiple execution threads.
	 */
	private boolean multiThreaded = true;

	/**
	 * Connection timeout.
	 */
	private Duration connectionTimeout = Duration.ofSeconds(3);

	/**
	 * Read timeout.
	 */
	private Duration readTimeout = Duration.ofSeconds(3);

	/**
	 * Proxy settings.
	 */
	private final Proxy proxy = new Proxy();

	//......

	public static class Proxy {

		/**
		 * Proxy host the HTTP client should use.
		 */
		private String host;

		/**
		 * Proxy port the HTTP client should use.
		 */
		private Integer port;

		public String getHost() {
			return this.host;
		}

		public void setHost(String host) {
			this.host = host;
		}

		public Integer getPort() {
			return this.port;
		}

		public void setPort(Integer port) {
			this.port = port;
		}

	}
}
複製程式碼
  • JestProperties提供了uris、username、password、multiThreaded(預設true)、connectionTimeout(預設3s)、readTimeout(預設3s)、proxy的配置

JestAutoConfiguration

spring-boot-autoconfigure-2.1.4.RELEASE-sources.jar!/org/springframework/boot/autoconfigure/elasticsearch/jest/JestAutoConfiguration.java

@Configuration
@ConditionalOnClass(JestClient.class)
@EnableConfigurationProperties(JestProperties.class)
@AutoConfigureAfter(GsonAutoConfiguration.class)
public class JestAutoConfiguration {

	private final JestProperties properties;

	private final ObjectProvider<Gson> gsonProvider;

	private final ObjectProvider<HttpClientConfigBuilderCustomizer> builderCustomizers;

	public JestAutoConfiguration(JestProperties properties, ObjectProvider<Gson> gson,
			ObjectProvider<HttpClientConfigBuilderCustomizer> builderCustomizers) {
		this.properties = properties;
		this.gsonProvider = gson;
		this.builderCustomizers = builderCustomizers;
	}

	@Bean(destroyMethod = "shutdownClient")
	@ConditionalOnMissingBean
	public JestClient jestClient() {
		JestClientFactory factory = new JestClientFactory();
		factory.setHttpClientConfig(createHttpClientConfig());
		return factory.getObject();
	}

	protected HttpClientConfig createHttpClientConfig() {
		HttpClientConfig.Builder builder = new HttpClientConfig.Builder(
				this.properties.getUris());
		PropertyMapper map = PropertyMapper.get();
		map.from(this.properties::getUsername).whenHasText().to((username) -> builder
				.defaultCredentials(username, this.properties.getPassword()));
		Proxy proxy = this.properties.getProxy();
		map.from(proxy::getHost).whenHasText().to((host) -> {
			Assert.notNull(proxy.getPort(), "Proxy port must not be null");
			builder.proxy(new HttpHost(host, proxy.getPort()));
		});
		map.from(this.gsonProvider::getIfUnique).whenNonNull().to(builder::gson);
		map.from(this.properties::isMultiThreaded).to(builder::multiThreaded);
		map.from(this.properties::getConnectionTimeout).whenNonNull()
				.asInt(Duration::toMillis).to(builder::connTimeout);
		map.from(this.properties::getReadTimeout).whenNonNull().asInt(Duration::toMillis)
				.to(builder::readTimeout);
		customize(builder);
		return builder.build();
	}

	private void customize(HttpClientConfig.Builder builder) {
		this.builderCustomizers.orderedStream()
				.forEach((customizer) -> customizer.customize(builder));
	}

}
複製程式碼
  • JestAutoConfiguration在沒有jestClient的bean情況下會通過JestProperties建立了HttpClientConfig,然後使用JestClientFactory建立JestClient,同時標記其destroyMethod為shutdownClient方法

JestClientFactory

jest-6.3.1-sources.jar!/io/searchbox/client/JestClientFactory.java

public class JestClientFactory {

    final static Logger log = LoggerFactory.getLogger(JestClientFactory.class);
    private HttpClientConfig httpClientConfig;

    public JestClient getObject() {
        JestHttpClient client = new JestHttpClient();

        if (httpClientConfig == null) {
            log.debug("There is no configuration to create http client. Going to create simple client with default values");
            httpClientConfig = new HttpClientConfig.Builder("http://localhost:9200").build();
        }

        client.setRequestCompressionEnabled(httpClientConfig.isRequestCompressionEnabled());
        client.setServers(httpClientConfig.getServerList());
        final HttpClientConnectionManager connectionManager = getConnectionManager();
        final NHttpClientConnectionManager asyncConnectionManager = getAsyncConnectionManager();
        client.setHttpClient(createHttpClient(connectionManager));
        client.setAsyncClient(createAsyncHttpClient(asyncConnectionManager));

        // set custom gson instance
        Gson gson = httpClientConfig.getGson();
        if (gson == null) {
            log.info("Using default GSON instance");
        } else {
            log.info("Using custom GSON instance");
            client.setGson(gson);
        }

        // set discovery (should be set after setting the httpClient on jestClient)
        if (httpClientConfig.isDiscoveryEnabled()) {
            log.info("Node Discovery enabled...");
            if (!Strings.isNullOrEmpty(httpClientConfig.getDiscoveryFilter())) {
                log.info("Node Discovery filtering nodes on \"{}\"", httpClientConfig.getDiscoveryFilter());
            }
            NodeChecker nodeChecker = createNodeChecker(client, httpClientConfig);
            client.setNodeChecker(nodeChecker);
            nodeChecker.startAsync();
            nodeChecker.awaitRunning();
        } else {
            log.info("Node Discovery disabled...");
        }

        // schedule idle connection reaping if configured
        if (httpClientConfig.getMaxConnectionIdleTime() > 0) {
            log.info("Idle connection reaping enabled...");

            IdleConnectionReaper reaper = new IdleConnectionReaper(httpClientConfig, new HttpReapableConnectionManager(connectionManager, asyncConnectionManager));
            client.setIdleConnectionReaper(reaper);
            reaper.startAsync();
            reaper.awaitRunning();
        } else {
            log.info("Idle connection reaping disabled...");
        }

        Set<HttpHost> preemptiveAuthTargetHosts = httpClientConfig.getPreemptiveAuthTargetHosts();
        if (!preemptiveAuthTargetHosts.isEmpty()) {
            log.info("Authentication cache set for preemptive authentication");
            client.setHttpClientContextTemplate(createPreemptiveAuthContext(preemptiveAuthTargetHosts));
        }

        client.setElasticsearchVersion(httpClientConfig.getElasticsearchVersion());

        return client;
    }

    public void setHttpClientConfig(HttpClientConfig httpClientConfig) {
        this.httpClientConfig = httpClientConfig;
    }

    //......

}
複製程式碼
  • JestClientFactory的getObject方法首先建立JestHttpClient,然後設定HttpClient、AsyncClient
  • 如果isDiscoveryEnabled為true則會建立NodeChecker並執行Node Discovery
  • 如果maxConnectionIdleTime大於0則會建立IdleConnectionReaper,進行Idle connection reaping

小結

  • JestProperties提供了uris、username、password、multiThreaded(預設true)、connectionTimeout(預設3s)、readTimeout(預設3s)、proxy的配置
  • JestAutoConfiguration在沒有jestClient的bean情況下會通過JestProperties建立了HttpClientConfig,然後使用JestClientFactory建立JestClient,同時標記其destroyMethod為shutdownClient方法
  • JestClientFactory的getObject方法首先建立JestHttpClient,然後設定HttpClient、AsyncClient;如果isDiscoveryEnabled為true則會建立NodeChecker並執行Node Discovery;如果maxConnectionIdleTime大於0則會建立IdleConnectionReaper,進行Idle connection reaping

doc

相關文章