非SpringCloud项目,有时会需要调用新SpringCloud项目,通过Eureka获取动态服务地址进行远程调用,很方便。
也可以删除Eureka的部分,直接使用Ribbon调用。
EurekaClient 初始化类
/**
* @author slankka
*/
@Configuration
public class EurekaClientConfiguration {
Logger log = LoggerFactory.getLogger(getClass());
private static ApplicationInfoManager applicationInfoManager;
private static EurekaClient eurekaClient;
private static synchronized ApplicationInfoManager initializeApplicationInfoManager(
EurekaInstanceConfig instanceConfig) {
if (applicationInfoManager == null) {
InstanceInfo instanceInfo = new EurekaConfigBasedInstanceInfoProvider(instanceConfig)
.get();
applicationInfoManager = new ApplicationInfoManager(instanceConfig, instanceInfo);
}
return applicationInfoManager;
}
private static synchronized EurekaClient initializeEurekaClient(
ApplicationInfoManager applicationInfoManager, EurekaClientConfig clientConfig) {
if (eurekaClient == null) {
eurekaClient = new DiscoveryClient(applicationInfoManager, clientConfig);
}
return eurekaClient;
}
@Bean(destroyMethod = "shutdown")
public EurekaClient eurekaClient() {
//初始化应用信息管理器,设置其状态为STARTING
applicationInfoManager = initializeApplicationInfoManager(new MyDataCenterInstanceConfig());
applicationInfoManager.setInstanceStatus(InstanceInfo.InstanceStatus.STARTING);
log.info("Registering service to eureka with status STARTING");
//读取配置文件(classpath:eureka-client.properties),初始化eurekaClient,并设置应用信息管理器的状态为UP
eurekaClient = initializeEurekaClient(applicationInfoManager,
new DefaultEurekaClientConfig());
DiscoveryManager.getInstance().setDiscoveryClient((DiscoveryClient) eurekaClient);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
applicationInfoManager.setInstanceStatus(InstanceInfo.InstanceStatus.UP);
log.info("Initialization finished, now changing eureka client status to UP");
long startTime = System.currentTimeMillis();
//开启一个线程验证注册结果
return eurekaClient;
}
}
服务配置类,目前是手动创建有点Low,后续可以改进为注解,使用Spring ImportBean进行改进自动创建Bean。
/**
* @author slankka
*/
@Configuration
public class RemoteServiceConfiguration {
Logger log = LoggerFactory.getLogger(RemoteServiceConfiguration.class);
public RemoteServiceConfiguration() {
try {
//这里读取其他配置
ConfigurationManager.loadPropertiesFromResources("config.properties");
} catch (IOException e) {
e.printStackTrace();
}
}
@Autowired
private EurekaClient eurekaClient;
class EurekaClientProvider implements Provider<EurekaClient> {
@Override
public EurekaClient get() {
return eurekaClient;
}
}
/**
* 自动创建Ribbon
* @return
*/
@Bean
public RibbonClientRemote remoteService() {
InstanceInfo nextServerFromEureka = eurekaClient
.getNextServerFromEureka("APOLLO-CONFIGSERVICE", false);
log.error("------------------------,APOLLO-CONFIGSERVICE= {}:{}",
nextServerFromEureka.getIPAddr(), nextServerFromEureka.getPort());
RibbonClientRemote service = Feign.builder().client(RibbonClient.create())
.logger(new Slf4jLogger()).logLevel(Level.FULL).encoder(new JacksonEncoder())
.decoder(new JacksonDecoder())
.target(RibbonClientRemote.class, "http://APOLLO-CONFIGSERVICE");
return service;
}
/**
* 手动创建Ribbon
*/
public RibbonClientRemote remoteServiceManuallyMade() {
IRule rule = new AvailabilityFilteringRule();
ServerList<DiscoveryEnabledServer> list = new DiscoveryEnabledNIWSServerList("APOLLO-CONFIGSERVICE", new EurekaClientProvider());
ServerListFilter<DiscoveryEnabledServer> filter = new ZoneAffinityServerListFilter<DiscoveryEnabledServer>();
ZoneAwareLoadBalancer<DiscoveryEnabledServer> lb = LoadBalancerBuilder.<DiscoveryEnabledServer>newBuilder()
.withDynamicServerList(list)
.withRule(rule)
.withServerListFilter(filter)
.buildDynamicServerListLoadBalancer();
RibbonClient client = RibbonClient.builder().lbClientFactory(new LBClientFactory() {
@Override
public LBClient create(String clientName) {
return LBClient.create(lb, ClientFactory.getNamedConfig(clientName));
}
}).build();
RibbonClientRemote service = Feign.builder().client(client).logger(new Slf4jLogger()).logLevel(Level.FULL).encoder(new JacksonEncoder())
.decoder(new JacksonDecoder()).target(RibbonClientRemote.class, "http://APOLLO-CONFIGSERVICE");
return service;
}
/**
* * Ribbon负载均衡策略实现 * 使用ZoneAvoidancePredicate和AvailabilityPredicate来判断是否选择某个server,前一个判断判定一个zone的运行性能是否可用,
* * 剔除不可用的zone(的所有server),AvailabilityPredicate用于过滤掉连接数过多的Server。 *
*/
private IRule zoneAvoidanceRule() {
return new ZoneAvoidanceRule();
}
/**
* Ribbon负载均衡策略实现 * 随机选择一个server。 *
*/
private IRule randomRule() {
return new RandomRule();
}
}
Feign接口
/**
* @Author: slankka
* @Date: 2018/08/08 10:24.
*/
public interface RibbonClientRemote {
@Headers({"Content-Type: application/json", "Accept: application/json"})
@RequestLine("GET /info")
InfoBean info();
}
这里直接调用 APOLLO-CONFIGSERVICE/info
Controller类
/**
* @Author: slankka
* @Date: 2018/08/04 22:25.
*/
@RequestMapping("/core")
@Controller
public class CoreController {
private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private RibbonClientRemote ribbonClientRemote;
@RequestMapping("/raw")
@ResponseBody
public String respone() {
return "{\"code\":200,\"msg\":\"你好中文\",\"data\":null}";
}
@RequestMapping("/ribbon")
@ResponseBody
public InfoBean ribbon() {
return ribbonClientRemote.info();
}
}