eureka获取服务ip和端口号进行Http调用
我告诉你们为啥我要先从eureka首先获取 goods的服务ip, 在用ip的方式使用http调用goods的服务.
因为公司的规定, 不让我们用Feigin. 我TMD的都震惊了, 我都不知道为啥. 我也不想写同事的ip地址, 做配置, 因为都去eureka里面注册了, 所以就这样调用了, 真是蛋疼. 这种微服务, 这种奇葩的方式..
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
package com.util; import com.alibaba.fastjson.JSON; import com.curefun.attendance.appclient.vo.ApplyListVO; import lombok.extern.slf4j.Slf4j; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import org.apache.commons.lang3.StringUtils; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * eureka的工具类 * * @author zhangke * @time 2019年12月5日18:11:12 */ @Slf4j public class EurekaUtil { /** * 解析eureka的返回数据 */ private static Pattern PATTERN_URL = Pattern.compile( "<homePageUrl>(.+?)</homePageUrl>" ); /** * IP的缓存 */ private static ConcurrentHashMap<String, List<String>> IP_CACHE = new ConcurrentHashMap<>(); /** * 缓存的名字 */ private final static String IP_NAME = "goodsIp" ; /** * 获取服务的所有地址(注册在 eureka server 上的服务) * * @param eurekaIp * @return */ public static List<String> getAllServiceAddr(String eurekaIp) { //先查询缓存 List<String> list = IP_CACHE.get(IP_NAME); if (list != null && list.size() > 0 ) { return list; } String serviceName = "GOODS" ; String url = eurekaIp + "apps/" + serviceName; OkHttpClient okHttpClient = new OkHttpClient().newBuilder().connectTimeout( 2 , TimeUnit.SECONDS).build(); Request request = new Request.Builder() //请求接口 如果需要传参拼接到接口后面 .url(url) .addHeader( "Content-Type" , "application/json" ) .addHeader( "Accept" , "application/xml" ) .get() .build(); Response response = null ; List<String> result = new ArrayList<>(); try { response = okHttpClient.newCall(request).execute(); if (response.isSuccessful()) { String responseContent = response.body().string(); Matcher matcher = PATTERN_URL.matcher(responseContent); while (matcher.find()) { String homepage = matcher.group( 1 ).trim(); result.add(homepage); } } } catch (IOException e) { log.error( "从eureka中查询GOODS的服务实例出错了.原因是 {}" , e.getMessage()); return result; } IP_CACHE.put(IP_NAME, result); return result; } /** * GET请求获取列表数据, 同步请求 * * @param ip * @param userId * @param state * @param pageNo * @param pageSize * @param key * @return */ public static List<ApplyListVO> getProductList(String ip, String userId, Integer state, Integer pageNo, Integer pageSize, String key) { if (StringUtils.isBlank(ip)) { return Collections.emptyList(); } StringBuilder sb = new StringBuilder(ip); sb.append( "goods/apply/getStuGoodsApplyList?user_id=" ).append(userId); sb.append( "&state=" ).append(state).append( "&pageNo=" ).append(pageNo); sb.append( "&pageSize=" ).append(pageSize); if (StringUtils.isNotBlank(key)) { sb.append( "&key=" ).append(key); } long millis = System.currentTimeMillis(); Request request = new Request.Builder().url(sb.toString()).get().build(); OkHttpClient okHttpClient = new OkHttpClient().newBuilder().connectTimeout( 2 , TimeUnit.SECONDS).build(); try { Response response = okHttpClient.newCall(request).execute(); if (response.isSuccessful()) { String string = response.body().string(); //json的转换.换成我需要的实体对象,为空的不返回null, 一个小技巧 List<ApplyListVO> applyListVOS = JSON.parseArray(string, ApplyListVO. class ); if (applyListVOS == null ) { applyListVOS = Collections.emptyList(); } long millis2 = System.currentTimeMillis(); log.info( "从周X那里查询到物资的列表,请求的url是:{},返回结果是:{}" , sb.toString(), applyListVOS); log.info( "查询的耗时是(微秒):{}" , (millis2 - millis)); return applyListVOS; } else { return Collections.emptyList(); } } catch (Exception e) { log.error( "从周X的接口中查询List信息出错了.原因是 {}" , e.getMessage()); return Collections.emptyList(); } } } |
这样就可以很方便的调用了,
做微服务的一定要协调好各个组件的关系, 不然很容易两个人要对不同的接口, 很麻烦.
对了, 现在我们的eureka 配置有个问题, 就是一个服务挂了之后, 需要很长的时间才能去掉. 然后请求到达网关之后还是去了已经关闭的服务, 就很蛋疼了. 需要配置一个参数.
1
2
3
4
5
6
|
eureka: server: #配置属性,但由于 Eureka 自我保护模式以及心跳周期长的原因, #经常会遇到 Eureka Server 不剔除已关停的节点的问题 enable-self-preservation: false # 设为false,关闭自我保护 eviction-interval-timer-in-ms: 5000 # 清理间隔(单位毫秒,默认是60*1000)启用主动失效, #并且每次主动失效检测间隔为3s |
先要关闭自我保护 enable-self-preservation: false
eviction-interval-timer-in-ms 启用主动失效,并且每次主动失效检测间隔为5s
Eureka Server会定时(间隔值是eureka.server.eviction-interval-timer-in-ms,默认值为0,默认情况不删除实例)进行检查,如果发现实例在在一定时间(此值由客户端设置的eureka.instance.lease-expiration-duration-in-seconds定义,默认值为90s)内没有收到心跳,则会注销此实例。
现在的eureka的配置 已经改过来了。
eureka页面中显示ip+端口
1
2
3
4
5
6
|
eureka: instance: prefer-ip-address: true instance-id: ${spring.cloud.client.ip-address}:${server.port} # spring.cloud.client.ip-address 为 2.x 版本,1.x 版本为 spring.cloud.client.ipAddress # ${spring.cloud.client.ip-address} 这个值从 org.springframework.cloud.client.HostInfoEnvironmentPostProcessor 中获取 |
1
2
3
4
5
6
7
8
9
10
11
|
@Override public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { InetUtils.HostInfo hostInfo = getFirstNonLoopbackHostInfo(environment); LinkedHashMap<String, Object> map = new LinkedHashMap<>(); map.put( "spring.cloud.client.hostname" , hostInfo.getHostname()); map.put( "spring.cloud.client.ip-address" , hostInfo.getIpAddress()); MapPropertySource propertySource = new MapPropertySource( "springCloudClientHostInfo" , map); environment.getPropertySources().addLast(propertySource); } |
以上为个人经验,希望能给大家一个参考,也希望大家多多支持服务器之家。
原文链接:https://changhe.blog.csdn.net/article/details/103432215