背景:
接口监控功能。对指定的接口进行监控,通过状态、请求时长判断接口是否存在危险及危险等级。公司已有es存储接口调用日志
代码
--pom.xml---------------------------
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
--application.yml------------------------
spring:
data:
elasticsearch:
cluster-name: elasticsearch
cluster-nodes: localhost:9300
--es bean --------------------------------
@AllArgsConstructor
@NoArgsConstructor
@Data
@Document(indexName = "nginx-*-*",type = "doc", shards = 1, replicas = 0)
public class InterfaceMonitoringEntity {
@Id
@Field(type = FieldType.Auto)
private String id;
@JsonProperty("body_bytes_sent")
@Field(type = FieldType.Keyword)
private String bodyBytesSent;
@JsonProperty("time_local")
@Field(type = FieldType.Auto)
private String timeLocal;
@JsonProperty("request_time")
@Field(type = FieldType.Auto)
private double requestTime;
@JsonProperty("upstream_status")
@Field(type = FieldType.Auto)
private String upstreamStatus;
@Field(type = FieldType.Auto)
private String clientRealIp;
}
--es调用--------------------------------
@Component
public interface ElasticsearchRepositoryCRUD extends ElasticsearchRepository<InterfaceMonitoringEntity,String> {
@Query("{\"bool\":{\"must\":[{\"bool\":{\"should\":[{\"match_phrase\":{\"body_bytes_sent\":\"?0\"}},{\"match_phrase\":{\"body_bytes_sent\":\"?1\"}},{\"match_phrase\":{\"body_bytes_sent\":\"?2\"}}]}},{\"range\":{\"time_local.keyword\":{\"from\":\"?3\",\"to\":\"?4\",\"include_lower\":true,\"include_upper\":false}}}]}}")
List<InterfaceMonitoringEntity> findInterfaceMonitoring(String loginUrl, String advertisingUrl, String businessUrl, String beginTime, String endTime);
}
踩坑记录
1.启动报错:elasticseach timeout connexting to [localhost/127.0.0.1:9200]
百度搜索的说法有两种:
1.spring集成es,会默认监听127.0.0.1:9200本地端口,需要改spring:elasticsearch:rest:uris: 实际es地址:9200
2.es的健康监测机制时间太短,所以加长它的时间
management:endpoints:web:exposure:include: ['*']health:elasticsearch:response-timeout: 3s
嗯,我的是读错了配置文件,导致没有读到es配置,走了默认配置
2.kibana能查出数据springboot查不出来
嗯,bean里的type类型写错了,这里@Document(indexName = "nginx--",type = "doc", shards = 1, replicas = 0)
3.match 匹配查出来的数据多了
match对数值型数据是精确匹配,但对文本型数据是模糊匹配(本质是分词,会对传入的字符串进行拆分,拆分出的多个字符串只要有一个能匹配上就会被查出来)
嗯,用match_phrase,短语匹配搜索
4.时间范围搜索不生效
嗯,对时间关键字加上keyword,如time_local.keyword
5.must和should结合使用,查出了所有数据(期望效果是必须满足时间范围,同时满足路径A或路径B...)
嗯,当使用should查询时,如果包含了must或者filter查询,那么should的查询语句就不是或者的意思了,而是有或者没有都行的含义。
例:
查询分数是70或80的男生
image.png
正常人思维写法(错误的)
{
"query": {
"bool": {
"must": [
{"term": {"sex": {"value": "男"}}}
],
"should": [
{"term": { "score": {"value": "70"}}},
{"term": {"score": {"value": "80"}}}
]
}
}
}
正确写法
{
"query": {
"bool": {
"must": [
{"term": {"sex": {"value": "男"}}},
{
"bool": {
"should": [
{"term": {"score": {"value": "70"}}},
{"term": {"score": {"value": "80"}}}
]
}
}
]
}
}
}
或
{
"query": {
"bool": {
"should": [
{
"bool": {
"must": [
{"term": {"sex": "男"}},
{"term": {"score": "70"}}
]
}
},
{
"bool": {
"must": [
{"term": {"sex": "男"}},
{"term": {"score": "80"}}
]
}
}
]
}
}
}