diff --git a/fizz-core/src/main/java/we/fizz/input/extension/grpc/GrpcInput.java b/fizz-core/src/main/java/we/fizz/input/extension/grpc/GrpcInput.java index d3eca4a..3180c6f 100644 --- a/fizz-core/src/main/java/we/fizz/input/extension/grpc/GrpcInput.java +++ b/fizz-core/src/main/java/we/fizz/input/extension/grpc/GrpcInput.java @@ -97,7 +97,7 @@ public class GrpcInput extends RPCInput implements IInput { request.put("method", config.getMethod()); GrpcInstanceService grpcInstanceService = this.getCurrentApplicationContext() .getBean(GrpcInstanceService.class); - request.put("endpoint", grpcInstanceService.getInstanceRoundRobin(config.getServiceName())); + request.put("endpoint", grpcInstanceService.getInstance(config.getServiceName())); // 数据转换 if (inputContext != null && inputContext.getStepContext() != null) { diff --git a/fizz-core/src/main/java/we/proxy/RpcInstanceService.java b/fizz-core/src/main/java/we/proxy/RpcInstanceService.java new file mode 100644 index 0000000..89fcedd --- /dev/null +++ b/fizz-core/src/main/java/we/proxy/RpcInstanceService.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2021 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package we.proxy; + +/** + * RPC instance service interface + * + * @author zhongjie + */ +public interface RpcInstanceService { + enum RpcTypeEnum { + /** + * gRPC + */ + gRPC((byte)2), + /** + * HTTP + */ + HTTP((byte)3); + + RpcTypeEnum(Byte type) { + this.type = type; + } + private Byte type; + + public Byte getType() { + return type; + } + } + + /** + * get an instance + * + * @param rpcTypeEnum RPC type + * @param service service name + * @return instance, {@code null} if instance not-exist + */ + String getInstance(RpcTypeEnum rpcTypeEnum, String service); +} diff --git a/fizz-core/src/main/java/we/proxy/RpcInstanceServiceImpl.java b/fizz-core/src/main/java/we/proxy/RpcInstanceServiceImpl.java new file mode 100644 index 0000000..5b25f1f --- /dev/null +++ b/fizz-core/src/main/java/we/proxy/RpcInstanceServiceImpl.java @@ -0,0 +1,302 @@ +/* + * Copyright (C) 2021 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package we.proxy; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.data.redis.core.ReactiveStringRedisTemplate; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import we.config.AggregateRedisConfig; +import we.flume.clients.log4j2appender.LogService; +import we.util.Constants; +import we.util.JacksonUtils; +import we.util.ReactorUtils; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import java.util.AbstractMap; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; + +/** + * RPC instance service implementation, get all config from redis cache when init and listen on redis channel for change + * + * @author zhongjie + */ +@Service +public class RpcInstanceServiceImpl implements RpcInstanceService { + private static final Logger LOGGER = LoggerFactory.getLogger(RpcInstanceServiceImpl.class); + /** + * redis rpc service change channel + */ + private static final String RPC_SERVICE_CHANNEL = "fizz_rpc_service_channel"; + /** + * redis rpc service info hash key + */ + private static final String RPC_SERVICE_HASH_KEY = "fizz_rpc_service"; + + /** + * key pattern of {@link #serviceToInstancesMap}, {@link #serviceToLoadBalanceTypeMap} and {@link #serviceToCountMap} + * {rpc type}-{service name} + */ + private static final String SERVICE_KEY_PATTERN = "%s-%s"; + + private static final Byte LOAD_BALANCE_TYPE_ROUND_ROBIN = 1; + private static final Byte LOAD_BALANCE_TYPE_RANDOM = 2; + + private static Map> serviceToInstancesMap = new ConcurrentHashMap<>(32); + private static Map serviceToLoadBalanceTypeMap = new ConcurrentHashMap<>(32); + private static Map idToRpcServiceMap = new ConcurrentHashMap<>(32); + private static Map serviceToCountMap = new ConcurrentHashMap<>(32); + + @Resource(name = AggregateRedisConfig.AGGREGATE_REACTIVE_REDIS_TEMPLATE) + private ReactiveStringRedisTemplate redisTemplate; + + @PostConstruct + public void init() throws Throwable { + final Throwable[] throwable = new Throwable[1]; + Throwable error = Mono.just(Objects.requireNonNull(redisTemplate.opsForHash().entries(RPC_SERVICE_HASH_KEY) + .defaultIfEmpty(new AbstractMap.SimpleEntry<>(ReactorUtils.OBJ, ReactorUtils.OBJ)).onErrorStop().doOnError(t -> LOGGER.info(null, t)) + .concatMap(e -> { + Object k = e.getKey(); + if (k == ReactorUtils.OBJ) { + return Flux.just(e); + } + Object v = e.getValue(); + LOGGER.info(k.toString() + Constants.Symbol.COLON + v.toString(), LogService.BIZ_ID, k.toString()); + String json = (String) v; + try { + RpcService rpcService = JacksonUtils.readValue(json, RpcService.class); + this.updateLocalCache(rpcService); + return Flux.just(e); + } catch (Throwable t) { + throwable[0] = t; + LOGGER.info(json, t); + return Flux.error(t); + } + }).blockLast())).flatMap( + e -> { + if (throwable[0] != null) { + return Mono.error(throwable[0]); + } + return lsnRpcServiceChange(); + } + ).block(); + if (error != ReactorUtils.EMPTY_THROWABLE) { + assert error != null; + throw error; + } + } + + @Override + public String getInstance(RpcTypeEnum rpcTypeEnum, String service) { + Byte loadBalanceType = serviceToLoadBalanceTypeMap.get(this.getServiceKey(rpcTypeEnum.getType(), service)); + if (LOAD_BALANCE_TYPE_RANDOM.equals(loadBalanceType)) { + LOGGER.debug("type:{} service:{} get instance random", rpcTypeEnum, service); + return this.getInstanceRandom(rpcTypeEnum, service); + } else { + LOGGER.debug("type:{} service:{} get instance round-robin", rpcTypeEnum, service); + return this.getInstanceRoundRobin(rpcTypeEnum, service); + } + } + + private String getInstanceRandom(RpcTypeEnum rpcTypeEnum, String service) { + List instanceList = this.getAllInstance(rpcTypeEnum, service); + if (CollectionUtils.isEmpty(instanceList)) { + return null; + } + if (instanceList.size() == 1) { + return instanceList.get(0); + } + + return instanceList.get(ThreadLocalRandom.current().nextInt(instanceList.size())); + } + + private String getInstanceRoundRobin(RpcTypeEnum rpcTypeEnum, String service) { + List instanceList = this.getAllInstance(rpcTypeEnum, service); + if (CollectionUtils.isEmpty(instanceList)) { + return null; + } + if (instanceList.size() == 1) { + return instanceList.get(0); + } + + long currentCount = serviceToCountMap.computeIfAbsent(this.getServiceKey(rpcTypeEnum.getType(), service), + it -> new AtomicLong()).getAndIncrement(); + return instanceList.get((int)currentCount % instanceList.size()); + } + + private List getAllInstance(RpcTypeEnum rpcTypeEnum, String service) { + return serviceToInstancesMap.get(this.getServiceKey(rpcTypeEnum.getType(), service)); + } + + private Mono lsnRpcServiceChange() { + final Throwable[] throwable = new Throwable[1]; + final boolean[] b = {false}; + redisTemplate.listenToChannel(RPC_SERVICE_CHANNEL).doOnError(t -> { + throwable[0] = t; + b[0] = false; + LOGGER.error("lsn " + RPC_SERVICE_CHANNEL, t); + }).doOnSubscribe( + s -> { + b[0] = true; + LOGGER.info("success to lsn on " + RPC_SERVICE_CHANNEL); + } + ).doOnNext(msg -> { + String json = msg.getMessage(); + LOGGER.info(json, LogService.BIZ_ID, "rpc" + System.currentTimeMillis()); + try { + RpcService rpcService = JacksonUtils.readValue(json, RpcService.class); + this.updateLocalCache(rpcService); + } catch (Throwable t) { + LOGGER.info(json, t); + } + }).subscribe(); + Throwable t = throwable[0]; + while (!b[0]) { + if (t != null) { + return Mono.error(t); + } else { + try { + TimeUnit.SECONDS.sleep(2); + } catch (InterruptedException e) { + return Mono.error(e); + } + } + } + return Mono.just(ReactorUtils.EMPTY_THROWABLE); + } + + private void updateLocalCache(RpcService rpcService) { + if (rpcService.getType() == null) { + // historical gRPC data type and loadBalanceType is null, here set default value + rpcService.setType(RpcTypeEnum.gRPC.getType()); + rpcService.setLoadBalanceType(LOAD_BALANCE_TYPE_ROUND_ROBIN); + } + + if (rpcService.getIsDeleted() == RpcService.DELETED) { + RpcService removedRpcService = idToRpcServiceMap.remove(rpcService.getId()); + LOGGER.info("remove {}", removedRpcService); + if (removedRpcService != null) { + serviceToInstancesMap.remove(this.getServiceKey(rpcService)); + serviceToLoadBalanceTypeMap.remove(this.getServiceKey(rpcService)); + serviceToCountMap.remove(this.getServiceKey(rpcService)); + } + } else { + RpcService existRpcService = idToRpcServiceMap.get(rpcService.getId()); + idToRpcServiceMap.put(rpcService.getId(), rpcService); + if (existRpcService == null) { + LOGGER.info("add {}", rpcService); + } else { + LOGGER.info("update {} with {}", existRpcService, rpcService); + serviceToInstancesMap.remove(this.getServiceKey(existRpcService)); + serviceToLoadBalanceTypeMap.remove(this.getServiceKey(existRpcService)); + serviceToCountMap.remove(this.getServiceKey(existRpcService)); + } + serviceToInstancesMap.put(this.getServiceKey(rpcService), rpcService.getInstance() == null ? Collections.emptyList() : + Arrays.asList(rpcService.getInstance().split(","))); + serviceToLoadBalanceTypeMap.put(this.getServiceKey(rpcService), rpcService.getLoadBalanceType()); + } + } + + private String getServiceKey(RpcService rpcService) { + return String.format(SERVICE_KEY_PATTERN, rpcService.getType(), rpcService.getService()); + } + + private String getServiceKey(Byte type, String service) { + return String.format(SERVICE_KEY_PATTERN, type, service); + } + + static class RpcService { + private static final int DELETED = 1; + private Long id; + private Integer isDeleted; + private String service; + private String instance; + /** + * RPC type: 2-gRPC 3-HTTP + */ + private Byte type; + /** + * load balance type: 1-round-robin 2-random + */ + private Byte loadBalanceType; + + @Override + public String toString() { + return JacksonUtils.writeValueAsString(this); + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Integer getIsDeleted() { + return isDeleted; + } + + public void setIsDeleted(Integer isDeleted) { + this.isDeleted = isDeleted; + } + + public String getService() { + return service; + } + + public void setService(String service) { + this.service = service; + } + + public String getInstance() { + return instance; + } + + public void setInstance(String instance) { + this.instance = instance; + } + + public Byte getType() { + return type; + } + + public void setType(Byte type) { + this.type = type; + } + + public Byte getLoadBalanceType() { + return loadBalanceType; + } + + public void setLoadBalanceType(Byte loadBalanceType) { + this.loadBalanceType = loadBalanceType; + } + } +} diff --git a/fizz-core/src/main/java/we/proxy/grpc/GrpcInstanceService.java b/fizz-core/src/main/java/we/proxy/grpc/GrpcInstanceService.java index 0f83961..285377b 100644 --- a/fizz-core/src/main/java/we/proxy/grpc/GrpcInstanceService.java +++ b/fizz-core/src/main/java/we/proxy/grpc/GrpcInstanceService.java @@ -1,7 +1,21 @@ +/* + * Copyright (C) 2021 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package we.proxy.grpc; -import java.util.List; - /** * gRPC instance service interface * @@ -9,24 +23,10 @@ import java.util.List; */ public interface GrpcInstanceService { /** - * random get an instance + * get an instance * * @param service service name * @return instance, {@code null} if instance not-exist */ - String getInstanceRandom(String service); - /** - * round-robin get an instance - * - * @param service service name - * @return instance, {@code null} if instance not-exist - */ - String getInstanceRoundRobin(String service); - /** - * get all instances - * - * @param service service name - * @return instance, {@code null} if instance not-exist - */ - List getAllInstance(String service); + String getInstance(String service); } diff --git a/fizz-core/src/main/java/we/proxy/grpc/GrpcInstanceServiceImpl.java b/fizz-core/src/main/java/we/proxy/grpc/GrpcInstanceServiceImpl.java index f31530d..a49ace0 100644 --- a/fizz-core/src/main/java/we/proxy/grpc/GrpcInstanceServiceImpl.java +++ b/fizz-core/src/main/java/we/proxy/grpc/GrpcInstanceServiceImpl.java @@ -1,217 +1,39 @@ +/* + * Copyright (C) 2021 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package we.proxy.grpc; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.data.redis.core.ReactiveStringRedisTemplate; import org.springframework.stereotype.Service; -import org.springframework.util.CollectionUtils; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; -import we.config.AggregateRedisConfig; -import we.flume.clients.log4j2appender.LogService; -import we.util.Constants; -import we.util.JacksonUtils; -import we.util.ReactorUtils; +import we.proxy.RpcInstanceService; -import javax.annotation.PostConstruct; import javax.annotation.Resource; -import java.util.AbstractMap; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ThreadLocalRandom; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; /** - * gRPC instance service implementation, get all config from redis cache when init and listen on redis channel for change + * gRPC instance service implementation * * @author zhongjie */ @Service public class GrpcInstanceServiceImpl implements GrpcInstanceService { - private static final Logger LOGGER = LoggerFactory.getLogger(GrpcInstanceServiceImpl.class); - /** - * redis rpc service change channel - */ - private static final String RPC_SERVICE_CHANNEL = "fizz_rpc_service_channel"; - /** - * redis rpc service info hash key - */ - private static final String RPC_SERVICE_HASH_KEY = "fizz_rpc_service"; - private static Map> serviceToInstancesMap = new ConcurrentHashMap<>(32); - private static Map idToRpcServiceMap = new ConcurrentHashMap<>(32); - private static Map serviceToCountMap = new ConcurrentHashMap<>(32); - - @Resource(name = AggregateRedisConfig.AGGREGATE_REACTIVE_REDIS_TEMPLATE) - private ReactiveStringRedisTemplate redisTemplate; - - @PostConstruct - public void init() throws Throwable { - final Throwable[] throwable = new Throwable[1]; - Throwable error = Mono.just(Objects.requireNonNull(redisTemplate.opsForHash().entries(RPC_SERVICE_HASH_KEY) - .defaultIfEmpty(new AbstractMap.SimpleEntry<>(ReactorUtils.OBJ, ReactorUtils.OBJ)).onErrorStop().doOnError(t -> LOGGER.info(null, t)) - .concatMap(e -> { - Object k = e.getKey(); - if (k == ReactorUtils.OBJ) { - return Flux.just(e); - } - Object v = e.getValue(); - LOGGER.info(k.toString() + Constants.Symbol.COLON + v.toString(), LogService.BIZ_ID, k.toString()); - String json = (String) v; - try { - RpcService rpcService = JacksonUtils.readValue(json, RpcService.class); - this.updateLocalCache(rpcService); - return Flux.just(e); - } catch (Throwable t) { - throwable[0] = t; - LOGGER.info(json, t); - return Flux.error(t); - } - }).blockLast())).flatMap( - e -> { - if (throwable[0] != null) { - return Mono.error(throwable[0]); - } - return lsnRpcServiceChange(); - } - ).block(); - if (error != ReactorUtils.EMPTY_THROWABLE) { - assert error != null; - throw error; - } - } + @Resource + private RpcInstanceService rpcInstanceService; @Override - public String getInstanceRandom(String service) { - List instanceList = serviceToInstancesMap.get(service); - if (CollectionUtils.isEmpty(instanceList)) { - return null; - } - return instanceList.get(ThreadLocalRandom.current().nextInt(instanceList.size())); - } - - @Override - public String getInstanceRoundRobin(String service) { - List instanceList = serviceToInstancesMap.get(service); - if (CollectionUtils.isEmpty(instanceList)) { - return null; - } - long currentCount = serviceToCountMap.computeIfAbsent(service, it -> new AtomicLong()).getAndIncrement(); - return instanceList.get((int)currentCount % instanceList.size()); - } - - @Override - public List getAllInstance(String service) { - return serviceToInstancesMap.get(service); - } - - private Mono lsnRpcServiceChange() { - final Throwable[] throwable = new Throwable[1]; - final boolean[] b = {false}; - redisTemplate.listenToChannel(RPC_SERVICE_CHANNEL).doOnError(t -> { - throwable[0] = t; - b[0] = false; - LOGGER.error("lsn " + RPC_SERVICE_CHANNEL, t); - }).doOnSubscribe( - s -> { - b[0] = true; - LOGGER.info("success to lsn on " + RPC_SERVICE_CHANNEL); - } - ).doOnNext(msg -> { - String json = msg.getMessage(); - LOGGER.info(json, LogService.BIZ_ID, "rpc" + System.currentTimeMillis()); - try { - RpcService rpcService = JacksonUtils.readValue(json, RpcService.class); - this.updateLocalCache(rpcService); - } catch (Throwable t) { - LOGGER.info(json, t); - } - }).subscribe(); - Throwable t = throwable[0]; - while (!b[0]) { - if (t != null) { - return Mono.error(t); - } else { - try { - TimeUnit.SECONDS.sleep(2); - } catch (InterruptedException e) { - return Mono.error(e); - } - } - } - return Mono.just(ReactorUtils.EMPTY_THROWABLE); - } - - private void updateLocalCache(RpcService rpcService) { - if (rpcService.getIsDeleted() == RpcService.DELETED) { - RpcService removedRpcService = idToRpcServiceMap.remove(rpcService.id); - LOGGER.info("remove {}", removedRpcService); - if (removedRpcService != null) { - serviceToInstancesMap.remove(removedRpcService.getService()); - serviceToCountMap.remove(removedRpcService.getService()); - } - } else { - RpcService existRpcService = idToRpcServiceMap.get(rpcService.id); - idToRpcServiceMap.put(rpcService.id, rpcService); - if (existRpcService == null) { - LOGGER.info("add {}", rpcService); - } else { - LOGGER.info("update {} with {}", existRpcService, rpcService); - serviceToInstancesMap.remove(existRpcService.getService()); - serviceToCountMap.remove(existRpcService.getService()); - } - serviceToInstancesMap.put(rpcService.service, rpcService.instance == null ? Collections.emptyList() : - Arrays.asList(rpcService.getInstance().split(","))); - } - } - - private static class RpcService { - private static final int DELETED = 1; - private Long id; - private Integer isDeleted; - private String service; - private String instance; - - @Override - public String toString() { - return JacksonUtils.writeValueAsString(this); - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public Integer getIsDeleted() { - return isDeleted; - } - - public void setIsDeleted(Integer isDeleted) { - this.isDeleted = isDeleted; - } - - public String getService() { - return service; - } - - public void setService(String service) { - this.service = service; - } - - public String getInstance() { - return instance; - } - - public void setInstance(String instance) { - this.instance = instance; - } + public String getInstance(String service) { + return rpcInstanceService.getInstance(RpcInstanceService.RpcTypeEnum.gRPC, service); } } diff --git a/fizz-core/src/main/java/we/proxy/http/HttpInstanceService.java b/fizz-core/src/main/java/we/proxy/http/HttpInstanceService.java new file mode 100644 index 0000000..22a95f4 --- /dev/null +++ b/fizz-core/src/main/java/we/proxy/http/HttpInstanceService.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2021 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package we.proxy.http; + +/** + * HTTP instance service interface + * + * @author zhongjie + */ +public interface HttpInstanceService { + /** + * get an instance + * + * @param service service name + * @return instance, {@code null} if instance not-exist + */ + String getInstance(String service); +} diff --git a/fizz-core/src/main/java/we/proxy/http/HttpInstanceServiceImpl.java b/fizz-core/src/main/java/we/proxy/http/HttpInstanceServiceImpl.java new file mode 100644 index 0000000..a05e79b --- /dev/null +++ b/fizz-core/src/main/java/we/proxy/http/HttpInstanceServiceImpl.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2021 the original author or authors. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package we.proxy.http; + +import org.springframework.stereotype.Service; +import we.proxy.RpcInstanceService; + +import javax.annotation.Resource; + +/** + * HTTP instance service implementation + * + * @author zhongjie + */ +@Service +public class HttpInstanceServiceImpl implements HttpInstanceService { + + @Resource + private RpcInstanceService rpcInstanceService; + + @Override + public String getInstance(String service) { + return rpcInstanceService.getInstance(RpcInstanceService.RpcTypeEnum.HTTP, service); + } +}