由於公司一些老的項目要對接新項目,而新項目是springCloud框架,需要在老項目里面集成下Eureka,(當然,如果新項目提供IP的調用方式,就可以用傳統的HTTP調用方式來調用)
注意:此次只是集成Eureka,並不涉及到Feign
項目依賴
<dependency> <groupId>com.netflix.eureka</groupId> <artifactId>eureka-client</artifactId> <version>1.7.0</version> </dependency> <!-- Ribbon 負載均衡 --> <dependency> <groupId>com.netflix.ribbon</groupId> <artifactId>ribbon-eureka</artifactId> <version>2.2.2</version> </dependency> <dependency> <groupId>com.netflix.ribbon</groupId> <artifactId>ribbon</artifactId> <version>2.2.5</version> </dependency> <dependency> <groupId>com.netflix.ribbon</groupId> <artifactId>ribbon-core</artifactId> <version>2.2.5</version> </dependency> <dependency> <groupId>com.netflix.ribbon</groupId> <artifactId>ribbon-httpclient</artifactId> <version>2.2.5</version> </dependency> <dependency> <groupId>com.netflix.ribbon</groupId> <artifactId>ribbon-loadbalancer</artifactId> <version>2.2.5</version> </dependency> <dependency> <groupId>com.netflix.archaius</groupId> <artifactId>archaius-core</artifactId> <version>0.7.4</version> </dependency>
配置文件
ribbon.properties
注意:ribbon由於配置是customer-svc服務名,所以只能獲取到customer-svc服務對應的ip地址,如果還要獲取其他服務,就需要把下面的ribbon的三行配置copy一下,把customer-svc改成你需要調用的其他服務名即可
# customer-svc:微服務Eureka上對應的服務名 customer-svc.ribbon.DeploymentContextBasedVipAddresses=customer-svc # 固定寫法,customer-svc使用的ribbon負載均衡器 customer-svc.ribbon.NIWSServerListClassName=com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList # 每分鍾更新customer-svc對應服務的可用地址列表 customer-svc.ribbon.ServerListRefreshInterval=60000
# 控制是否注冊自身到eureka中 eureka.registration.enabled=false # eureka相關配置 eureka.preferSameZone=true eureka.shouldUseDns=false eureka.serviceUrl.default=http://10.0.0.0:8671/eureka eureka.decoderName=JacksonJson
初始化Ribbon
package com.movitech.mbox.modules.feign; import com.netflix.appinfo.MyDataCenterInstanceConfig; import com.netflix.config.ConfigurationManager; import com.netflix.discovery.DefaultEurekaClientConfig; import com.netflix.discovery.DiscoveryManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import java.io.IOException; public class EurekaInitAndRegisterListener implements ServletContextListener { /** * 默認的ribbon配置文件名, 該文件需要放在classpath目錄下 */ public static final String RIBBON_CONFIG_FILE_NAME = "ribbon.properties"; private static Logger log = LoggerFactory.getLogger(EurekaInitAndRegisterListener.class); @Override public void contextInitialized(ServletContextEvent sce) { log.info("開始初始化ribbon"); try { // 加載ribbon配置文件 ConfigurationManager.loadPropertiesFromResources(RIBBON_CONFIG_FILE_NAME); } catch (IOException e) { e.printStackTrace(); log.error("ribbon初始化失敗"); throw new IllegalStateException("ribbon初始化失敗"); } // 初始化Eureka Client DiscoveryManager.getInstance().initComponent(new MyDataCenterInstanceConfig(), new DefaultEurekaClientConfig()); log.info("ribbon初始化完成"); } @Override public void contextDestroyed(ServletContextEvent sce) { DiscoveryManager.getInstance().shutdownComponent(); } }
web.xml
<listener> <listener-class>xx.xx.modules.feign.EurekaInitAndRegisterListener</listener-class> </listener>
獲取服務地址
package com.movitech.mbox.modules.feign; import com.movitech.mbox.modules.feign.vo.AlanServiceAddress; import com.netflix.client.ClientFactory; import com.netflix.loadbalancer.DynamicServerListLoadBalancer; import com.netflix.loadbalancer.RoundRobinRule; import com.netflix.loadbalancer.Server; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; public class AlanServiceAddressSelector { private static Logger log = LoggerFactory.getLogger(AlanServiceAddressSelector.class); private static RoundRobinRule chooseRule = new RoundRobinRule(); /** * 根據輪詢策略選擇一個地址 * * @param clientName * ribbon.properties配置文件中配置項的前綴名, 如myclient * @return null表示該服務當前沒有可用地址 */ public static AlanServiceAddress selectOne(String clientName) { // ClientFactory.getNamedLoadBalancer會緩存結果, 所以不用擔心它每次都會向eureka發起查詢 DynamicServerListLoadBalancer lb = (DynamicServerListLoadBalancer) ClientFactory .getNamedLoadBalancer(clientName); Server selected = chooseRule.choose(lb, null); if (null == selected) { log.warn("服務{}沒有可用地址", clientName); return null; } log.debug("服務{}選擇結果:{}", clientName, selected); return new AlanServiceAddress(selected.getPort(), selected.getHost()); } /** * 選出該服務所有可用地址 * * @param clientName * @return */ public static List<AlanServiceAddress> selectAvailableServers(String clientName) { DynamicServerListLoadBalancer lb = (DynamicServerListLoadBalancer) ClientFactory .getNamedLoadBalancer(clientName); List<Server> serverList = lb.getReachableServers(); if (serverList.isEmpty()) { log.warn("服務{}沒有可用地址", clientName); return Collections.emptyList(); } log.debug("服務{}所有選擇結果:{}", clientName, serverList); return serverList.stream().map(server -> new AlanServiceAddress(server.getPort(), server.getHost())) .collect(Collectors.toList()); } }
地址實體類:
package com.movitech.mbox.modules.feign.vo; public class AlanServiceAddress { private int port; private String host; public AlanServiceAddress() { } public AlanServiceAddress(int port, String host) { this.port = port; this.host = host; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } public String getHost() { return host; } public void setHost(String host) { this.host = host; } /** * 將服務地址轉換為 http://主機名:端口/ 的格式 * @return */ @Override public String toString() { StringBuilder sb = new StringBuilder(15 + host.length()); sb.append("http://").append(host).append(":").append(port).append("/"); return sb.toString(); } }
使用方法
JSONObject param = (JSONObject) JSON.toJSON(feignVO); AlanServiceAddress addr = AlanServiceAddressSelector.selectOne("customer-svc"); String response = HttpUtil.httpPost(addr+"v1/createRecommend",param,null);
借鑒https://www.cnblogs.com/xandersu/p/8504740.html
踩坑
項目集成后,測試環境tomcat一直啟動報錯
錯誤信息報的是這個:Failed to initalize discoveryClient! 這個一看就可能是HTTPCLient的問題,看了下初始化EurekaClient的底層代碼,把pom文件里面的HTTPCLient版本升級成
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.4.1</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpcore</artifactId> <version>4.4.1</version> </dependency>
然后重新啟動就可以了,至於為什么低版本的不行,還不是很清楚