传统SSM项目集成Eureka


由于公司一些老的项目要对接新项目,而新项目是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>

然后重新启动就可以了,至于为什么低版本的不行,还不是很清楚


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM