zoukankan      html  css  js  c++  java
  • 公司ES升级带来的坑怎么填?

    前言

    公司的ES最近需要全部进行升级,目的是方便维护和统一管理。以前的版本不统一,这次准备统一升级到一个固定的版本。

    同时还会给ES加上权限控制,虽然都是部署在内网,为了防止误操作,加上权限还是有必要的。

    带来的问题就是我这边的程序得改了,目前用的是Spring Data Elasticsearch来操作ES。

    问题

    首先版本从5.x升级到6.4.0,我这边用的Spring Boot是2.0.1版本,这块是兼容的,没有影响。唯一导致我这边要改动的就是权限这块。

    在Spring Boot的文档中,提供了三种操作ES的框架,有两种是走Http协议的,也就是操作9200端口,是可以直接支持用户名和密码配置的。

    elasticsearch-rest-client

    spring.elasticsearch.rest.uris=http://search.example.com:9200
    spring.elasticsearch.rest.username=user
    spring.elasticsearch.rest.password=secret
    

    JestClient:

    spring.elasticsearch.jest.uris=http://search.example.com:9200
    spring.elasticsearch.jest.read-timeout=10000
    spring.elasticsearch.jest.username=user
    spring.elasticsearch.jest.password=secret
    

    偏偏我用的是第三种Spring Data Elasticsearch,没有认证信息的配置,但是有一个扩展属性properties

    @ConfigurationProperties(prefix = "spring.data.elasticsearch")
    public class ElasticsearchProperties {
    
    	/**
    	 * Elasticsearch cluster name.
    	 */
    	private String clusterName = "elasticsearch";
    
    	/**
    	 * Comma-separated list of cluster node addresses.
    	 */
    	private String clusterNodes;
    
    	/**
    	 * Additional properties used to configure the client.
    	 */
    	private Map<String, String> properties = new HashMap<>();
    }
    

    在TransportClientFactoryBean中初始化Settings的时候,会取properties中值

    private Settings settings() {
    	if (properties != null) {
    			Settings.Builder builder = Settings.builder();
    
    			properties.forEach((key, value) -> {
    				builder.put(key.toString(), value.toString());
    			});
    
    			return builder.build();
    	}
    	return Settings.builder()
    			.put("cluster.name", clusterName)
    			.put("client.transport.sniff", clientTransportSniff)
    			.put("client.transport.ignore_cluster_name", clientIgnoreClusterName)
    			.put("client.transport.ping_timeout", clientPingTimeout)
    			.put("client.transport.nodes_sampler_interval", clientNodesSamplerInterval)
    			.build();
    }
    

    于是我在properties 中加上认证信息的配置发现还是不行,因为这个全新认证是扩展的,需要增加x-pack-transport才行。

    <!-- add the x-pack jar as a dependency -->
    <dependency>
          <groupId>org.elasticsearch.client</groupId>
          <artifactId>x-pack-transport</artifactId>
          <version>6.4.2</version>
    </dependency>
    

    恶心的是中央仓库没有,还得指定仓库:

    <repositories>
          <!-- add the elasticsearch repo -->
          <repository>
             <id>elasticsearch-releases</id>
             <url>https://artifacts.elastic.co/maven</url>
             <releases>
                <enabled>true</enabled>
             </releases>
             <snapshots>
                <enabled>false</enabled>
             </snapshots>
          </repository>
    </repositories>
    

    当你加入这些依赖之后你会发现,还是不能采用spring.data.elasticsearch.xxx这种方式直接配置认证信息,因为底层不是用的xpack扩展的client构造的, 用的是PreBuiltTransportClient,看下代码:

    protected void buildClient() throws Exception {
    
    	client = new PreBuiltTransportClient(settings());
    		
    	clusterNodes.stream() //
    			.peek(it -> logger.info("Adding transport node : " + it.toString())) //
    			.forEach(client::addTransportAddress);
    		
    	client.connectedNodes();
    }
    

    最终还是放弃了自动配置的方式,自己手动配置定义Client来支持权限认证。

    @Bean
    public Client client() {
    	try {
    		Settings.Builder builder = Settings.builder()
    				.put("client.transport.ping_timeout", pingTimeout)
    				.put("cluster.name", clusterName)
    				.put("xpack.security.user", username + ":" + password)
    				.put("xpack.security.transport.ssl.enabled", "true")
    				.put("xpack.security.transport.ssl.truststore.path", keystorePath)
    				.put("xpack.security.transport.ssl.keystore.path", keystorePath)
    				.put("xpack.security.transport.ssl.verification_mode", "certificate");
    		Settings settings = builder.build();
    		String[] nodes = clusterNodes.split(",");
    		TransportAddress[] addressArray = new TransportAddress[nodes.length];
    		for (int i = 0; i < nodes.length; i++) {
    			String[] nodeArray = nodes[i].split(":");
    			addressArray[i] = new TransportAddress(InetAddress.getByName(nodeArray[0]), Integer.parseInt(nodeArray[1]));
    		}
    		return new PreBuiltXPackTransportClient(settings).addTransportAddresses(addressArray);
    	} catch (Exception e) {
    		logger.error("初始化ESClient异常", e);
    	}
    	return null;
    }
    
    • username:用户名
    • password:密码
    • keystorePath:证书地址,会有一个.p12的证书

    不知大家发现没有,看上去我们自定义的代码也没什么特别,关键点在于PreBuiltXPackTransportClient,框架中用的是PreBuiltTransportClient,所以我们才需要自定义。

    配置完了你会发现还是不行,各种jar冲突,Spring Boot的版本还需要升级,于是只能升到目前最新的2.1.0版本。升级完之后又有坑了。

    升级之前Data中的注解,要指定类型,keyword变成了Keyword

    @Field(type=FieldType.Keyword)
    

    ES的这个Field注解没有别名映射的属性,就是我es中存的u_name, 实体类中写的是username,这个确实不太方便,像data mongodb中都有这样的功能,有知道怎么解决的要给我留言哈,学习下。

    然后就是security的一个坑了,升级之后security版本也升级了,下载下来的jar包用不了,错误如下:

    err.png

    一开始以为是网络原因,没下载完,然后重新删了再下,试了5次还是不行,最后没办法,我手动下载了spring-security-config这个包,替换了本地仓库的jar。

    下载地址:https://mvnrepository.com/artifact/org.springframework.security/spring-security-config/5.1.1.RELEASE

    以上就是这次升级过程中踩过的坑,分享给大家。这次只是客户端这块的改变,至于ES是怎么开启权限认证的我这边就不做讲解了,因为这块不是我弄的,所以我也不熟悉,等后面有机会我也去研究研究可以给大家分享,反正是基于xpack搞的。

    欢迎加入我的知识星球,一起交流技术,免费学习猿天地的课程(http://cxytiandi.com/course)

    微信扫码加入猿天地知识星球

    猿天地

  • 相关阅读:
    Sublime Text3 无法调出package controll问题
    Python标准库-enumerate用法
    设计模式学习-简单工厂模式(python3)
    【IO流】java中文件路径(相对路径、绝对路径)相关类及方法
    nginx安装教程(详细)
    nginx -stream(tcp连接)反向代理配置 实现代理mysql以及文件上传
    【单例模式】懒汉式的线程安全问题 volatile的作用
    jsonp协议 java服务端、JQuery客户端 简单实现原理
    MyBatis原理,Spring、SpringBoot整合MyBatis
    【JavaSE】运行时类型信息(RTTI、反射)
  • 原文地址:https://www.cnblogs.com/yinjihuan/p/10470804.html
Copyright © 2011-2022 走看看