首頁 > 軟體

如何從eureka獲取服務的ip和埠號進行Http的呼叫

2022-03-09 13:00:15

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);
}

以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。 


IT145.com E-mail:sddin#qq.com