如何从eureka获取服务的ip和端口号进行Http的调用
目录
- eureka获取服务ip和端口号进行Http调用
- eureka页面中显示ip+端口
eureka获取服务ip和端口号进行Http调用
我告诉你们为啥我要先从eureka首先获取 goods的服务ip, 在用ip的方式使用http调用goods的服务.
因为公司的规定, 不让我们用Feigin. 我TMD的都震惊了, 我都不知道为啥. 我也不想写同事的ip地址, 做配置, 因为都去eureka里面注册了, 所以就这样调用了, 真是蛋疼. 这种微服务, 这种奇葩的方式..
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 配置有个问题, 就是一个服务挂了之后, 需要很长的时间才能去掉. 然后请求到达网关之后还是去了已经关闭的服务, 就很蛋疼了. 需要配置一个参数.
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+端口
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 中获取
@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); }
以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。
赞 (0)