├── .gitignore ├── CHANGES.md ├── README.md ├── jaws-core ├── pom.xml └── src │ ├── main │ ├── java │ │ └── org │ │ │ └── hongxi │ │ │ └── jaws │ │ │ ├── closable │ │ │ ├── Closable.java │ │ │ ├── ShutDownHookListener.java │ │ │ └── ShutdownHook.java │ │ │ ├── cluster │ │ │ ├── Cluster.java │ │ │ ├── HaStrategy.java │ │ │ ├── LoadBalance.java │ │ │ ├── ha │ │ │ │ ├── AbstractHaStrategy.java │ │ │ │ ├── FailfastHaStrategy.java │ │ │ │ └── FailoverHaStrategy.java │ │ │ ├── loadbalance │ │ │ │ ├── AbstractLoadBalance.java │ │ │ │ ├── ActiveWeightLoadBalance.java │ │ │ │ ├── ConfigurableWeightLoadBalance.java │ │ │ │ ├── ConsistentHashLoadBalance.java │ │ │ │ ├── LocalFirstLoadBalance.java │ │ │ │ ├── RandomLoadBalance.java │ │ │ │ └── RoundRobinLoadBalance.java │ │ │ └── support │ │ │ │ ├── ClusterSpi.java │ │ │ │ └── ClusterSupport.java │ │ │ ├── codec │ │ │ ├── AbstractCodec.java │ │ │ ├── Codec.java │ │ │ ├── CodecUtils.java │ │ │ └── Serialization.java │ │ │ ├── common │ │ │ ├── ChannelState.java │ │ │ ├── FutureState.java │ │ │ ├── JawsConstants.java │ │ │ ├── URLParamType.java │ │ │ ├── extension │ │ │ │ ├── Activation.java │ │ │ │ ├── ActivationComparator.java │ │ │ │ ├── ExtensionLoader.java │ │ │ │ ├── Scope.java │ │ │ │ ├── Spi.java │ │ │ │ └── SpiMeta.java │ │ │ ├── threadpool │ │ │ │ ├── DefaultThreadFactory.java │ │ │ │ ├── ExecutorQueue.java │ │ │ │ └── StandardThreadPoolExecutor.java │ │ │ └── util │ │ │ │ ├── ByteUtils.java │ │ │ │ ├── CollectionUtils.java │ │ │ │ ├── ConcurrentHashSet.java │ │ │ │ ├── ExceptionUtils.java │ │ │ │ ├── JawsFrameworkUtils.java │ │ │ │ ├── MathUtils.java │ │ │ │ ├── NetUtils.java │ │ │ │ ├── ReflectUtils.java │ │ │ │ ├── RequestIdGenerator.java │ │ │ │ ├── StringTools.java │ │ │ │ └── UrlUtils.java │ │ │ ├── config │ │ │ ├── AbstractConfig.java │ │ │ ├── AbstractInterfaceConfig.java │ │ │ ├── AbstractRefererConfig.java │ │ │ ├── AbstractServiceConfig.java │ │ │ ├── BasicRefererInterfaceConfig.java │ │ │ ├── BasicServiceInterfaceConfig.java │ │ │ ├── ConfigUtils.java │ │ │ ├── MethodConfig.java │ │ │ ├── ProtocolConfig.java │ │ │ ├── RefererConfig.java │ │ │ ├── RegistryConfig.java │ │ │ ├── ServiceConfig.java │ │ │ ├── annotation │ │ │ │ └── ConfigDesc.java │ │ │ └── handler │ │ │ │ ├── ConfigHandler.java │ │ │ │ └── SimpleConfigHandler.java │ │ │ ├── exception │ │ │ ├── JawsAbstractException.java │ │ │ ├── JawsBizException.java │ │ │ ├── JawsErrorMsg.java │ │ │ ├── JawsErrorMsgConstants.java │ │ │ ├── JawsFrameworkException.java │ │ │ └── JawsServiceException.java │ │ │ ├── filter │ │ │ ├── AccessLogFilter.java │ │ │ ├── Filter.java │ │ │ └── InitializableFilter.java │ │ │ ├── protocol │ │ │ ├── AbstractProtocol.java │ │ │ ├── injvm │ │ │ │ └── InjvmProtocol.java │ │ │ ├── jaws │ │ │ │ ├── DefaultRpcExporter.java │ │ │ │ ├── DefaultRpcReferer.java │ │ │ │ ├── JawsCodec.java │ │ │ │ └── JawsProtocol.java │ │ │ ├── package-info.java │ │ │ └── support │ │ │ │ └── ProtocolFilterDecorator.java │ │ │ ├── proxy │ │ │ ├── AbstractRefererHandler.java │ │ │ ├── CommonHandler.java │ │ │ ├── ProxyFactory.java │ │ │ ├── RefererCommonHandler.java │ │ │ ├── RefererInvocationHandler.java │ │ │ └── support │ │ │ │ ├── CommonProxyFactory.java │ │ │ │ └── JdkProxyFactory.java │ │ │ ├── registry │ │ │ ├── DiscoveryService.java │ │ │ ├── FailbackRegistry.java │ │ │ ├── NotifyListener.java │ │ │ ├── Registry.java │ │ │ ├── RegistryFactory.java │ │ │ ├── RegistryService.java │ │ │ └── support │ │ │ │ ├── AbstractRegistry.java │ │ │ │ ├── AbstractRegistryFactory.java │ │ │ │ ├── DirectRegistry.java │ │ │ │ ├── DirectRegistryFactory.java │ │ │ │ ├── LocalRegistry.java │ │ │ │ ├── LocalRegistryFactory.java │ │ │ │ └── command │ │ │ │ ├── CommandFailbackRegistry.java │ │ │ │ ├── CommandListener.java │ │ │ │ ├── CommandServiceManager.java │ │ │ │ ├── RpcCommand.java │ │ │ │ ├── RpcCommandUtils.java │ │ │ │ └── ServiceListener.java │ │ │ ├── rpc │ │ │ ├── AbstractExporter.java │ │ │ ├── AbstractNode.java │ │ │ ├── AbstractProvider.java │ │ │ ├── AbstractReferer.java │ │ │ ├── Callbackable.java │ │ │ ├── Caller.java │ │ │ ├── DefaultProvider.java │ │ │ ├── DefaultRequest.java │ │ │ ├── DefaultResponse.java │ │ │ ├── DefaultResponseFuture.java │ │ │ ├── Exporter.java │ │ │ ├── Future.java │ │ │ ├── FutureListener.java │ │ │ ├── Node.java │ │ │ ├── Protocol.java │ │ │ ├── Provider.java │ │ │ ├── Referer.java │ │ │ ├── RefererSupports.java │ │ │ ├── Request.java │ │ │ ├── Response.java │ │ │ ├── ResponseFuture.java │ │ │ ├── RpcContext.java │ │ │ └── URL.java │ │ │ ├── serialize │ │ │ ├── DeserializableObject.java │ │ │ ├── FastJsonSerialization.java │ │ │ └── Hessian2Serialization.java │ │ │ ├── switcher │ │ │ ├── JawsSwitcherUtils.java │ │ │ ├── LocalSwitcherService.java │ │ │ ├── Switcher.java │ │ │ ├── SwitcherListener.java │ │ │ └── SwitcherService.java │ │ │ └── transport │ │ │ ├── AbstractClient.java │ │ │ ├── AbstractServer.java │ │ │ ├── AbstractSharedPoolClient.java │ │ │ ├── Channel.java │ │ │ ├── Client.java │ │ │ ├── DefaultProtectedStrategy.java │ │ │ ├── Endpoint.java │ │ │ ├── EndpointFactory.java │ │ │ ├── MessageHandler.java │ │ │ ├── ProviderMessageRouter.java │ │ │ ├── ProviderProtectedStrategy.java │ │ │ ├── Server.java │ │ │ ├── SharedObjectFactory.java │ │ │ ├── TransportException.java │ │ │ ├── UnprotectedStrategy.java │ │ │ └── support │ │ │ └── AbstractEndpointFactory.java │ └── resources │ │ └── META-INF │ │ └── services │ │ ├── org.hongxi.jaws.cluster.Cluster │ │ ├── org.hongxi.jaws.cluster.HaStrategy │ │ ├── org.hongxi.jaws.cluster.LoadBalance │ │ ├── org.hongxi.jaws.codec.Codec │ │ ├── org.hongxi.jaws.codec.Serialization │ │ ├── org.hongxi.jaws.config.handler.ConfigHandler │ │ ├── org.hongxi.jaws.filter.Filter │ │ ├── org.hongxi.jaws.proxy.ProxyFactory │ │ ├── org.hongxi.jaws.registry.Registry │ │ ├── org.hongxi.jaws.registry.RegistryFactory │ │ ├── org.hongxi.jaws.rpc.Protocol │ │ ├── org.hongxi.jaws.switcher.SwitcherService │ │ └── org.hongxi.jaws.transport.ProviderProtectedStrategy │ └── test │ ├── java │ └── org │ │ └── hongxi │ │ └── jaws │ │ ├── BaseTestCase.java │ │ ├── MockServiceConfig.java │ │ ├── ThreadPoolTest.java │ │ ├── config │ │ ├── MultiConfigTest.java │ │ ├── RefererConfigTest.java │ │ └── ServiceConfigTest.java │ │ ├── mock │ │ ├── MockChannel.java │ │ ├── MockClient.java │ │ ├── MockEndpointFactory.java │ │ ├── MockReferer.java │ │ └── MockServer.java │ │ └── protocol │ │ ├── example │ │ ├── Hello.java │ │ ├── IHello.java │ │ ├── IHelloMock.java │ │ ├── IWorld.java │ │ ├── MockWorld.java │ │ ├── Model.java │ │ ├── SimpleObject.java │ │ ├── UnSerializableClass.java │ │ └── World.java │ │ └── package-info.java │ └── resources │ └── META-INF │ └── services │ └── org.hongxi.jaws.transport.EndpointFactory ├── jaws-registry-zookeeper ├── pom.xml └── src │ ├── main │ ├── java │ │ └── org │ │ │ └── hongxi │ │ │ └── jaws │ │ │ └── registry │ │ │ └── zookeeper │ │ │ ├── StringSerializer.java │ │ │ ├── ZkNodeType.java │ │ │ ├── ZkUtils.java │ │ │ ├── ZookeeperRegistry.java │ │ │ ├── ZookeeperRegistryFactory.java │ │ │ └── ZookeeperStringSerializerRegistryFactory.java │ └── resources │ │ └── META-INF │ │ └── services │ │ └── org.hongxi.jaws.registry.RegistryFactory │ └── test │ ├── java │ └── org │ │ └── hongxi │ │ └── jaws │ │ └── registry │ │ └── zookeeper │ │ ├── EmbeddedZookeeper.java │ │ ├── ZkStartup.java │ │ └── ZookeeperRegistryTest.java │ └── resources │ └── zoo.cfg ├── jaws-samples ├── README.md ├── jaws-sample-api │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── org │ │ └── hongxi │ │ └── jaws │ │ └── sample │ │ └── api │ │ ├── DemoService.java │ │ └── model │ │ ├── Contacts.java │ │ ├── Phone.java │ │ └── User.java ├── jaws-sample-consumer │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── org │ │ │ └── hongxi │ │ │ └── jaws │ │ │ └── sample │ │ │ └── consumer │ │ │ └── SampleConsumer.java │ │ └── resources │ │ └── logback.xml ├── jaws-sample-provider │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── org │ │ │ └── hongxi │ │ │ └── jaws │ │ │ └── sample │ │ │ └── provider │ │ │ ├── SampleProvider.java │ │ │ └── service │ │ │ └── DemoServiceImpl.java │ │ └── resources │ │ └── logback.xml ├── jaws-test │ ├── pom.xml │ └── src │ │ └── test │ │ ├── java │ │ └── org │ │ │ └── jaws │ │ │ └── test │ │ │ ├── BaseTestCase.java │ │ │ ├── HelloService.java │ │ │ ├── HelloServiceImpl.java │ │ │ ├── RefererConfigTest.java │ │ │ ├── ServiceConfigTest.java │ │ │ └── User.java │ │ └── resources │ │ └── logback.xml ├── pom.xml └── zk │ ├── pom.xml │ └── src │ └── main │ ├── java │ └── org │ │ └── hongxi │ │ └── jaws │ │ └── zk │ │ ├── ZKClient.java │ │ └── ZKStartup.java │ └── resources │ └── zookeeper.properties ├── jaws-spring-boot-starter ├── pom.xml └── src │ └── main │ ├── java │ └── org │ │ └── hongxi │ │ └── jaws │ │ └── spring │ │ └── package-info.java │ └── resources │ └── META-INF │ └── spring.factories ├── jaws-transport-netty ├── pom.xml └── src │ ├── main │ ├── java │ │ └── org │ │ │ └── hongxi │ │ │ └── jaws │ │ │ └── transport │ │ │ └── netty │ │ │ ├── NettyChannel.java │ │ │ ├── NettyChannelFactory.java │ │ │ ├── NettyChannelHandler.java │ │ │ ├── NettyClient.java │ │ │ ├── NettyDecoder.java │ │ │ ├── NettyEncoder.java │ │ │ ├── NettyEndpointFactory.java │ │ │ ├── NettyMessage.java │ │ │ ├── NettyServer.java │ │ │ └── NettyServerChannelManage.java │ └── resources │ │ └── META-INF │ │ └── services │ │ └── org.hongxi.jaws.transport.EndpointFactory │ └── test │ └── java │ └── org │ └── hongxi │ └── jaws │ └── transport │ └── netty │ └── NettyClientTest.java └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | .target/ 2 | .logs/ 3 | */logs/ 4 | */*/logs/ 5 | */target/ 6 | bin/ 7 | 8 | # maven ignore 9 | target/ 10 | *.war 11 | *.zip 12 | *.tar 13 | *.tar.gz 14 | 15 | # eclipse ignore 16 | .settings/ 17 | .project 18 | .classpath 19 | 20 | # idea ignore 21 | .idea/ 22 | *.ipr 23 | *.iml 24 | *.iws 25 | 26 | # temp ignore 27 | *.log 28 | *.cache 29 | *.diff 30 | *.patch 31 | *.tmp 32 | 33 | # system ignore 34 | .DS_Store 35 | Thumbs.db 36 | logs/ 37 | -------------------------------------------------------------------------------- /CHANGES.md: -------------------------------------------------------------------------------- 1 | ## 0.0.3-SNAPSHOT 2 | 服务注册与发现,负载均衡,容错 3 | 4 | ## 0.0.1 5 | 编解码,传输协议,请求响应 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Jaws Framework 2 | RPC framework based on Netty. 3 | 4 | © [hongxi.org](http://hongxi.org) | [jaws.hongxi.org](http://jaws.hongxi.org) 5 | -------------------------------------------------------------------------------- /jaws-core/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | org.hongxi 7 | jaws-parent 8 | 0.0.3-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | jaws-core 13 | 14 | 15 | 16 | org.apache.commons 17 | commons-lang3 18 | 19 | 20 | commons-pool 21 | commons-pool 22 | 23 | 24 | com.caucho 25 | hessian 26 | 27 | 28 | com.alibaba 29 | fastjson 30 | 31 | 32 | com.google.guava 33 | guava 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/closable/Closable.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.closable; 2 | 3 | /** 4 | * Created by shenhongxi on 2021/4/23. 5 | */ 6 | public interface Closable { 7 | 8 | void close(); 9 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/closable/ShutDownHookListener.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.closable; 2 | 3 | import javax.servlet.ServletContextEvent; 4 | import javax.servlet.ServletContextListener; 5 | 6 | /** 7 | * In order to shutdown jaws server running in tomcat(run tomcat's shutdown.sh rather than kill PID manually),add ShutDownHookListener to web.xml 8 | * 为了关闭在tomcat中运行的 jaws server(运行tomcat的shutdown.sh关闭而不是手动kill pid),在web.xml中添加ShutDownHookListener 9 | * 10 | * Created by shenhongxi on 2021/4/23. 11 | */ 12 | public class ShutDownHookListener implements ServletContextListener { 13 | @Override 14 | public void contextInitialized(ServletContextEvent sce) { 15 | } 16 | 17 | @Override 18 | public void contextDestroyed(ServletContextEvent sce) { 19 | ShutdownHook.runHook(true); 20 | } 21 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/closable/ShutdownHook.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.closable; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Collections; 8 | import java.util.List; 9 | 10 | /** 11 | * Add a shutdown hook to close some global resources 12 | * 13 | * Created by shenhongxi on 2021/4/23. 14 | */ 15 | public class ShutdownHook extends Thread { 16 | 17 | private static final Logger log = LoggerFactory.getLogger(ShutdownHook.class); 18 | 19 | //Smaller the priority is,earlier the resource is to be closed,default Priority is 20 20 | private static final int DEFAULT_PRIORITY = 20; 21 | //only global resource should be register to ShutDownHook,don't register connections to it. 22 | private static ShutdownHook instance; 23 | private List resourceList = new ArrayList<>(); 24 | 25 | private ShutdownHook() { 26 | } 27 | 28 | private static void init() { 29 | if (instance == null) { 30 | instance = new ShutdownHook(); 31 | log.info("ShutdownHook is initialized"); 32 | } 33 | } 34 | 35 | public static void runHook(boolean sync) { 36 | if (instance != null) { 37 | if (sync) { 38 | instance.run(); 39 | } else { 40 | instance.start(); 41 | } 42 | } 43 | } 44 | 45 | public static void registerShutdownHook(Closable closable) { 46 | registerShutdownHook(closable, DEFAULT_PRIORITY); 47 | } 48 | 49 | public static synchronized void registerShutdownHook(Closable closable, int priority) { 50 | if (instance == null) { 51 | init(); 52 | } 53 | instance.resourceList.add(new closableObject(closable, priority)); 54 | log.info("add resource {} to list", closable.getClass()); 55 | } 56 | 57 | @Override 58 | public void run() { 59 | closeAll(); 60 | } 61 | 62 | /** 63 | * synchronized method to close all the resources in the list 64 | */ 65 | private synchronized void closeAll() { 66 | Collections.sort(resourceList); 67 | log.info("Start to close global resource due to priority"); 68 | for (closableObject resource : resourceList) { 69 | try { 70 | resource.closable.close(); 71 | } catch (Exception e) { 72 | log.error("Failed to close {}", resource.closable.getClass(), e); 73 | } 74 | log.info("Success to close {}", resource.closable.getClass()); 75 | } 76 | log.info("Success to close all the resource!"); 77 | resourceList.clear(); 78 | } 79 | 80 | private static class closableObject implements Comparable { 81 | Closable closable; 82 | int priority; 83 | 84 | public closableObject(Closable closable, int priority) { 85 | this.closable = closable; 86 | this.priority = priority; 87 | } 88 | 89 | @Override 90 | public int compareTo(closableObject o) { 91 | if (this.priority > o.priority) { 92 | return -1; 93 | } else if (this.priority == o.priority) { 94 | return 0; 95 | } else { 96 | return 1; 97 | } 98 | } 99 | } 100 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/cluster/Cluster.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.cluster; 2 | 3 | import org.hongxi.jaws.common.extension.Scope; 4 | import org.hongxi.jaws.common.extension.Spi; 5 | import org.hongxi.jaws.rpc.Caller; 6 | import org.hongxi.jaws.rpc.Referer; 7 | import org.hongxi.jaws.rpc.URL; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * Cluster is a service broker 13 | * 14 | * Created by shenhongxi on 2021/4/23. 15 | */ 16 | @Spi(scope = Scope.PROTOTYPE) 17 | public interface Cluster extends Caller { 18 | 19 | @Override 20 | void init(); 21 | 22 | void setUrl(URL url); 23 | 24 | void setLoadBalance(LoadBalance loadBalance); 25 | 26 | LoadBalance getLoadBalance(); 27 | 28 | void setHaStrategy(HaStrategy haStrategy); 29 | 30 | void onRefresh(List> referers); 31 | 32 | List> getReferers(); 33 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/cluster/HaStrategy.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.cluster; 2 | 3 | import org.hongxi.jaws.common.extension.Scope; 4 | import org.hongxi.jaws.common.extension.Spi; 5 | import org.hongxi.jaws.rpc.Request; 6 | import org.hongxi.jaws.rpc.Response; 7 | import org.hongxi.jaws.rpc.URL; 8 | 9 | /** 10 | * Ha strategy. 11 | * 12 | * Created by shenhongxi on 2021/4/23. 13 | */ 14 | @Spi(scope = Scope.PROTOTYPE) 15 | public interface HaStrategy { 16 | 17 | void setUrl(URL url); 18 | 19 | Response call(Request request, LoadBalance loadBalance); 20 | 21 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/cluster/LoadBalance.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.cluster; 2 | 3 | import org.hongxi.jaws.common.extension.Scope; 4 | import org.hongxi.jaws.common.extension.Spi; 5 | import org.hongxi.jaws.rpc.Referer; 6 | import org.hongxi.jaws.rpc.Request; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * Load balance for select referer 12 | * 13 | * Created by shenhongxi on 2021/4/23. 14 | */ 15 | @Spi(scope = Scope.PROTOTYPE) 16 | public interface LoadBalance { 17 | 18 | void onRefresh(List> referers); 19 | 20 | Referer select(Request request); 21 | 22 | void selectToHolder(Request request, List> refersHolder); 23 | 24 | void setWeightString(String weightString); 25 | 26 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/cluster/ha/AbstractHaStrategy.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.cluster.ha; 2 | 3 | import org.hongxi.jaws.cluster.HaStrategy; 4 | import org.hongxi.jaws.rpc.URL; 5 | 6 | /** 7 | * 8 | * Abstract ha strategy. 9 | * 10 | * Created by shenhongxi on 2021/4/23. 11 | */ 12 | 13 | public abstract class AbstractHaStrategy implements HaStrategy { 14 | 15 | protected URL url; 16 | 17 | @Override 18 | public void setUrl(URL url) { 19 | this.url = url; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/cluster/ha/FailfastHaStrategy.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.cluster.ha; 2 | 3 | import org.hongxi.jaws.cluster.LoadBalance; 4 | import org.hongxi.jaws.common.extension.SpiMeta; 5 | import org.hongxi.jaws.rpc.Referer; 6 | import org.hongxi.jaws.rpc.Request; 7 | import org.hongxi.jaws.rpc.Response; 8 | 9 | /** 10 | * 11 | * Fail fast ha strategy. 12 | * 13 | * Created by shenhongxi on 2021/4/23. 14 | */ 15 | @SpiMeta(name = "failfast") 16 | public class FailfastHaStrategy extends AbstractHaStrategy { 17 | 18 | @Override 19 | public Response call(Request request, LoadBalance loadBalance) { 20 | Referer refer = loadBalance.select(request); 21 | return refer.call(request); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/cluster/ha/FailoverHaStrategy.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.cluster.ha; 2 | 3 | import org.hongxi.jaws.cluster.LoadBalance; 4 | import org.hongxi.jaws.common.URLParamType; 5 | import org.hongxi.jaws.common.extension.SpiMeta; 6 | import org.hongxi.jaws.common.util.ExceptionUtils; 7 | import org.hongxi.jaws.exception.JawsFrameworkException; 8 | import org.hongxi.jaws.exception.JawsServiceException; 9 | import org.hongxi.jaws.rpc.Referer; 10 | import org.hongxi.jaws.rpc.Request; 11 | import org.hongxi.jaws.rpc.Response; 12 | import org.hongxi.jaws.rpc.URL; 13 | import org.slf4j.Logger; 14 | import org.slf4j.LoggerFactory; 15 | 16 | import java.util.ArrayList; 17 | import java.util.List; 18 | 19 | /** 20 | * Failover ha strategy. 21 | * 22 | * Created by shenhongxi on 2021/4/23. 23 | */ 24 | @SpiMeta(name = "failover") 25 | public class FailoverHaStrategy extends AbstractHaStrategy { 26 | 27 | private static final Logger log = LoggerFactory.getLogger(FailoverHaStrategy.class); 28 | 29 | protected ThreadLocal>> referersHolder = ThreadLocal.withInitial(ArrayList::new); 30 | 31 | @Override 32 | public Response call(Request request, LoadBalance loadBalance) { 33 | 34 | List> referers = selectReferers(request, loadBalance); 35 | if (referers.isEmpty()) { 36 | throw new JawsServiceException(String.format("FailoverHaStrategy No referers for request:%s, loadbalance:%s", request, 37 | loadBalance)); 38 | } 39 | URL refUrl = referers.get(0).getUrl(); 40 | // 先使用method的配置 41 | int tryCount = 42 | refUrl.getMethodParameter(request.getMethodName(), request.getParametersDesc(), URLParamType.retries.getName(), 43 | URLParamType.retries.intValue()); 44 | // 如果有问题,则设置为不重试 45 | if (tryCount < 0) { 46 | tryCount = 0; 47 | } 48 | 49 | for (int i = 0; i <= tryCount; i++) { 50 | Referer refer = referers.get(i % referers.size()); 51 | try { 52 | request.setRetries(i); 53 | return refer.call(request); 54 | } catch (RuntimeException e) { 55 | // 对于业务异常,直接抛出 56 | if (ExceptionUtils.isBizException(e)) { 57 | throw e; 58 | } else if (i >= tryCount) { 59 | throw e; 60 | } 61 | log.warn("FailoverHaStrategy Call false for request: {}", request, e); 62 | } 63 | } 64 | 65 | throw new JawsFrameworkException("FailoverHaStrategy.call should not come here!"); 66 | } 67 | 68 | protected List> selectReferers(Request request, LoadBalance loadBalance) { 69 | List> referers = referersHolder.get(); 70 | referers.clear(); 71 | loadBalance.selectToHolder(request, referers); 72 | return referers; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/cluster/loadbalance/AbstractLoadBalance.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.cluster.loadbalance; 2 | 3 | import org.hongxi.jaws.cluster.LoadBalance; 4 | import org.hongxi.jaws.common.util.JawsFrameworkUtils; 5 | import org.hongxi.jaws.exception.JawsServiceException; 6 | import org.hongxi.jaws.rpc.Referer; 7 | import org.hongxi.jaws.rpc.Request; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | import java.util.Collections; 12 | import java.util.List; 13 | 14 | /** 15 | * Created by shenhongxi on 2021/4/23. 16 | */ 17 | public abstract class AbstractLoadBalance implements LoadBalance { 18 | 19 | private static final Logger log = LoggerFactory.getLogger(AbstractLoadBalance.class); 20 | 21 | public static final int MAX_REFERER_COUNT = 10; 22 | 23 | private List> referers; 24 | 25 | @Override 26 | public void onRefresh(List> referers) { 27 | Collections.shuffle(referers); 28 | // 只能引用替换,不能进行referers update。 29 | this.referers = referers; 30 | } 31 | 32 | @Override 33 | public Referer select(Request request) { 34 | List> referers = this.referers; 35 | if (referers == null) { 36 | throw new JawsServiceException(this.getClass().getSimpleName() + " No available referers for call request:" + request); 37 | } 38 | Referer ref = null; 39 | if (referers.size() > 1) { 40 | ref = doSelect(request); 41 | 42 | } else if (referers.size() == 1) { 43 | ref = referers.get(0).isAvailable() ? referers.get(0) : null; 44 | } 45 | 46 | if (ref != null) { 47 | return ref; 48 | } 49 | throw new JawsServiceException(this.getClass().getSimpleName() + " No available referers for call request:" + request); 50 | } 51 | 52 | @Override 53 | public void selectToHolder(Request request, List> refersHolder) { 54 | List> referers = this.referers; 55 | 56 | if (referers == null) { 57 | throw new JawsServiceException(this.getClass().getSimpleName() + " No available referers for call : referers_size= 0 " 58 | + JawsFrameworkUtils.toString(request)); 59 | } 60 | 61 | if (referers.size() > 1) { 62 | doSelectToHolder(request, refersHolder); 63 | 64 | } else if (referers.size() == 1 && referers.get(0).isAvailable()) { 65 | refersHolder.add(referers.get(0)); 66 | } 67 | if (refersHolder.isEmpty()) { 68 | throw new JawsServiceException(this.getClass().getSimpleName() + " No available referers for call : referers_size=" 69 | + referers.size() + " " + JawsFrameworkUtils.toString(request)); 70 | } 71 | } 72 | 73 | protected List> getReferers() { 74 | return referers; 75 | } 76 | 77 | @Override 78 | public void setWeightString(String weightString) { 79 | log.info("ignore weightString: {}", weightString); 80 | } 81 | 82 | protected abstract Referer doSelect(Request request); 83 | 84 | protected abstract void doSelectToHolder(Request request, List> refersHolder); 85 | } 86 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/cluster/loadbalance/ActiveWeightLoadBalance.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.cluster.loadbalance; 2 | 3 | import org.hongxi.jaws.common.extension.SpiMeta; 4 | import org.hongxi.jaws.rpc.Referer; 5 | import org.hongxi.jaws.rpc.Request; 6 | 7 | import java.util.Collections; 8 | import java.util.Comparator; 9 | import java.util.List; 10 | import java.util.concurrent.ThreadLocalRandom; 11 | 12 | /** 13 | * "低并发优化" 负载均衡 14 | * 15 | *
16 |  * 		1) 低并发度优先: referer的某时刻的call数越小优先级越高 
17 |  * 
18 |  * 		2) 低并发referer获取策略:
19 |  * 				由于Referer List可能很多,比如上百台,如果每次都要从这上百个Referer或者最低并发的几个,性能有些损耗,
20 |  * 				因此 random.nextInt(list.size()) 获取一个起始的index,然后获取最多不超过MAX_REFERER_COUNT的
21 |  * 				状态是isAvailable的referer进行判断activeCount.
22 |  * 
23 | * 24 | * Created by shenhongxi on 2021/4/23. 25 | */ 26 | @SpiMeta(name = "activeWeight") 27 | public class ActiveWeightLoadBalance extends AbstractLoadBalance { 28 | 29 | @Override 30 | protected Referer doSelect(Request request) { 31 | List> referers = getReferers(); 32 | 33 | int refererSize = referers.size(); 34 | int startIndex = ThreadLocalRandom.current().nextInt(refererSize); 35 | int currentCursor = 0; 36 | int currentAvailableCursor = 0; 37 | 38 | Referer referer = null; 39 | 40 | while (currentAvailableCursor < MAX_REFERER_COUNT && currentCursor < refererSize) { 41 | Referer temp = referers.get((startIndex + currentCursor) % refererSize); 42 | currentCursor++; 43 | 44 | if (!temp.isAvailable()) { 45 | continue; 46 | } 47 | 48 | currentAvailableCursor++; 49 | 50 | if (referer == null) { 51 | referer = temp; 52 | } else { 53 | if (compare(referer, temp) > 0) { 54 | referer = temp; 55 | } 56 | } 57 | } 58 | 59 | return referer; 60 | } 61 | 62 | @Override 63 | protected void doSelectToHolder(Request request, List> refersHolder) { 64 | List> referers = getReferers(); 65 | 66 | int refererSize = referers.size(); 67 | int startIndex = ThreadLocalRandom.current().nextInt(refererSize); 68 | int currentCursor = 0; 69 | int currentAvailableCursor = 0; 70 | 71 | while (currentAvailableCursor < MAX_REFERER_COUNT && currentCursor < refererSize) { 72 | Referer temp = referers.get((startIndex + currentCursor) % refererSize); 73 | currentCursor++; 74 | 75 | if (!temp.isAvailable()) { 76 | continue; 77 | } 78 | 79 | currentAvailableCursor++; 80 | 81 | refersHolder.add(temp); 82 | } 83 | 84 | Collections.sort(refersHolder, new LowActivePriorityComparator()); 85 | } 86 | 87 | private int compare(Referer referer1, Referer referer2) { 88 | return referer1.activeRefererCount() - referer2.activeRefererCount(); 89 | } 90 | 91 | static class LowActivePriorityComparator implements Comparator> { 92 | @Override 93 | public int compare(Referer referer1, Referer referer2) { 94 | return referer1.activeRefererCount() - referer2.activeRefererCount(); 95 | } 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/cluster/loadbalance/ConsistentHashLoadBalance.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.cluster.loadbalance; 2 | 3 | import org.hongxi.jaws.common.JawsConstants; 4 | import org.hongxi.jaws.common.extension.SpiMeta; 5 | import org.hongxi.jaws.common.util.MathUtils; 6 | import org.hongxi.jaws.rpc.Referer; 7 | import org.hongxi.jaws.rpc.Request; 8 | 9 | import java.util.ArrayList; 10 | import java.util.Arrays; 11 | import java.util.Collections; 12 | import java.util.List; 13 | 14 | /** 15 | * 16 | * Use consistent hash to choose referer 17 | * 18 | * Created by shenhongxi on 2021/4/23. 19 | */ 20 | @SpiMeta(name = "consistent") 21 | public class ConsistentHashLoadBalance extends AbstractLoadBalance { 22 | 23 | private List> consistentHashReferers; 24 | 25 | @Override 26 | public void onRefresh(List> referers) { 27 | super.onRefresh(referers); 28 | 29 | List> copyReferers = new ArrayList>(referers); 30 | List> tempRefers = new ArrayList>(); 31 | for (int i = 0; i < JawsConstants.DEFAULT_CONSISTENT_HASH_BASE_LOOP; i++) { 32 | Collections.shuffle(copyReferers); 33 | for (Referer ref : copyReferers) { 34 | tempRefers.add(ref); 35 | } 36 | } 37 | 38 | consistentHashReferers = tempRefers; 39 | } 40 | 41 | @Override 42 | protected Referer doSelect(Request request) { 43 | 44 | int hash = getHash(request); 45 | Referer ref; 46 | for (int i = 0; i < getReferers().size(); i++) { 47 | ref = consistentHashReferers.get((hash + i) % consistentHashReferers.size()); 48 | if (ref.isAvailable()) { 49 | return ref; 50 | } 51 | } 52 | return null; 53 | } 54 | 55 | @Override 56 | protected void doSelectToHolder(Request request, List> refersHolder) { 57 | List> referers = getReferers(); 58 | 59 | int hash = getHash(request); 60 | for (int i = 0; i < referers.size(); i++) { 61 | Referer ref = consistentHashReferers.get((hash + i) % consistentHashReferers.size()); 62 | if (ref.isAvailable()) { 63 | refersHolder.add(ref); 64 | } 65 | } 66 | } 67 | 68 | private int getHash(Request request) { 69 | int hashcode; 70 | if (request.getArguments() == null || request.getArguments().length == 0) { 71 | hashcode = request.hashCode(); 72 | } else { 73 | hashcode = Arrays.hashCode(request.getArguments()); 74 | } 75 | return MathUtils.getNonNegative(hashcode); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/cluster/loadbalance/RandomLoadBalance.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.cluster.loadbalance; 2 | 3 | import org.hongxi.jaws.common.extension.SpiMeta; 4 | import org.hongxi.jaws.rpc.Referer; 5 | import org.hongxi.jaws.rpc.Request; 6 | 7 | import java.util.List; 8 | import java.util.concurrent.ThreadLocalRandom; 9 | 10 | /** 11 | * 12 | * random load balance. 13 | * 14 | * Created by shenhongxi on 2021/4/23. 15 | */ 16 | @SpiMeta(name = "random") 17 | public class RandomLoadBalance extends AbstractLoadBalance { 18 | 19 | @Override 20 | protected Referer doSelect(Request request) { 21 | List> referers = getReferers(); 22 | 23 | int idx = (int) (ThreadLocalRandom.current().nextDouble() * referers.size()); 24 | for (int i = 0; i < referers.size(); i++) { 25 | Referer ref = referers.get((i + idx) % referers.size()); 26 | if (ref.isAvailable()) { 27 | return ref; 28 | } 29 | } 30 | return null; 31 | } 32 | 33 | @Override 34 | protected void doSelectToHolder(Request request, List> refersHolder) { 35 | List> referers = getReferers(); 36 | 37 | int idx = (int) (ThreadLocalRandom.current().nextDouble() * referers.size()); 38 | for (int i = 0; i < referers.size(); i++) { 39 | Referer referer = referers.get((i + idx) % referers.size()); 40 | if (referer.isAvailable()) { 41 | refersHolder.add(referer); 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/cluster/loadbalance/RoundRobinLoadBalance.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.cluster.loadbalance; 2 | 3 | import org.hongxi.jaws.common.extension.SpiMeta; 4 | import org.hongxi.jaws.common.util.MathUtils; 5 | import org.hongxi.jaws.rpc.Referer; 6 | import org.hongxi.jaws.rpc.Request; 7 | 8 | import java.util.List; 9 | import java.util.concurrent.atomic.AtomicInteger; 10 | 11 | /** 12 | * 13 | * Round robin loadbalance. 14 | * 15 | * Created by shenhongxi on 2021/4/23. 16 | */ 17 | @SpiMeta(name = "roundrobin") 18 | public class RoundRobinLoadBalance extends AbstractLoadBalance { 19 | 20 | private AtomicInteger idx = new AtomicInteger(0); 21 | 22 | @Override 23 | protected Referer doSelect(Request request) { 24 | List> referers = getReferers(); 25 | 26 | int index = getNextNonNegative(); 27 | for (int i = 0; i < referers.size(); i++) { 28 | Referer ref = referers.get((i + index) % referers.size()); 29 | if (ref.isAvailable()) { 30 | return ref; 31 | } 32 | } 33 | return null; 34 | } 35 | 36 | @Override 37 | protected void doSelectToHolder(Request request, List> refersHolder) { 38 | List> referers = getReferers(); 39 | 40 | int index = getNextNonNegative(); 41 | for (int i = 0, count = 0; i < referers.size() && count < MAX_REFERER_COUNT; i++) { 42 | Referer referer = referers.get((i + index) % referers.size()); 43 | if (referer.isAvailable()) { 44 | refersHolder.add(referer); 45 | count++; 46 | } 47 | } 48 | } 49 | 50 | // get non-negative int 51 | private int getNextNonNegative() { 52 | return MathUtils.getNonNegative(idx.incrementAndGet()); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/codec/Codec.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.codec; 2 | 3 | import org.hongxi.jaws.common.extension.Scope; 4 | import org.hongxi.jaws.common.extension.Spi; 5 | import org.hongxi.jaws.transport.Channel; 6 | 7 | import java.io.IOException; 8 | 9 | /** 10 | * Created by shenhongxi on 2020/6/25. 11 | */ 12 | @Spi(scope = Scope.PROTOTYPE) 13 | public interface Codec { 14 | 15 | byte[] encode(Channel channel, Object message) throws IOException; 16 | 17 | Object decode(Channel channel, String remoteIp, byte[] data) throws IOException; 18 | } 19 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/codec/Serialization.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.codec; 2 | 3 | import org.hongxi.jaws.common.extension.Scope; 4 | import org.hongxi.jaws.common.extension.Spi; 5 | 6 | import java.io.IOException; 7 | 8 | /** 9 | * Created by shenhongxi on 2020/7/25. 10 | */ 11 | @Spi(scope = Scope.SINGLETON) 12 | public interface Serialization { 13 | 14 | byte[] serialize(Object obj) throws IOException; 15 | 16 | T deserialize(byte[] bytes, Class clz) throws IOException; 17 | 18 | byte[] serializeMulti(Object[] data) throws IOException; 19 | 20 | Object[] deserializeMulti(byte[] data, Class[] classes) throws IOException; 21 | 22 | /** 23 | * serializaion的唯一编号,用于传输协议中指定序列化方式。每种序列化的编号必须唯一。 24 | * @return 由于编码规范限制,序列化方式最大支持32种,因此返回值必须在0-31之间。 25 | */ 26 | int getSerializationNumber(); 27 | } 28 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/common/ChannelState.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.common; 2 | 3 | /** 4 | * Created by shenhongxi on 2020/6/25. 5 | */ 6 | public enum ChannelState { 7 | UNINIT(0), 8 | 9 | INIT(1), 10 | 11 | ALIVE(2), 12 | 13 | UNALIVE(3), 14 | 15 | CLOSE(4); 16 | 17 | private final int value; 18 | 19 | ChannelState(int value) { 20 | this.value = value; 21 | } 22 | 23 | public int value() { 24 | return value; 25 | } 26 | 27 | public boolean isUnInitState() { 28 | return this == UNINIT; 29 | } 30 | 31 | public boolean isInitState() { 32 | return this == INIT; 33 | } 34 | 35 | public boolean isAliveState() { 36 | return this == ALIVE; 37 | } 38 | 39 | public boolean isUnAliveState() { 40 | return this == UNALIVE; 41 | } 42 | 43 | public boolean isCloseState() { 44 | return this == CLOSE; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/common/FutureState.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.common; 2 | 3 | /** 4 | * future task state 5 | * 6 | * Created by shenhongxi on 2020/8/23. 7 | * 8 | */ 9 | public enum FutureState { 10 | /** the task is doing **/ 11 | DOING(0), 12 | /** the task is done **/ 13 | DONE(1), 14 | /** ths task is cancelled **/ 15 | CANCELLED(2); 16 | 17 | public final int value; 18 | 19 | FutureState(int value) { 20 | this.value = value; 21 | } 22 | 23 | public boolean isCancelledState() { 24 | return this == CANCELLED; 25 | } 26 | 27 | public boolean isDoneState() { 28 | return this == DONE; 29 | } 30 | 31 | public boolean isDoingState() { 32 | return this == DOING; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/common/extension/Activation.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.common.extension; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * Spi有多个实现时,可以根据条件进行过滤、排序后再返回。 7 | * 8 | * Created by shenhongxi on 2020/7/25. 9 | */ 10 | @Documented 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Target(ElementType.TYPE) 13 | public @interface Activation { 14 | 15 | /** seq号越小,在返回的list中的位置越靠前,尽量使用 0-100以内的数字 */ 16 | int sequence() default 20; 17 | 18 | /** spi 的key,获取spi列表时,根据key进行匹配,当key中存在待过滤的search-key时,匹配成功 */ 19 | String[] key() default ""; 20 | 21 | /** 是否支持重试的时候也调用 */ 22 | boolean retry() default true; 23 | } 24 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/common/extension/ActivationComparator.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.common.extension; 2 | 3 | import java.util.Comparator; 4 | 5 | /** 6 | * Created by shenhongxi on 2020/7/25. 7 | */ 8 | public class ActivationComparator implements Comparator { 9 | 10 | /** 11 | * sequence 大的排在后面,如果没有设置sequence的排到最前面 12 | */ 13 | @Override 14 | public int compare(T o1, T o2) { 15 | Activation p1 = o1.getClass().getAnnotation(Activation.class); 16 | Activation p2 = o2.getClass().getAnnotation(Activation.class); 17 | if (p1 == null) { 18 | return 1; 19 | } else if (p2 == null) { 20 | return -1; 21 | } else { 22 | return p1.sequence() - p2.sequence(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/common/extension/Scope.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.common.extension; 2 | 3 | public enum Scope { 4 | 5 | /** 6 | * 单例模式 7 | */ 8 | SINGLETON, 9 | 10 | /** 11 | * 多例模式 12 | */ 13 | PROTOTYPE 14 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/common/extension/Spi.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.common.extension; 2 | 3 | import java.lang.annotation.*; 4 | 5 | @Documented 6 | @Retention(RetentionPolicy.RUNTIME) 7 | @Target({ElementType.TYPE}) 8 | public @interface Spi { 9 | 10 | Scope scope() default Scope.PROTOTYPE; 11 | 12 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/common/extension/SpiMeta.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.common.extension; 2 | 3 | import java.lang.annotation.*; 4 | 5 | @Documented 6 | @Retention(RetentionPolicy.RUNTIME) 7 | @Target({ElementType.TYPE}) 8 | public @interface SpiMeta { 9 | String name() default ""; 10 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/common/threadpool/DefaultThreadFactory.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.common.threadpool; 2 | 3 | import org.hongxi.jaws.common.JawsConstants; 4 | 5 | import java.util.concurrent.ThreadFactory; 6 | import java.util.concurrent.atomic.AtomicInteger; 7 | 8 | /** 9 | * Created by shenhongxi on 2020/7/6. 10 | */ 11 | public class DefaultThreadFactory implements ThreadFactory { 12 | 13 | private static final AtomicInteger poolNumber = new AtomicInteger(1); 14 | private final ThreadGroup threadGroup; 15 | private final AtomicInteger currentThreadNumber = new AtomicInteger(1); 16 | private final String namePrefix; 17 | private int priority = Thread.NORM_PRIORITY; 18 | private boolean isDaemon = false; 19 | 20 | public DefaultThreadFactory() { 21 | this(JawsConstants.FRAMEWORK_NAME); 22 | } 23 | 24 | public DefaultThreadFactory(String prefix) { 25 | this(prefix, false); 26 | } 27 | 28 | public DefaultThreadFactory(String prefix, boolean isDaemon) { 29 | this(prefix, isDaemon, Thread.NORM_PRIORITY); 30 | } 31 | 32 | public DefaultThreadFactory(String prefix, boolean isDaemon, int priority) { 33 | SecurityManager s = System.getSecurityManager(); 34 | this.threadGroup = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); 35 | this.namePrefix = prefix + "-" + poolNumber.getAndIncrement() + "-thread-"; 36 | this.isDaemon = isDaemon; 37 | this.priority = priority; 38 | } 39 | 40 | @Override 41 | public Thread newThread(Runnable r) { 42 | Thread thread = new Thread(threadGroup, r, namePrefix + currentThreadNumber.getAndIncrement(), 0); 43 | thread.setDaemon(isDaemon); 44 | thread.setPriority(priority); 45 | return thread; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/common/threadpool/ExecutorQueue.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.common.threadpool; 2 | 3 | import java.util.concurrent.LinkedTransferQueue; 4 | import java.util.concurrent.RejectedExecutionException; 5 | 6 | /** 7 | * LinkedTransferQueue 能保证更高性能,相比与LinkedBlockingQueue有明显提升 8 | * 9 | *
10 |  * 		1) 不过LinkedTransferQueue的缺点是没有队列长度控制,需要在外层协助控制
11 |  * 
12 | * 13 | * Created by shenhongxi on 2020/7/6. 14 | * 15 | */ 16 | public class ExecutorQueue extends LinkedTransferQueue { 17 | private static final long serialVersionUID = -3392627914941820087L; 18 | 19 | private StandardThreadPoolExecutor threadPoolExecutor; 20 | 21 | public ExecutorQueue() { 22 | super(); 23 | } 24 | 25 | public void setThreadPoolExecutor(StandardThreadPoolExecutor threadPoolExecutor) { 26 | this.threadPoolExecutor = threadPoolExecutor; 27 | } 28 | 29 | public boolean force(Runnable command) { 30 | if (threadPoolExecutor.isShutdown()) { 31 | throw new RejectedExecutionException("Executor not running, cannot force a task into the queue"); 32 | } 33 | return super.offer(command); 34 | } 35 | 36 | public boolean offer(Runnable command) { 37 | int poolSize = threadPoolExecutor.getPoolSize(); 38 | 39 | if (poolSize == threadPoolExecutor.getMaximumPoolSize()) { 40 | return super.offer(command); 41 | } 42 | 43 | if (threadPoolExecutor.getSubmittedTasksCount() <= poolSize) { 44 | return super.offer(command); 45 | } 46 | 47 | if (poolSize < threadPoolExecutor.getMaximumPoolSize()) { 48 | return false; 49 | } 50 | 51 | return super.offer(command); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/common/util/CollectionUtils.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.common.util; 2 | 3 | import java.util.Collection; 4 | import java.util.Map; 5 | 6 | /** 7 | * Created by shenhongxi on 2020/7/30. 8 | */ 9 | public abstract class CollectionUtils { 10 | 11 | /** 12 | * Return {@code true} if the supplied Collection is {@code null} or empty. 13 | * Otherwise, return {@code false}. 14 | * @param collection the Collection to check 15 | * @return whether the given Collection is empty 16 | */ 17 | public static boolean isEmpty(Collection collection) { 18 | return (collection == null || collection.isEmpty()); 19 | } 20 | 21 | /** 22 | * Return {@code true} if the supplied Map is {@code null} or empty. 23 | * Otherwise, return {@code false}. 24 | * @param map the Map to check 25 | * @return whether the given Map is empty 26 | */ 27 | public static boolean isEmpty(Map map) { 28 | return (map == null || map.isEmpty()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/common/util/MathUtils.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.common.util; 2 | 3 | /** 4 | * Created by shenhongxi on 2020/7/28. 5 | */ 6 | public class MathUtils { 7 | 8 | /** 9 | * 针对int类型字符串进行解析,如果存在格式错误,则返回默认值(defaultValue) 10 | * Parse intStr, return defaultValue when numberFormatException occurs 11 | * @param intStr 12 | * @param defaultValue 13 | * @return 14 | */ 15 | public static int parseInt(String intStr, int defaultValue) { 16 | try { 17 | return Integer.parseInt(intStr); 18 | } catch (NumberFormatException e) { 19 | return defaultValue; 20 | } 21 | } 22 | 23 | /** 24 | * 针对long类型字符串进行解析,如果存在格式错误,则返回默认值(defaultValue) 25 | * Parse longStr, return defaultValue when numberFormatException occurs 26 | * @param longStr 27 | * @param defaultValue 28 | * @return 29 | */ 30 | public static long parseLong(String longStr, long defaultValue){ 31 | try { 32 | return Long.parseLong(longStr); 33 | } catch (NumberFormatException e) { 34 | return defaultValue; 35 | } 36 | } 37 | 38 | /** 39 | * 通过二进制位操作将originValue转化为非负数: 40 | * 0和正数返回本身 41 | * 负数通过二进制首位取反转化为正数或0(Integer.MIN_VALUE将转换为0) 42 | * return non-negative int value of originValue 43 | * @param originValue 44 | * @return positive int 45 | */ 46 | public static int getNonNegative(int originValue){ 47 | return 0x7fffffff & originValue; 48 | } 49 | 50 | /** 51 | * 通过二进制位操作将originValue转化为非负数: 52 | * 范围在[0-16777215] 之间 53 | * 54 | * @param originValue 55 | * @return 56 | */ 57 | public static int getNonNegativeRange24bit(int originValue) { 58 | return 0x00ffffff & originValue; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/common/util/RequestIdGenerator.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.common.util; 2 | 3 | import java.util.concurrent.atomic.AtomicLong; 4 | 5 | /** 6 | * 通过requestId能够知道大致请求的时间 7 | * 8 | *
 9 |  * 		目前是 currentTimeMillis * (2^20) + offset.incrementAndGet()
10 |  * 
11 |  * 		通过 requestId / (2^20 * 1000) 能够得到秒
12 |  *
13 |  * 
14 | * 15 | * Created by shenhongxi on 2020/8/22. 16 | * 17 | */ 18 | public class RequestIdGenerator { 19 | protected static final AtomicLong offset = new AtomicLong(0); 20 | protected static final int BITS = 20; 21 | protected static final long MAX_COUNT_PER_MILLIS = 1 << BITS; 22 | 23 | /** 24 | * 获取 requestId 25 | * 26 | * @return 27 | */ 28 | public static long getRequestId() { 29 | long currentTime = System.currentTimeMillis(); 30 | long count = offset.incrementAndGet(); 31 | while(count >= MAX_COUNT_PER_MILLIS){ 32 | synchronized (RequestIdGenerator.class){ 33 | if(offset.get() >= MAX_COUNT_PER_MILLIS){ 34 | offset.set(0); 35 | } 36 | } 37 | count = offset.incrementAndGet(); 38 | } 39 | return (currentTime << BITS) + count; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/common/util/StringTools.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.common.util; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.hongxi.jaws.common.JawsConstants; 5 | 6 | import java.io.UnsupportedEncodingException; 7 | import java.net.URLDecoder; 8 | import java.net.URLEncoder; 9 | import java.util.Map; 10 | import java.util.TreeMap; 11 | 12 | public class StringTools { 13 | 14 | public static int parseInteger(String intStr) { 15 | if (intStr == null) { 16 | return JawsConstants.DEFAULT_INT_VALUE; 17 | } 18 | try { 19 | return Integer.parseInt(intStr); 20 | } catch (NumberFormatException e) { 21 | return JawsConstants.DEFAULT_INT_VALUE; 22 | } 23 | } 24 | 25 | public static String urlEncode(String value) { 26 | if (StringUtils.isEmpty(value)) { 27 | return ""; 28 | } 29 | try { 30 | return URLEncoder.encode(value, JawsConstants.DEFAULT_CHARSET); 31 | } catch (UnsupportedEncodingException e) { 32 | throw new RuntimeException(e.getMessage(), e); 33 | } 34 | } 35 | 36 | public static String urlDecode(String value) { 37 | if (StringUtils.isBlank(value)) { 38 | return ""; 39 | } 40 | try { 41 | return URLDecoder.decode(value, JawsConstants.DEFAULT_CHARSET); 42 | } catch (UnsupportedEncodingException e) { 43 | throw new RuntimeException(e.getMessage(), e); 44 | } 45 | } 46 | 47 | public static String toQueryString(Map ps) { 48 | StringBuilder buf = new StringBuilder(); 49 | if (ps != null && ps.size() > 0) { 50 | for (Map.Entry entry : new TreeMap(ps).entrySet()) { 51 | String key = entry.getKey(); 52 | String value = entry.getValue(); 53 | if (key != null && key.length() > 0 && value != null && value.length() > 0) { 54 | if (buf.length() > 0) { 55 | buf.append("&"); 56 | } 57 | buf.append(key); 58 | buf.append("="); 59 | buf.append(value); 60 | } 61 | } 62 | } 63 | return buf.toString(); 64 | } 65 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/config/AbstractRefererConfig.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.config; 2 | 3 | /** 4 | * Created by shenhongxi on 2021/4/23. 5 | */ 6 | public abstract class AbstractRefererConfig extends AbstractInterfaceConfig { 7 | 8 | private static final long serialVersionUID = -8953815191278008453L; 9 | 10 | // 服务接口的mock类SLA 11 | protected String mean; 12 | protected String p90; 13 | protected String p99; 14 | protected String p999; 15 | protected String errorRate; 16 | protected Boolean asyncInitConnection; 17 | 18 | public String getMean() { 19 | return mean; 20 | } 21 | 22 | public void setMean(String mean) { 23 | this.mean = mean; 24 | } 25 | 26 | public String getP90() { 27 | return p90; 28 | } 29 | 30 | public void setP90(String p90) { 31 | this.p90 = p90; 32 | } 33 | 34 | public String getP99() { 35 | return p99; 36 | } 37 | 38 | public void setP99(String p99) { 39 | this.p99 = p99; 40 | } 41 | 42 | public String getP999() { 43 | return p999; 44 | } 45 | 46 | public void setP999(String p999) { 47 | this.p999 = p999; 48 | } 49 | 50 | public String getErrorRate() { 51 | return errorRate; 52 | } 53 | 54 | public void setErrorRate(String errorRate) { 55 | this.errorRate = errorRate; 56 | } 57 | 58 | public Boolean getAsyncInitConnection() { 59 | return asyncInitConnection; 60 | } 61 | 62 | public void setAsyncInitConnection(Boolean asyncInitConnection) { 63 | this.asyncInitConnection = asyncInitConnection; 64 | } 65 | 66 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/config/AbstractServiceConfig.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.config; 2 | 3 | /** 4 | * Created by shenhongxi on 2021/3/6. 5 | */ 6 | public abstract class AbstractServiceConfig extends AbstractInterfaceConfig { 7 | 8 | private static final long serialVersionUID = 6798383581370989643L; 9 | /** 10 | * 一个service可以按多个protocol提供服务,不同protocol使用不同port 利用export来设置protocol和port,格式如下: 11 | * protocol1:port1,protocol2:port2 12 | **/ 13 | protected String export; 14 | 15 | /** 一般不用设置,由服务自己获取,但如果有多个ip,而只想用指定ip,则可以在此处指定 */ 16 | protected String host; 17 | 18 | public String getExport() { 19 | return export; 20 | } 21 | 22 | public void setExport(String export) { 23 | this.export = export; 24 | } 25 | 26 | public String getHost() { 27 | return host; 28 | } 29 | 30 | public void setHost(String host) { 31 | this.host = host; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/config/BasicRefererInterfaceConfig.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.config; 2 | 3 | /** 4 | * Created by shenhongxi on 2021/4/23. 5 | */ 6 | public class BasicRefererInterfaceConfig extends AbstractRefererConfig { 7 | 8 | private static final long serialVersionUID = -418351068816874749L; 9 | /** 是否默认配置 */ 10 | private Boolean isDefault; 11 | 12 | public void setDefault(boolean isDefault) { 13 | this.isDefault = isDefault; 14 | } 15 | 16 | public Boolean isDefault() { 17 | return isDefault; 18 | } 19 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/config/BasicServiceInterfaceConfig.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.config; 2 | 3 | /** 4 | * Created by shenhongxi on 2021/3/6. 5 | */ 6 | public class BasicServiceInterfaceConfig extends AbstractServiceConfig { 7 | 8 | private static final long serialVersionUID = 12689211620290427L; 9 | /** 是否默认配置 */ 10 | private Boolean isDefault; 11 | 12 | public void setDefault(boolean isDefault) { 13 | this.isDefault = isDefault; 14 | } 15 | 16 | public Boolean isDefault() { 17 | return isDefault; 18 | } 19 | 20 | 21 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/config/ConfigUtils.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.config; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.hongxi.jaws.common.JawsConstants; 5 | import org.hongxi.jaws.common.util.MathUtils; 6 | import org.hongxi.jaws.exception.JawsServiceException; 7 | 8 | import java.util.Collections; 9 | import java.util.HashMap; 10 | import java.util.Map; 11 | 12 | /** 13 | * Config tools 14 | * 15 | * Created by shenhongxi on 2021/3/7. 16 | */ 17 | 18 | public class ConfigUtils { 19 | 20 | /** 21 | * export fomart: protocol1:port1,protocol2:port2 22 | * 23 | * @param export 24 | * @return 25 | */ 26 | public static Map parseExport(String export) { 27 | if (StringUtils.isBlank(export)) { 28 | return Collections.emptyMap(); 29 | } 30 | Map pps = new HashMap<>(); 31 | String[] protocolAndPorts = JawsConstants.COMMA_SPLIT_PATTERN.split(export); 32 | for (String pp : protocolAndPorts) { 33 | if (StringUtils.isBlank(pp)) { 34 | continue; 35 | } 36 | String[] ppDetail = pp.split(":"); 37 | if (ppDetail.length == 2) { 38 | pps.put(ppDetail[0], Integer.parseInt(ppDetail[1])); 39 | } else if (ppDetail.length == 1) { 40 | if (JawsConstants.PROTOCOL_INJVM.equals(ppDetail[0])) { 41 | pps.put(ppDetail[0], JawsConstants.DEFAULT_INT_VALUE); 42 | } else { 43 | int port = MathUtils.parseInt(ppDetail[0], 0); 44 | if (port <= 0) { 45 | throw new JawsServiceException("Export is malformed :" + export); 46 | } else { 47 | pps.put(JawsConstants.PROTOCOL_JAWS, port); 48 | } 49 | } 50 | } else { 51 | throw new JawsServiceException("Export is malformed :" + export); 52 | } 53 | } 54 | return pps; 55 | } 56 | 57 | public static String extractProtocols(String export) { 58 | Map protocols = parseExport(export); 59 | StringBuilder sb = new StringBuilder(16); 60 | for (String p : protocols.keySet()) { 61 | sb.append(p).append(JawsConstants.COMMA_SEPARATOR); 62 | } 63 | if (sb.length() > 0) { 64 | sb.deleteCharAt(sb.length() - 1); 65 | } 66 | return sb.toString(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/config/MethodConfig.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.config; 2 | 3 | import org.hongxi.jaws.config.annotation.ConfigDesc; 4 | 5 | /** 6 | * Created by shenhongxi on 2021/3/5. 7 | */ 8 | public class MethodConfig extends AbstractConfig { 9 | 10 | private static final long serialVersionUID = -1996115906176873773L; 11 | 12 | // 方法名 13 | private String name; 14 | // 超时时间 15 | private Integer requestTimeout; 16 | // 失败重试次数(默认为0,不重试) 17 | private Integer retries; 18 | // 最大并发调用 19 | // TODO 暂未实现 20 | private Integer actives; 21 | // 参数类型(逗号分隔) 22 | private String argumentTypes; 23 | private Integer slowThreshold; 24 | 25 | @ConfigDesc(excluded = true) 26 | public String getName() { 27 | return name; 28 | } 29 | 30 | public void setName(String name) { 31 | this.name = name; 32 | } 33 | 34 | public Integer getRequestTimeout() { 35 | return requestTimeout; 36 | } 37 | 38 | public void setRequestTimeout(Integer requestTimeout) { 39 | this.requestTimeout = requestTimeout; 40 | } 41 | 42 | public Integer getRetries() { 43 | return retries; 44 | } 45 | 46 | public void setRetries(Integer retries) { 47 | this.retries = retries; 48 | } 49 | 50 | public Integer getActives() { 51 | return actives; 52 | } 53 | 54 | public void setActives(Integer actives) { 55 | this.actives = actives; 56 | } 57 | 58 | @ConfigDesc(excluded = true) 59 | public String getArgumentTypes() { 60 | return argumentTypes; 61 | } 62 | 63 | public void setArgumentTypes(String argumentTypes) { 64 | this.argumentTypes = argumentTypes; 65 | } 66 | 67 | public Integer getSlowThreshold() { 68 | return slowThreshold; 69 | } 70 | 71 | public void setSlowThreshold(Integer slowThreshold) { 72 | this.slowThreshold = slowThreshold; 73 | } 74 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/config/annotation/ConfigDesc.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.config.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * 对配置参数的描述,用于通过配置方法进行配置属性自动装载 7 | * 8 | * Created by shenhongxi on 2021/3/5. 9 | */ 10 | @Documented 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Target(ElementType.METHOD) 13 | public @interface ConfigDesc { 14 | 15 | String key() default ""; 16 | 17 | boolean excluded() default false; 18 | 19 | boolean required() default false; 20 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/config/handler/ConfigHandler.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.config.handler; 2 | 3 | import org.hongxi.jaws.cluster.Cluster; 4 | import org.hongxi.jaws.cluster.support.ClusterSupport; 5 | import org.hongxi.jaws.common.extension.Scope; 6 | import org.hongxi.jaws.common.extension.Spi; 7 | import org.hongxi.jaws.rpc.Exporter; 8 | import org.hongxi.jaws.rpc.URL; 9 | 10 | import java.util.Collection; 11 | import java.util.List; 12 | 13 | /** 14 | * 15 | * Handle urls which are from config. 16 | * 17 | * Created by shenhongxi on 2021/3/6. 18 | */ 19 | @Spi(scope = Scope.SINGLETON) 20 | public interface ConfigHandler { 21 | 22 | Exporter export(Class interfaceClass, T ref, List registryUrls, URL serviceUrl); 23 | 24 | void unexport(List> exporters, Collection registryUrls); 25 | 26 | ClusterSupport buildClusterSupport(Class interfaceClass, List registryUrls, URL refUrl); 27 | 28 | T refer(Class interfaceClass, List> clusters, String proxyType); 29 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/exception/JawsAbstractException.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.exception; 2 | 3 | import org.hongxi.jaws.rpc.RpcContext; 4 | 5 | /** 6 | * Created by shenhongxi on 2020/6/26. 7 | */ 8 | public abstract class JawsAbstractException extends RuntimeException { 9 | private static final long serialVersionUID = -6842400415484759967L; 10 | 11 | protected JawsErrorMsg jawsErrorMsg = JawsErrorMsgConstants.FRAMEWORK_DEFAULT_ERROR; 12 | protected String errorMsg; 13 | 14 | public JawsAbstractException() { 15 | super(); 16 | } 17 | 18 | public JawsAbstractException(JawsErrorMsg jawsErrorMsg) { 19 | super(); 20 | this.jawsErrorMsg = jawsErrorMsg; 21 | } 22 | 23 | public JawsAbstractException(String message) { 24 | super(message); 25 | this.errorMsg = message; 26 | } 27 | 28 | public JawsAbstractException(String message, JawsErrorMsg jawsErrorMsg) { 29 | super(message); 30 | this.jawsErrorMsg = jawsErrorMsg; 31 | this.errorMsg = message; 32 | } 33 | 34 | public JawsAbstractException(String message, Throwable cause) { 35 | super(message, cause); 36 | this.errorMsg = message; 37 | } 38 | 39 | public JawsAbstractException(String message, Throwable cause, JawsErrorMsg jawsErrorMsg) { 40 | super(message, cause); 41 | this.jawsErrorMsg = jawsErrorMsg; 42 | this.errorMsg = message; 43 | } 44 | 45 | public JawsAbstractException(String message, JawsErrorMsg jawsErrorMsg, boolean writableStackTrace) { 46 | this(message, null, jawsErrorMsg, writableStackTrace); 47 | } 48 | 49 | public JawsAbstractException(String message, Throwable cause, JawsErrorMsg jawsErrorMsg, boolean writableStackTrace) { 50 | super(message, cause, false, writableStackTrace); 51 | this.jawsErrorMsg = jawsErrorMsg; 52 | this.errorMsg = message; 53 | } 54 | 55 | public JawsAbstractException(Throwable cause) { 56 | super(cause); 57 | } 58 | 59 | public JawsAbstractException(Throwable cause, JawsErrorMsg jawsErrorMsg) { 60 | super(cause); 61 | this.jawsErrorMsg = jawsErrorMsg; 62 | } 63 | 64 | @Override 65 | public String getMessage() { 66 | String message = getOriginMessage(); 67 | return String.format("error_message: %s, status: %d, error_code: %d, request_id: %s", 68 | message, getStatus(), getErrorCode(), RpcContext.getContext().getRequestId()); 69 | } 70 | 71 | public String getOriginMessage() { 72 | if (jawsErrorMsg == null) return super.getMessage(); 73 | 74 | if (errorMsg != null && !errorMsg.equals("")) { 75 | return errorMsg; 76 | } 77 | return jawsErrorMsg.getMessage(); 78 | } 79 | 80 | public int getStatus() { 81 | return jawsErrorMsg != null ? jawsErrorMsg.getStatus() : 0; 82 | } 83 | 84 | public int getErrorCode() { 85 | return jawsErrorMsg != null ? jawsErrorMsg.getErrorCode() : 0; 86 | } 87 | 88 | public JawsErrorMsg getJawsErrorMsg() { 89 | return jawsErrorMsg; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/exception/JawsBizException.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.exception; 2 | 3 | /** 4 | * Created by shenhongxi on 2020/7/26. 5 | */ 6 | public class JawsBizException extends JawsAbstractException { 7 | private static final long serialVersionUID = -9030222846555573201L; 8 | 9 | public JawsBizException() { 10 | super(JawsErrorMsgConstants.BIZ_DEFAULT_EXCEPTION); 11 | } 12 | 13 | public JawsBizException(JawsErrorMsg jawsErrorMsg) { 14 | super(jawsErrorMsg); 15 | } 16 | 17 | public JawsBizException(String message) { 18 | super(message, JawsErrorMsgConstants.BIZ_DEFAULT_EXCEPTION); 19 | } 20 | 21 | public JawsBizException(String message, JawsErrorMsg jawsErrorMsg) { 22 | super(message, jawsErrorMsg); 23 | } 24 | 25 | public JawsBizException(String message, Throwable cause) { 26 | super(message, cause, JawsErrorMsgConstants.BIZ_DEFAULT_EXCEPTION); 27 | } 28 | 29 | public JawsBizException(String message, Throwable cause, JawsErrorMsg jawsErrorMsg) { 30 | super(message, cause, jawsErrorMsg); 31 | } 32 | 33 | public JawsBizException(Throwable cause) { 34 | super(cause, JawsErrorMsgConstants.BIZ_DEFAULT_EXCEPTION); 35 | } 36 | 37 | public JawsBizException(Throwable cause, JawsErrorMsg jawsErrorMsg) { 38 | super(cause, jawsErrorMsg); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/exception/JawsErrorMsg.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.exception; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by shenhongxi on 2020/6/26. 7 | */ 8 | public class JawsErrorMsg implements Serializable { 9 | private static final long serialVersionUID = -5483348908144912517L; 10 | 11 | private int status; 12 | private int errorCode; 13 | private String message; 14 | 15 | public JawsErrorMsg(int status, int errorCode, String message) { 16 | this.status = status; 17 | this.errorCode = errorCode; 18 | this.message = message; 19 | } 20 | 21 | public int getStatus() { 22 | return status; 23 | } 24 | 25 | public int getErrorCode() { 26 | return errorCode; 27 | } 28 | 29 | public String getMessage() { 30 | return message; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/exception/JawsErrorMsgConstants.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.exception; 2 | 3 | /** 4 | * Created by shenhongxi on 2020/6/26. 5 | */ 6 | public class JawsErrorMsgConstants { 7 | 8 | // service error status 503 9 | public static final int SERVICE_DEFAULT_ERROR_CODE = 10001; 10 | public static final int SERVICE_REJECT_ERROR_CODE = 10002; 11 | public static final int SERVICE_TIMEOUT_ERROR_CODE = 10003; 12 | public static final int SERVICE_TASK_CANCEL_ERROR_CODE = 10004; 13 | // service error status 404 14 | public static final int SERVICE_NOT_FOUND_ERROR_CODE = 10101; 15 | // service error status 403 16 | public static final int SERVICE_REQUEST_LENGTH_OUT_OF_LIMIT_ERROR_CODE = 10201; 17 | 18 | // service error start 19 | 20 | public static final JawsErrorMsg SERVICE_DEFAULT_ERROR = 21 | new JawsErrorMsg(503, SERVICE_DEFAULT_ERROR_CODE, "service error"); 22 | public static final JawsErrorMsg SERVICE_REJECT = 23 | new JawsErrorMsg(503, SERVICE_REJECT_ERROR_CODE, "service reject"); 24 | public static final JawsErrorMsg SERVICE_NOT_FOUND = 25 | new JawsErrorMsg(404, SERVICE_NOT_FOUND_ERROR_CODE, "service not found"); 26 | public static final JawsErrorMsg SERVICE_TIMEOUT = 27 | new JawsErrorMsg(503, SERVICE_TIMEOUT_ERROR_CODE, "service request timeout"); 28 | 29 | // framework error 30 | public static final int FRAMEWORK_DEFAULT_ERROR_CODE = 20001; 31 | public static final int FRAMEWORK_ENCODE_ERROR_CODE = 20002; 32 | public static final int FRAMEWORK_DECODE_ERROR_CODE = 20003; 33 | public static final int FRAMEWORK_INIT_ERROR_CODE = 20004; 34 | public static final int FRAMEWORK_EXPORT_ERROR_CODE = 20005; 35 | public static final int FRAMEWORK_REGISTER_ERROR_CODE = 20008; 36 | // biz error 37 | public static final int BIZ_DEFAULT_ERROR_CODE = 30001; 38 | 39 | public static final JawsErrorMsg FRAMEWORK_DEFAULT_ERROR = 40 | new JawsErrorMsg(503, FRAMEWORK_DEFAULT_ERROR_CODE, "framework default error"); 41 | 42 | public static final JawsErrorMsg FRAMEWORK_ENCODE_ERROR = 43 | new JawsErrorMsg(503, FRAMEWORK_ENCODE_ERROR_CODE, "framework encode error"); 44 | public static final JawsErrorMsg FRAMEWORK_DECODE_ERROR = 45 | new JawsErrorMsg(503, FRAMEWORK_DECODE_ERROR_CODE, "framework decode error"); 46 | public static final JawsErrorMsg FRAMEWORK_INIT_ERROR = 47 | new JawsErrorMsg(500, FRAMEWORK_INIT_ERROR_CODE, "framework init error"); 48 | public static final JawsErrorMsg FRAMEWORK_EXPORT_ERROR = 49 | new JawsErrorMsg(503, FRAMEWORK_EXPORT_ERROR_CODE, "framework export error"); 50 | 51 | public static final JawsErrorMsg BIZ_DEFAULT_EXCEPTION = 52 | new JawsErrorMsg(503, BIZ_DEFAULT_ERROR_CODE, "provider error"); 53 | } 54 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/exception/JawsFrameworkException.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.exception; 2 | 3 | /** 4 | * Created by shenhongxi on 2020/6/26. 5 | */ 6 | public class JawsFrameworkException extends JawsAbstractException { 7 | private static final long serialVersionUID = -6860263607854518306L; 8 | 9 | public JawsFrameworkException() { 10 | super(JawsErrorMsgConstants.FRAMEWORK_DEFAULT_ERROR); 11 | } 12 | 13 | public JawsFrameworkException(JawsErrorMsg jawsErrorMsg) { 14 | super(jawsErrorMsg); 15 | } 16 | 17 | public JawsFrameworkException(String message) { 18 | super(message, JawsErrorMsgConstants.FRAMEWORK_DEFAULT_ERROR); 19 | } 20 | 21 | public JawsFrameworkException(String message, JawsErrorMsg jawsErrorMsg) { 22 | super(message, jawsErrorMsg); 23 | } 24 | 25 | public JawsFrameworkException(String message, Throwable cause) { 26 | super(message, cause, JawsErrorMsgConstants.FRAMEWORK_DEFAULT_ERROR); 27 | } 28 | 29 | public JawsFrameworkException(String message, Throwable cause, JawsErrorMsg jawsErrorMsg) { 30 | super(message, cause, jawsErrorMsg); 31 | } 32 | 33 | public JawsFrameworkException(Throwable cause) { 34 | super(cause, JawsErrorMsgConstants.FRAMEWORK_DEFAULT_ERROR); 35 | } 36 | 37 | public JawsFrameworkException(Throwable cause, JawsErrorMsg jawsErrorMsg) { 38 | super(cause, jawsErrorMsg); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/exception/JawsServiceException.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.exception; 2 | 3 | /** 4 | * Created by shenhongxi on 2020/7/25. 5 | */ 6 | public class JawsServiceException extends JawsAbstractException { 7 | private static final long serialVersionUID = 167949946546769763L; 8 | 9 | public JawsServiceException() { 10 | super(JawsErrorMsgConstants.SERVICE_DEFAULT_ERROR); 11 | } 12 | 13 | public JawsServiceException(JawsErrorMsg jawsErrorMsg) { 14 | super(jawsErrorMsg); 15 | } 16 | 17 | public JawsServiceException(String message) { 18 | super(message, JawsErrorMsgConstants.SERVICE_DEFAULT_ERROR); 19 | } 20 | 21 | public JawsServiceException(String message, JawsErrorMsg jawsErrorMsg) { 22 | super(message, jawsErrorMsg); 23 | } 24 | 25 | public JawsServiceException(String message, JawsErrorMsg jawsErrorMsg, boolean writableStackTrace) { 26 | super(message, jawsErrorMsg, writableStackTrace); 27 | } 28 | 29 | public JawsServiceException(String message, Throwable cause) { 30 | super(message, cause, JawsErrorMsgConstants.SERVICE_DEFAULT_ERROR); 31 | } 32 | 33 | public JawsServiceException(String message, Throwable cause, JawsErrorMsg jawsErrorMsg) { 34 | super(message, cause, jawsErrorMsg); 35 | } 36 | 37 | public JawsServiceException(Throwable cause) { 38 | super(cause, JawsErrorMsgConstants.SERVICE_DEFAULT_ERROR); 39 | } 40 | 41 | public JawsServiceException(Throwable cause, JawsErrorMsg jawsErrorMsg) { 42 | super(cause, jawsErrorMsg); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/filter/Filter.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.filter; 2 | 3 | import org.hongxi.jaws.common.extension.Spi; 4 | import org.hongxi.jaws.rpc.Caller; 5 | import org.hongxi.jaws.rpc.Request; 6 | import org.hongxi.jaws.rpc.Response; 7 | 8 | /** 9 | * 10 | * filter before transport. 11 | * 12 | * Created by shenhongxi on 2021/3/6. 13 | */ 14 | @Spi 15 | public interface Filter { 16 | 17 | Response filter(Caller caller, Request request); 18 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/filter/InitializableFilter.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.filter; 2 | 3 | import org.hongxi.jaws.common.extension.Scope; 4 | import org.hongxi.jaws.common.extension.Spi; 5 | import org.hongxi.jaws.rpc.Caller; 6 | 7 | /** 8 | * Created by shenhongxi on 2021/3/6. 9 | */ 10 | @Spi(scope = Scope.PROTOTYPE) 11 | public interface InitializableFilter extends Filter { 12 | /** 13 | * init with caller eg. referer or provider be careful when using SINGLETON scope 14 | * 15 | * @param caller 16 | */ 17 | void init(Caller caller); 18 | 19 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/protocol/jaws/DefaultRpcReferer.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.protocol.jaws; 2 | 3 | import org.hongxi.jaws.common.URLParamType; 4 | import org.hongxi.jaws.common.extension.ExtensionLoader; 5 | import org.hongxi.jaws.exception.JawsServiceException; 6 | import org.hongxi.jaws.rpc.*; 7 | import org.hongxi.jaws.transport.Client; 8 | import org.hongxi.jaws.transport.EndpointFactory; 9 | import org.hongxi.jaws.transport.TransportException; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | /** 14 | * Created by shenhongxi on 2021/4/21. 15 | */ 16 | public class DefaultRpcReferer extends AbstractReferer { 17 | 18 | private static final Logger log = LoggerFactory.getLogger(DefaultRpcReferer.class); 19 | 20 | protected Client client; 21 | protected EndpointFactory endpointFactory; 22 | 23 | public DefaultRpcReferer(Class clz, URL url, URL serviceUrl) { 24 | super(clz, url, serviceUrl); 25 | 26 | endpointFactory = 27 | ExtensionLoader.getExtensionLoader(EndpointFactory.class).getExtension( 28 | url.getParameter(URLParamType.endpointFactory.getName(), URLParamType.endpointFactory.value())); 29 | 30 | client = endpointFactory.createClient(url); 31 | } 32 | 33 | @Override 34 | protected Response doCall(Request request) { 35 | try { 36 | // 为了能够实现跨group请求,需要使用server端的group。 37 | request.setAttachment(URLParamType.group.getName(), serviceUrl.getGroup()); 38 | return client.request(request); 39 | } catch (TransportException exception) { 40 | throw new JawsServiceException("DefaultRpcReferer call Error: url=" + url.getUri(), exception); 41 | } 42 | } 43 | 44 | @Override 45 | protected void decrActiveCount(Request request, Response response) { 46 | if (!(response instanceof Future)) { 47 | activeRefererCount.decrementAndGet(); 48 | return; 49 | } 50 | 51 | Future future = (Future) response; 52 | 53 | future.addListener(new FutureListener() { 54 | @Override 55 | public void operationComplete(Future future) throws Exception { 56 | activeRefererCount.decrementAndGet(); 57 | } 58 | }); 59 | } 60 | 61 | @Override 62 | protected boolean doInit() { 63 | boolean result = client.open(); 64 | 65 | return result; 66 | } 67 | 68 | @Override 69 | public boolean isAvailable() { 70 | return client.isAvailable(); 71 | } 72 | 73 | @Override 74 | public void destroy() { 75 | endpointFactory.safeReleaseResource(client, url); 76 | log.info("DefaultRpcReferer destory client: url={}", url); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/protocol/jaws/JawsProtocol.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.protocol.jaws; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.hongxi.jaws.common.JawsConstants; 5 | import org.hongxi.jaws.common.URLParamType; 6 | import org.hongxi.jaws.common.extension.SpiMeta; 7 | import org.hongxi.jaws.exception.JawsServiceException; 8 | import org.hongxi.jaws.protocol.AbstractProtocol; 9 | import org.hongxi.jaws.rpc.*; 10 | import org.hongxi.jaws.transport.ProviderMessageRouter; 11 | import org.hongxi.jaws.transport.TransportException; 12 | 13 | import java.util.concurrent.ConcurrentHashMap; 14 | 15 | /** 16 | * Created by shenhongxi on 2021/4/21. 17 | */ 18 | @SpiMeta(name = "jaws") 19 | public class JawsProtocol extends AbstractProtocol { 20 | 21 | public static final String DEFAULT_CODEC = "jaws"; 22 | private ConcurrentHashMap ipPort2RequestRouter = new ConcurrentHashMap<>(); 23 | 24 | @Override 25 | protected Exporter createExporter(Provider provider, URL url) { 26 | setDefaultCodec(url); 27 | return new DefaultRpcExporter(provider, url, this.ipPort2RequestRouter, this.exporterMap); 28 | } 29 | 30 | @Override 31 | protected Referer createReferer(Class clz, URL url, URL serviceUrl) { 32 | setDefaultCodec(url); 33 | return new V2RpcReferer(clz, url, serviceUrl); 34 | } 35 | 36 | private void setDefaultCodec(URL url) { 37 | String codec = url.getParameter(URLParamType.codec.getName()); 38 | if (StringUtils.isBlank(codec)) { 39 | url.getParameters().put(URLParamType.codec.getName(), DEFAULT_CODEC); 40 | } 41 | } 42 | 43 | /** 44 | * rpc referer 45 | * 46 | * @param 47 | */ 48 | class V2RpcReferer extends DefaultRpcReferer { 49 | 50 | public V2RpcReferer(Class clz, URL url, URL serviceUrl) { 51 | super(clz, url, serviceUrl); 52 | } 53 | 54 | @Override 55 | protected Response doCall(Request request) { 56 | try { 57 | // use server end group 58 | request.setAttachment(URLParamType.group.getName(), serviceUrl.getGroup()); 59 | request.setAttachment(JawsConstants.JAWS_PROXY_PROTOCOL, this.url.getProtocol()); // add proxy protocol for request agent 60 | return client.request(request); 61 | } catch (TransportException exception) { 62 | throw new JawsServiceException("DefaultRpcReferer call Error: url=" + url.getUri(), exception); 63 | } 64 | } 65 | 66 | } 67 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/protocol/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by shenhongxi on 2020/7/25. 3 | */ 4 | package org.hongxi.jaws.protocol; -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/proxy/CommonHandler.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.proxy; 2 | 3 | import org.hongxi.jaws.rpc.Request; 4 | 5 | /** 6 | * Created by shenhongxi on 2021/4/23. 7 | */ 8 | public interface CommonHandler { 9 | /** 10 | * call a service method with general handler 11 | * 12 | * @param methodName the method name of remote service 13 | * @param arguments an array of objects containing the values of the arguments passed in the method invocation 14 | * @param returnType the class type that the method returns 15 | * @return 16 | * @throws Throwable 17 | */ 18 | Object call(String methodName, Object[] arguments, Class returnType) throws Throwable; 19 | 20 | /** 21 | * async call a service with general handler 22 | * 23 | * @param methodName 24 | * @param arguments 25 | * @param returnType 26 | * @return 27 | * @throws Throwable 28 | */ 29 | Object asyncCall(String methodName, Object[] arguments, Class returnType) throws Throwable; 30 | 31 | /** 32 | * call a service method with request 33 | * 34 | * @param request 35 | * @param returnType 36 | * @return 37 | */ 38 | Object call(Request request, Class returnType) throws Throwable; 39 | 40 | /** 41 | * async call a service with request 42 | * 43 | * @param request 44 | * @param returnType 45 | * @return 46 | */ 47 | Object asyncCall(Request request, Class returnType) throws Throwable; 48 | 49 | /** 50 | * build request with methodName and arguments 51 | * 52 | * @param methodName 53 | * @param arguments 54 | * @return 55 | */ 56 | Request buildRequest(String methodName, Object[] arguments); 57 | 58 | /** 59 | * build request with interfaceName, methodName and arguments 60 | * 61 | * @param interfaceName 62 | * @param methodName 63 | * @param arguments 64 | * @return 65 | */ 66 | Request buildRequest(String interfaceName, String methodName, Object[] arguments); 67 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/proxy/ProxyFactory.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.proxy; 2 | 3 | import org.hongxi.jaws.cluster.Cluster; 4 | import org.hongxi.jaws.common.extension.Spi; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * Created by shenhongxi on 2021/4/23. 10 | */ 11 | @Spi 12 | public interface ProxyFactory { 13 | 14 | T getProxy(Class clz, List> clusters); 15 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/proxy/RefererCommonHandler.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.proxy; 2 | 3 | import org.hongxi.jaws.cluster.Cluster; 4 | import org.hongxi.jaws.common.util.RequestIdGenerator; 5 | import org.hongxi.jaws.rpc.DefaultRequest; 6 | import org.hongxi.jaws.rpc.Request; 7 | 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | /** 12 | * Created by shenhongxi on 2021/4/23. 13 | */ 14 | public class RefererCommonHandler extends AbstractRefererHandler implements CommonHandler { 15 | 16 | public RefererCommonHandler(String interfaceName, List> clusters) { 17 | this.interfaceName = interfaceName; 18 | this.clusters = clusters; 19 | init(); 20 | } 21 | 22 | public Object call(String methodName, Object[] arguments, Class returnType, Map attachments, boolean async) throws Throwable { 23 | DefaultRequest request = new DefaultRequest(); 24 | request.setRequestId(RequestIdGenerator.getRequestId()); 25 | request.setInterfaceName(interfaceName); 26 | request.setMethodName(methodName); 27 | request.setArguments(arguments); 28 | request.setAttachments(attachments); 29 | return invokeRequest(request, returnType, async); 30 | } 31 | 32 | @Override 33 | public Object call(String methodName, Object[] arguments, Class returnType) throws Throwable { 34 | return call(methodName, arguments, returnType, null, false); 35 | } 36 | 37 | @Override 38 | public Object asyncCall(String methodName, Object[] arguments, Class returnType) throws Throwable { 39 | return call(methodName, arguments, returnType, null, true); 40 | } 41 | 42 | @Override 43 | public Object call(Request request, Class returnType) throws Throwable { 44 | return invokeRequest(request, returnType, false); 45 | } 46 | 47 | @Override 48 | public Object asyncCall(Request request, Class returnType) throws Throwable { 49 | return invokeRequest(request, returnType, true); 50 | } 51 | 52 | @Override 53 | public Request buildRequest(String methodName, Object[] arguments) { 54 | return buildRequest(interfaceName, methodName, arguments); 55 | } 56 | 57 | @Override 58 | public Request buildRequest(String interfaceName, String methodName, Object[] arguments) { 59 | DefaultRequest request = new DefaultRequest(); 60 | request.setRequestId(RequestIdGenerator.getRequestId()); 61 | request.setInterfaceName(interfaceName); 62 | request.setMethodName(methodName); 63 | request.setArguments(arguments); 64 | return request; 65 | } 66 | 67 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/proxy/support/CommonProxyFactory.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.proxy.support; 2 | 3 | import org.hongxi.jaws.cluster.Cluster; 4 | import org.hongxi.jaws.common.extension.SpiMeta; 5 | import org.hongxi.jaws.proxy.ProxyFactory; 6 | import org.hongxi.jaws.proxy.RefererCommonHandler; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * common proxy 12 | * 13 | * Created by shenhongxi on 2021/4/23. 14 | */ 15 | @SpiMeta(name = "common") 16 | public class CommonProxyFactory implements ProxyFactory { 17 | 18 | @Override 19 | @SuppressWarnings("unchecked") 20 | public T getProxy(Class clz, List> clusters) { 21 | return (T) new RefererCommonHandler(clusters.get(0).getUrl().getPath(), clusters); 22 | } 23 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/proxy/support/JdkProxyFactory.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.proxy.support; 2 | 3 | import org.hongxi.jaws.cluster.Cluster; 4 | import org.hongxi.jaws.common.extension.SpiMeta; 5 | import org.hongxi.jaws.proxy.ProxyFactory; 6 | import org.hongxi.jaws.proxy.RefererInvocationHandler; 7 | 8 | import java.lang.reflect.Proxy; 9 | import java.util.List; 10 | 11 | /** 12 | * jdk proxy 13 | * 14 | * Created by shenhongxi on 2021/4/23. 15 | */ 16 | @SpiMeta(name = "jdk") 17 | public class JdkProxyFactory implements ProxyFactory { 18 | 19 | @Override 20 | @SuppressWarnings("unchecked") 21 | public T getProxy(Class clz, List> clusters) { 22 | return (T) Proxy.newProxyInstance(clz.getClassLoader(), new Class[]{clz}, new RefererInvocationHandler<>(clz, clusters)); 23 | } 24 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/registry/DiscoveryService.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.registry; 2 | 3 | import org.hongxi.jaws.rpc.URL; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Discovery service. 9 | * 10 | * Created by shenhongxi on 2021/3/7. 11 | */ 12 | 13 | public interface DiscoveryService { 14 | 15 | void subscribe(URL url, NotifyListener listener); 16 | 17 | void unsubscribe(URL url, NotifyListener listener); 18 | 19 | List discover(URL url); 20 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/registry/NotifyListener.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.registry; 2 | 3 | import org.hongxi.jaws.rpc.URL; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Notify when service changed. 9 | * 10 | * Created by shenhongxi on 2021/3/7. 11 | */ 12 | 13 | public interface NotifyListener { 14 | 15 | void notify(URL registryUrl, List urls); 16 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/registry/Registry.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.registry; 2 | 3 | import org.hongxi.jaws.common.extension.Scope; 4 | import org.hongxi.jaws.common.extension.Spi; 5 | import org.hongxi.jaws.rpc.URL; 6 | 7 | /** 8 | * Used to register and discover. 9 | * 10 | * Created by shenhongxi on 2021/3/7. 11 | */ 12 | @Spi(scope = Scope.SINGLETON) 13 | public interface Registry extends RegistryService, DiscoveryService { 14 | 15 | URL getUrl(); 16 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/registry/RegistryFactory.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.registry; 2 | 3 | import org.hongxi.jaws.common.extension.Scope; 4 | import org.hongxi.jaws.common.extension.Spi; 5 | import org.hongxi.jaws.rpc.URL; 6 | 7 | /** 8 | * To create registry 9 | * 10 | * Created by shenhongxi on 2021/3/7. 11 | */ 12 | @Spi(scope = Scope.SINGLETON) 13 | public interface RegistryFactory { 14 | 15 | Registry getRegistry(URL url); 16 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/registry/RegistryService.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.registry; 2 | 3 | import org.hongxi.jaws.rpc.URL; 4 | 5 | import java.util.Collection; 6 | 7 | /** 8 | * Register service to Restery center. 9 | * 10 | * Created by shenhongxi on 2021/3/5. 11 | */ 12 | 13 | public interface RegistryService { 14 | 15 | /** 16 | * register service to registry 17 | * 18 | * @param url 19 | */ 20 | void register(URL url); 21 | 22 | /** 23 | * unregister service to registry 24 | * 25 | * @param url 26 | */ 27 | void unregister(URL url); 28 | 29 | /** 30 | * set service status to available, so clients could use it 31 | * 32 | * @param url service url to be available, null means all services 33 | */ 34 | void available(URL url); 35 | 36 | /** 37 | * set service status to unavailable, client should not discover services of unavailable state 38 | * 39 | * @param url service url to be unavailable, null means all services 40 | */ 41 | void unavailable(URL url); 42 | 43 | Collection getRegisteredServiceUrls(); 44 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/registry/support/AbstractRegistryFactory.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.registry.support; 2 | 3 | import org.hongxi.jaws.exception.JawsErrorMsgConstants; 4 | import org.hongxi.jaws.exception.JawsFrameworkException; 5 | import org.hongxi.jaws.registry.Registry; 6 | import org.hongxi.jaws.registry.RegistryFactory; 7 | import org.hongxi.jaws.rpc.URL; 8 | 9 | import java.util.concurrent.ConcurrentHashMap; 10 | import java.util.concurrent.locks.ReentrantLock; 11 | 12 | /** 13 | * Create and cache registry. 14 | * 15 | * Created by shenhongxi on 2021/4/21. 16 | */ 17 | 18 | public abstract class AbstractRegistryFactory implements RegistryFactory { 19 | 20 | private static ConcurrentHashMap registries = new ConcurrentHashMap(); 21 | 22 | private static final ReentrantLock lock = new ReentrantLock(); 23 | 24 | protected String getRegistryUri(URL url) { 25 | return url.getUri(); 26 | } 27 | 28 | @Override 29 | public Registry getRegistry(URL url) { 30 | String registryUri = getRegistryUri(url); 31 | try { 32 | lock.lock(); 33 | Registry registry = registries.get(registryUri); 34 | if (registry != null) { 35 | return registry; 36 | } 37 | registry = createRegistry(url); 38 | if (registry == null) { 39 | throw new JawsFrameworkException("Create registry false for url:" + url, JawsErrorMsgConstants.FRAMEWORK_INIT_ERROR); 40 | } 41 | registries.put(registryUri, registry); 42 | return registry; 43 | } catch (Exception e) { 44 | throw new JawsFrameworkException("Create registry false for url:" + url, e, JawsErrorMsgConstants.FRAMEWORK_INIT_ERROR); 45 | } finally { 46 | lock.unlock(); 47 | } 48 | } 49 | 50 | protected abstract Registry createRegistry(URL url); 51 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/registry/support/DirectRegistryFactory.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.registry.support; 2 | 3 | import org.hongxi.jaws.common.extension.SpiMeta; 4 | import org.hongxi.jaws.registry.Registry; 5 | import org.hongxi.jaws.rpc.URL; 6 | 7 | /** 8 | * Created by shenhongxi on 2021/4/22. 9 | */ 10 | @SpiMeta(name = "direct") 11 | public class DirectRegistryFactory extends AbstractRegistryFactory { 12 | 13 | @Override 14 | protected Registry createRegistry(URL url) { 15 | return new DirectRegistry(url); 16 | } 17 | 18 | 19 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/registry/support/LocalRegistryFactory.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.registry.support; 2 | 3 | import org.hongxi.jaws.common.JawsConstants; 4 | import org.hongxi.jaws.common.extension.ExtensionLoader; 5 | import org.hongxi.jaws.common.extension.SpiMeta; 6 | import org.hongxi.jaws.registry.Registry; 7 | import org.hongxi.jaws.rpc.URL; 8 | 9 | /** 10 | * Created by shenhongxi on 2021/4/21. 11 | */ 12 | @SpiMeta(name = "local") 13 | public class LocalRegistryFactory extends AbstractRegistryFactory { 14 | 15 | @Override 16 | protected Registry createRegistry(URL url) { 17 | return ExtensionLoader.getExtensionLoader(Registry.class).getExtension(JawsConstants.REGISTRY_PROTOCOL_LOCAL); 18 | } 19 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/registry/support/command/CommandListener.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.registry.support.command; 2 | 3 | import org.hongxi.jaws.rpc.URL; 4 | 5 | /** 6 | * Created by shenhongxi on 2021/4/23. 7 | */ 8 | public interface CommandListener { 9 | 10 | void notifyCommand(URL refUrl, String commandString); 11 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/registry/support/command/RpcCommand.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.registry.support.command; 2 | 3 | import java.util.Collections; 4 | import java.util.List; 5 | 6 | /** 7 | * Created by shenhongxi on 2021/4/23. 8 | */ 9 | public class RpcCommand { 10 | 11 | private List clientCommandList; 12 | 13 | public void sort() { 14 | Collections.sort(clientCommandList, (o1, o2) -> { 15 | Integer i1 = o1.getIndex(); 16 | Integer i2 = o2.getIndex(); 17 | if (i1 == null) { 18 | return -1; 19 | } 20 | if (i2 == null) { 21 | return 1; 22 | } 23 | int r = i1.compareTo(i2); 24 | return r; 25 | }); 26 | } 27 | 28 | public static class ClientCommand { 29 | private Integer index; 30 | private String version; 31 | private String dc; 32 | private String pattern; 33 | private List mergeGroups; 34 | // 路由规则,当有多个匹配时,按顺序依次过滤结果 35 | private List routeRules; 36 | private String remark; 37 | 38 | public Integer getIndex() { 39 | return index; 40 | } 41 | 42 | public void setIndex(Integer index) { 43 | this.index = index; 44 | } 45 | 46 | public String getVersion() { 47 | return version; 48 | } 49 | 50 | public void setVersion(String version) { 51 | this.version = version; 52 | } 53 | 54 | public String getDc() { 55 | return dc; 56 | } 57 | 58 | public void setDc(String dc) { 59 | this.dc = dc; 60 | } 61 | 62 | public String getPattern() { 63 | return pattern; 64 | } 65 | 66 | public void setPattern(String pattern) { 67 | this.pattern = pattern; 68 | } 69 | 70 | public List getMergeGroups() { 71 | return mergeGroups; 72 | } 73 | 74 | public void setMergeGroups(List mergeGroups) { 75 | this.mergeGroups = mergeGroups; 76 | } 77 | 78 | public List getRouteRules() { 79 | return routeRules; 80 | } 81 | 82 | public void setRouteRules(List routeRules) { 83 | this.routeRules = routeRules; 84 | } 85 | 86 | public String getRemark() { 87 | return remark; 88 | } 89 | 90 | public void setRemark(String remark) { 91 | this.remark = remark; 92 | } 93 | } 94 | 95 | public List getClientCommandList() { 96 | return clientCommandList; 97 | } 98 | 99 | public void setClientCommandList(List clientCommandList) { 100 | this.clientCommandList = clientCommandList; 101 | } 102 | 103 | public static class ServerCommand { 104 | 105 | } 106 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/registry/support/command/ServiceListener.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.registry.support.command; 2 | 3 | import org.hongxi.jaws.rpc.URL; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Created by shenhongxi on 2021/4/23. 9 | */ 10 | public interface ServiceListener { 11 | 12 | void notifyService(URL refUrl, URL registryUrl, List urls); 13 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/rpc/AbstractExporter.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.rpc; 2 | 3 | /** 4 | * Created by shenhongxi on 2021/4/21. 5 | */ 6 | public abstract class AbstractExporter extends AbstractNode implements Exporter { 7 | protected Provider provider; 8 | 9 | public AbstractExporter(Provider provider, URL url) { 10 | super(url); 11 | this.provider = provider; 12 | } 13 | 14 | public Provider getProvider() { 15 | return provider; 16 | } 17 | 18 | @Override 19 | public String desc() { 20 | return "[" + this.getClass().getSimpleName() + "] url=" + url; 21 | } 22 | 23 | /** 24 | * update real listened port 25 | * @param port 26 | */ 27 | protected void updateRealServerPort(int port){ 28 | getUrl().setPort(port); 29 | } 30 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/rpc/AbstractNode.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.rpc; 2 | 3 | import org.hongxi.jaws.exception.JawsErrorMsgConstants; 4 | import org.hongxi.jaws.exception.JawsFrameworkException; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | /** 9 | * Created by shenhongxi on 2021/4/21. 10 | */ 11 | public abstract class AbstractNode implements Node { 12 | 13 | private static final Logger log = LoggerFactory.getLogger(AbstractNode.class); 14 | 15 | protected URL url; 16 | 17 | protected volatile boolean init = false; 18 | protected volatile boolean available = false; 19 | 20 | public AbstractNode(URL url) { 21 | this.url = url; 22 | } 23 | 24 | @Override 25 | public synchronized void init() { 26 | if (init) { 27 | log.warn(this.getClass().getSimpleName() + " node already init: " + desc()); 28 | return; 29 | } 30 | 31 | boolean result = doInit(); 32 | 33 | if (!result) { 34 | log.error("{} node init Error: {}", this.getClass().getSimpleName(), desc()); 35 | throw new JawsFrameworkException(this.getClass().getSimpleName() + " node init Error: " + desc(), 36 | JawsErrorMsgConstants.FRAMEWORK_INIT_ERROR); 37 | } else { 38 | log.info("{} node init Success: {}", this.getClass().getSimpleName(), desc()); 39 | 40 | init = true; 41 | available = true; 42 | } 43 | } 44 | 45 | protected abstract boolean doInit(); 46 | 47 | @Override 48 | public boolean isAvailable() { 49 | return available; 50 | } 51 | 52 | public void setAvailable(boolean available) { 53 | this.available = available; 54 | } 55 | 56 | public URL getUrl() { 57 | return url; 58 | } 59 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/rpc/AbstractProvider.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.rpc; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.hongxi.jaws.common.util.ReflectUtils; 5 | 6 | import java.lang.reflect.Method; 7 | import java.util.ArrayList; 8 | import java.util.HashMap; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | /** 13 | * Created by shenhongxi on 2021/3/7. 14 | */ 15 | public abstract class AbstractProvider implements Provider { 16 | protected Class clz; 17 | protected URL url; 18 | protected boolean alive = false; 19 | protected boolean close = false; 20 | 21 | protected Map methodMap = new HashMap<>(); 22 | 23 | public AbstractProvider(URL url, Class clz) { 24 | this.url = url; 25 | this.clz = clz; 26 | 27 | initMethodMap(clz); 28 | } 29 | 30 | @Override 31 | public Response call(Request request) { 32 | return invoke(request); 33 | } 34 | 35 | protected abstract Response invoke(Request request); 36 | 37 | @Override 38 | public void init() { 39 | alive = true; 40 | } 41 | 42 | @Override 43 | public void destroy() { 44 | alive = false; 45 | close = true; 46 | } 47 | 48 | @Override 49 | public boolean isAvailable() { 50 | return alive; 51 | } 52 | 53 | @Override 54 | public String desc() { 55 | if (url != null) { 56 | return url.toString(); 57 | } 58 | 59 | return null; 60 | } 61 | 62 | @Override 63 | public URL getUrl() { 64 | return url; 65 | } 66 | 67 | @Override 68 | public Class getInterface() { 69 | return clz; 70 | } 71 | 72 | @Override 73 | public Method lookupMethod(String methodName, String methodDesc) { 74 | Method method; 75 | String fullMethodName = ReflectUtils.getMethodDesc(methodName, methodDesc); 76 | method = methodMap.get(fullMethodName); 77 | if (method == null && StringUtils.isBlank(methodDesc)) { 78 | method = methodMap.get(methodName); 79 | if (method == null) { 80 | method = methodMap.get(methodName.substring(0, 1).toLowerCase() + methodName.substring(1)); 81 | } 82 | } 83 | 84 | return method; 85 | } 86 | 87 | private void initMethodMap(Class clz) { 88 | Method[] methods = clz.getMethods(); 89 | 90 | List dupList = new ArrayList<>(); 91 | for (Method method : methods) { 92 | String methodDesc = ReflectUtils.getMethodDesc(method); 93 | methodMap.put(methodDesc, method); 94 | if (methodMap.get(method.getName()) == null) { 95 | methodMap.put(method.getName(), method); 96 | } else { 97 | dupList.add(method.getName()); 98 | } 99 | } 100 | if (!dupList.isEmpty()) { 101 | for (String removedName : dupList) { 102 | methodMap.remove(removedName); 103 | } 104 | } 105 | } 106 | 107 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/rpc/AbstractReferer.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.rpc; 2 | 3 | import org.hongxi.jaws.common.util.JawsFrameworkUtils; 4 | import org.hongxi.jaws.exception.JawsFrameworkException; 5 | 6 | import java.util.concurrent.atomic.AtomicInteger; 7 | 8 | /** 9 | * Created by shenhongxi on 2021/4/21. 10 | */ 11 | public abstract class AbstractReferer extends AbstractNode implements Referer { 12 | 13 | protected Class clz; 14 | protected AtomicInteger activeRefererCount = new AtomicInteger(0); 15 | protected URL serviceUrl; 16 | 17 | public AbstractReferer(Class clz, URL url) { 18 | super(url); 19 | this.clz = clz; 20 | this.serviceUrl = url; 21 | } 22 | 23 | public AbstractReferer(Class clz, URL url, URL serviceUrl) { 24 | super(url); 25 | this.clz = clz; 26 | this.serviceUrl = serviceUrl; 27 | } 28 | 29 | @Override 30 | public Class getInterface() { 31 | return clz; 32 | } 33 | 34 | @Override 35 | public Response call(Request request) { 36 | if (!isAvailable()) { 37 | throw new JawsFrameworkException(this.getClass().getSimpleName() + " call Error: node is not available, url=" + url.getUri() 38 | + " " + JawsFrameworkUtils.toString(request)); 39 | } 40 | 41 | incrActiveCount(request); 42 | Response response = null; 43 | try { 44 | response = doCall(request); 45 | 46 | return response; 47 | } finally { 48 | decrActiveCount(request, response); 49 | } 50 | } 51 | 52 | @Override 53 | public int activeRefererCount() { 54 | return activeRefererCount.get(); 55 | } 56 | 57 | protected void incrActiveCount(Request request) { 58 | activeRefererCount.incrementAndGet(); 59 | } 60 | 61 | protected void decrActiveCount(Request request, Response response) { 62 | activeRefererCount.decrementAndGet(); 63 | } 64 | 65 | protected abstract Response doCall(Request request); 66 | 67 | @Override 68 | public String desc() { 69 | return "[" + this.getClass().getSimpleName() + "] url=" + url; 70 | } 71 | 72 | @Override 73 | public URL getServiceUrl() { 74 | return serviceUrl; 75 | } 76 | 77 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/rpc/Callbackable.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.rpc; 2 | 3 | import java.util.concurrent.Executor; 4 | 5 | /** 6 | * Created by shenhongxi on 2020/8/22. 7 | */ 8 | public interface Callbackable { 9 | 10 | void addFinishCallback(Runnable runnable, Executor executor); 11 | 12 | void onFinish(); 13 | } 14 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/rpc/Caller.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.rpc; 2 | 3 | /** 4 | * Created by shenhongxi on 2021/3/6. 5 | */ 6 | public interface Caller extends Node { 7 | 8 | Class getInterface(); 9 | 10 | Response call(Request request); 11 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/rpc/DefaultRequest.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.rpc; 2 | 3 | import java.io.Serializable; 4 | import java.util.Collections; 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | /** 9 | * Created by shenhongxi on 2020/7/28. 10 | */ 11 | public class DefaultRequest implements Request, Serializable { 12 | private static final long serialVersionUID = -6525078483477733530L; 13 | 14 | private String interfaceName; 15 | private String methodName; 16 | private String parametersDesc; 17 | private Object[] arguments; 18 | private Map attachments; 19 | private int retries = 0; 20 | private long requestId; 21 | private int serializationNumber = 0;// default serialization is hession2 22 | 23 | @Override 24 | public String getInterfaceName() { 25 | return interfaceName; 26 | } 27 | 28 | public void setInterfaceName(String interfaceName) { 29 | this.interfaceName = interfaceName; 30 | } 31 | 32 | @Override 33 | public String getMethodName() { 34 | return methodName; 35 | } 36 | 37 | public void setMethodName(String methodName) { 38 | this.methodName = methodName; 39 | } 40 | 41 | @Override 42 | public String getParametersDesc() { 43 | return parametersDesc; 44 | } 45 | 46 | public void setParametersDesc(String parametersDesc) { 47 | this.parametersDesc = parametersDesc; 48 | } 49 | 50 | @Override 51 | public Object[] getArguments() { 52 | return arguments; 53 | } 54 | 55 | public void setArguments(Object[] arguments) { 56 | this.arguments = arguments; 57 | } 58 | 59 | @Override 60 | public Map getAttachments() { 61 | return attachments != null ? attachments : Collections.emptyMap(); 62 | } 63 | 64 | public void setAttachments(Map attachments) { 65 | this.attachments = attachments; 66 | } 67 | 68 | @Override 69 | public void setAttachment(String key, String value) { 70 | if (this.attachments == null) { 71 | this.attachments = new HashMap<>(); 72 | } 73 | this.attachments.put(key, value); 74 | } 75 | 76 | @Override 77 | public long getRequestId() { 78 | return requestId; 79 | } 80 | 81 | public void setRequestId(long requestId) { 82 | this.requestId = requestId; 83 | } 84 | 85 | @Override 86 | public int getRetries() { 87 | return retries; 88 | } 89 | 90 | @Override 91 | public void setRetries(int retries) { 92 | this.retries = retries; 93 | } 94 | 95 | @Override 96 | public void setSerializationNumber(int number) { 97 | this.serializationNumber = number; 98 | } 99 | 100 | @Override 101 | public int getSerializationNumber() { 102 | return serializationNumber; 103 | } 104 | 105 | @Override 106 | public String toString() { 107 | return interfaceName + "." + methodName + "(" + parametersDesc + ") requestId=" + requestId; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/rpc/Exporter.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.rpc; 2 | 3 | /** 4 | * Created by shenhongxi on 2021/3/6. 5 | */ 6 | public interface Exporter extends Node { 7 | 8 | Provider getProvider(); 9 | 10 | void unexport(); 11 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/rpc/Future.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.rpc; 2 | 3 | /** 4 | * Created by shenhongxi on 2020/7/30. 5 | */ 6 | public interface Future { 7 | 8 | /** 9 | * cancel the task 10 | * 11 | * @return 12 | */ 13 | boolean cancel(); 14 | 15 | /** 16 | * task cancelled 17 | * 18 | * @return 19 | */ 20 | boolean isCancelled(); 21 | 22 | /** 23 | * task is complete : normal or exception 24 | * 25 | * @return 26 | */ 27 | boolean isDone(); 28 | 29 | /** 30 | * isDone() & normal 31 | * 32 | * @return 33 | */ 34 | boolean isSuccess(); 35 | 36 | /** 37 | * if task is success, return the result. 38 | * 39 | * @throws Exception when timeout, cancel, onFailure 40 | * @return 41 | */ 42 | Object getValue(); 43 | 44 | /** 45 | * if task is done or cancel, return the exception 46 | * 47 | * @return 48 | */ 49 | Exception getException(); 50 | 51 | /** 52 | * add future listener , when task is success,failure, timeout, cancel, it will be called 53 | * 54 | * @param listener 55 | */ 56 | void addListener(FutureListener listener); 57 | } 58 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/rpc/FutureListener.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.rpc; 2 | 3 | /** 4 | * 用于监听Future的success和fail事件 5 | * 6 | * Created by shenhongxi on 2020/7/30. 7 | */ 8 | public interface FutureListener { 9 | 10 | /** 11 | *
12 |      * 		建议做一些比较简单的低功耗的操作
13 |      *
14 |      * 		注意一些反模式:
15 |      *
16 |      * 		1) 死循环:
17 |      * 			operationComplete(Future future) {
18 |      * 					......
19 |      * 				future.addListener(this);  // 类似于这种操作,后果你懂的
20 |      * 					......
21 |      * 			}
22 |      *
23 |      * 		2)耗资源操作或者慢操作:
24 |      * 			operationComplete(Future future) {
25 |      * 					......
26 |      * 				Thread.sleep(500);
27 |      * 					......
28 |      * 			}
29 |      *
30 |      * 
31 | * 32 | * @param future 33 | * @throws Exception 34 | */ 35 | void operationComplete(Future future) throws Exception; 36 | } 37 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/rpc/Node.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.rpc; 2 | 3 | /** 4 | * Created by shenhongxi on 2021/3/6. 5 | */ 6 | public interface Node { 7 | 8 | void init(); 9 | 10 | void destroy(); 11 | 12 | boolean isAvailable(); 13 | 14 | String desc(); 15 | 16 | URL getUrl(); 17 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/rpc/Protocol.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.rpc; 2 | 3 | import org.hongxi.jaws.common.extension.Scope; 4 | import org.hongxi.jaws.common.extension.Spi; 5 | 6 | /** 7 | * protocol 8 | * 9 | *
10 |  * 只负责点到点的通讯
11 |  * 
12 | * 13 | * Created by shenhongxi on 2021/3/6. 14 | */ 15 | @Spi(scope = Scope.SINGLETON) 16 | public interface Protocol { 17 | /** 18 | * 暴露服务 19 | * 20 | * @param 21 | * @param provider 22 | * @param url 23 | * @return 24 | */ 25 | Exporter export(Provider provider, URL url); 26 | 27 | /** 28 | * 引用服务 29 | * 30 | * @param 31 | * @param clz 32 | * @param url 33 | * @param serviceUrl 34 | * @return 35 | */ 36 | Referer refer(Class clz, URL url, URL serviceUrl); 37 | 38 | /** 39 | *
40 | 	 * 		1) exporter destroy
41 | 	 * 		2) referer destroy
42 | 	 * 
43 | * 44 | */ 45 | void destroy(); 46 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/rpc/Provider.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.rpc; 2 | 3 | import org.hongxi.jaws.common.extension.Scope; 4 | import org.hongxi.jaws.common.extension.Spi; 5 | 6 | import java.lang.reflect.Method; 7 | 8 | /** 9 | * Created by shenhongxi on 2021/3/6. 10 | */ 11 | @Spi(scope = Scope.PROTOTYPE) 12 | public interface Provider extends Caller { 13 | 14 | Class getInterface(); 15 | 16 | Method lookupMethod(String methodName, String methodDesc); 17 | 18 | T getImpl(); 19 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/rpc/Referer.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.rpc; 2 | 3 | import org.hongxi.jaws.common.extension.Scope; 4 | import org.hongxi.jaws.common.extension.Spi; 5 | 6 | /** 7 | * Created by shenhongxi on 2021/4/21. 8 | */ 9 | @Spi(scope = Scope.PROTOTYPE) 10 | public interface Referer extends Caller, Node { 11 | 12 | /** 13 | * 当前使用该referer的调用数 14 | * 15 | * @return 16 | */ 17 | int activeRefererCount(); 18 | 19 | /** 20 | * 获取referer的原始service url 21 | * 22 | * @return 23 | */ 24 | URL getServiceUrl(); 25 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/rpc/RefererSupports.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.rpc; 2 | 3 | import org.hongxi.jaws.closable.Closable; 4 | import org.hongxi.jaws.closable.ShutdownHook; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import java.util.List; 9 | import java.util.concurrent.Executors; 10 | import java.util.concurrent.ScheduledExecutorService; 11 | import java.util.concurrent.TimeUnit; 12 | 13 | /** 14 | * Created by shenhongxi on 2021/3/7. 15 | */ 16 | public class RefererSupports { 17 | 18 | private static final Logger log = LoggerFactory.getLogger(RefererSupports.class); 19 | 20 | private static ScheduledExecutorService scheduledExecutor = Executors.newScheduledThreadPool(10); 21 | 22 | // 正常情况下请求超过1s已经是能够忍耐的极限值了,delay 1s进行destroy 23 | private static final int DELAY_TIME = 1000; 24 | static{ 25 | ShutdownHook.registerShutdownHook(new Closable() { 26 | @Override 27 | public void close() { 28 | if(!scheduledExecutor.isShutdown()){ 29 | scheduledExecutor.shutdown(); 30 | } 31 | } 32 | }); 33 | } 34 | public static void delayDestroy(final List> referers) { 35 | if (referers == null || referers.isEmpty()) { 36 | return; 37 | } 38 | 39 | scheduledExecutor.schedule(new Runnable() { 40 | @Override 41 | public void run() { 42 | 43 | for (Referer referer : referers) { 44 | try { 45 | referer.destroy(); 46 | } catch (Exception e) { 47 | log.error("RefererSupports delayDestroy Error: url={}" + referer.getUrl().getUri(), e); 48 | } 49 | } 50 | } 51 | }, DELAY_TIME, TimeUnit.MILLISECONDS); 52 | 53 | log.info("RefererSupports delayDestroy Success: size={} service={} urls={}", referers.size(), referers.get(0).getUrl() 54 | .getIdentity(), getServerPorts(referers)); 55 | } 56 | 57 | private static String getServerPorts(List> referers) { 58 | if (referers == null || referers.isEmpty()) { 59 | return "[]"; 60 | } 61 | 62 | StringBuilder builder = new StringBuilder(); 63 | builder.append("["); 64 | for (Referer referer : referers) { 65 | builder.append(referer.getUrl().getServerPortStr()).append(","); 66 | } 67 | builder.setLength(builder.length() - 1); 68 | builder.append("]"); 69 | 70 | return builder.toString(); 71 | } 72 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/rpc/Request.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.rpc; 2 | 3 | import java.util.Map; 4 | 5 | /** 6 | * Created by shenhongxi on 2020/6/14. 7 | */ 8 | public interface Request { 9 | 10 | /** 11 | * service interface 12 | * 13 | * @return 14 | */ 15 | String getInterfaceName(); 16 | 17 | /** 18 | * service method name 19 | * 20 | * @return 21 | */ 22 | String getMethodName(); 23 | 24 | /** 25 | * service method param desc (sign) 26 | * 27 | * @return 28 | */ 29 | String getParametersDesc(); 30 | 31 | /** 32 | * service method param 33 | * 34 | * @return 35 | */ 36 | Object[] getArguments(); 37 | 38 | /** 39 | * get framework param 40 | * 41 | * @return 42 | */ 43 | Map getAttachments(); 44 | 45 | /** 46 | * set framework param 47 | * 48 | * @return 49 | */ 50 | void setAttachment(String name, String value); 51 | 52 | /** 53 | * request id 54 | * 55 | * @return 56 | */ 57 | long getRequestId(); 58 | 59 | /** 60 | * retries 61 | * 62 | * @return 63 | */ 64 | int getRetries(); 65 | 66 | /** 67 | * set retries 68 | */ 69 | void setRetries(int retries); 70 | 71 | /** 72 | * set the serialization number. 73 | * same to the protocol version, this value only used in server end for compatible. 74 | * 75 | * @param number 76 | */ 77 | void setSerializationNumber(int number); 78 | 79 | int getSerializationNumber(); 80 | } 81 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/rpc/Response.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.rpc; 2 | 3 | import java.util.Map; 4 | 5 | /** 6 | * Created by shenhongxi on 2020/6/14. 7 | */ 8 | public interface Response { 9 | 10 | /** 11 | *
12 |      * 		如果 request 正常处理,那么会返回 Object value,而如果 request 处理有异常,那么 getValue 会抛出异常
13 |      * 
14 | * 15 | * @return 16 | * @throws RuntimeException 17 | */ 18 | Object getValue(); 19 | 20 | /** 21 | * 如果request处理有异常,那么调用该方法return exception 如果request还没处理完或者request处理正常,那么return null 22 | *

23 | *

24 |      * 		该方法不会阻塞,无论该request是处理中还是处理完成
25 |      * 
26 | * 27 | * @return 28 | */ 29 | Exception getException(); 30 | 31 | /** 32 | * 与 Request 的 requestId 相对应 33 | * 34 | * @return 35 | */ 36 | long getRequestId(); 37 | 38 | /** 39 | * 业务处理时间 40 | * 41 | * @return 42 | */ 43 | long getProcessTime(); 44 | 45 | /** 46 | * 业务处理时间 47 | * 48 | * @param time 49 | */ 50 | void setProcessTime(long time); 51 | 52 | int getTimeout(); 53 | 54 | Map getAttachments(); 55 | 56 | void setAttachment(String key, String value); 57 | 58 | /** 59 | * set the serialization number. 60 | * same to the protocol version, this value only used in server end for compatible. 61 | * 62 | * @param number 63 | */ 64 | void setSerializationNumber(int number); 65 | 66 | int getSerializationNumber(); 67 | } 68 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/rpc/ResponseFuture.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.rpc; 2 | 3 | /** 4 | * Created by shenhongxi on 2020/7/30. 5 | */ 6 | public interface ResponseFuture extends Future, Response { 7 | 8 | void onSuccess(Response response); 9 | 10 | void onFailure(Response response); 11 | 12 | long getCreateTime(); 13 | 14 | void setReturnType(Class clazz); 15 | } 16 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/rpc/RpcContext.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.rpc; 2 | 3 | import org.hongxi.jaws.common.URLParamType; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | /** 9 | * Created by shenhongxi on 2020/6/26. 10 | */ 11 | public class RpcContext { 12 | private static final ThreadLocal LOCAL_CONTEXT = ThreadLocal.withInitial(() -> new RpcContext()); 13 | private Map attributes = new HashMap<>(); 14 | private Map attachments = new HashMap<>(); 15 | private Request request; 16 | private Response response; 17 | private String clientRequestId; 18 | 19 | public static RpcContext getContext() { 20 | return LOCAL_CONTEXT.get(); 21 | } 22 | 23 | public static void destroy() { 24 | LOCAL_CONTEXT.remove(); 25 | } 26 | 27 | /** 28 | * init new rpcContext with request 29 | * 30 | * @param request 31 | * @return 32 | */ 33 | public static RpcContext init(Request request) { 34 | RpcContext context = new RpcContext(); 35 | if (request != null) { 36 | context.setRequest(request); 37 | context.setClientRequestId( 38 | request.getAttachments().get(URLParamType.requestIdFromClient.getName())); 39 | } 40 | LOCAL_CONTEXT.set(context); 41 | return context; 42 | } 43 | 44 | public String getRequestId() { 45 | if (clientRequestId != null) return clientRequestId; 46 | if (request != null) return String.valueOf(request.getRequestId()); 47 | return null; 48 | } 49 | 50 | public void putAttribute(Object key, Object value) { 51 | attributes.put(key, value); 52 | } 53 | 54 | public Object getAttribute(Object key) { 55 | return attributes.get(key); 56 | } 57 | 58 | public void removeAttribute(Object key) { 59 | attributes.remove(key); 60 | } 61 | 62 | public Map getAttributes() { 63 | return attributes; 64 | } 65 | 66 | public void setRpcAttachment(String key, String value) { 67 | attachments.put(key, value); 68 | } 69 | 70 | /** 71 | * get attachments from rpccontext only. not from request or response 72 | * 73 | * @param key 74 | * @return 75 | */ 76 | public String getRpcAttachment(String key) { 77 | return attachments.get(key); 78 | } 79 | 80 | public void removeRpcAttachment(String key) { 81 | attachments.remove(key); 82 | } 83 | 84 | public Map getRpcAttachments() { 85 | return attachments; 86 | } 87 | 88 | public Request getRequest() { 89 | return request; 90 | } 91 | 92 | public void setRequest(Request request) { 93 | this.request = request; 94 | } 95 | 96 | public Response getResponse() { 97 | return response; 98 | } 99 | 100 | public void setResponse(Response response) { 101 | this.response = response; 102 | } 103 | 104 | public String getClientRequestId() { 105 | return clientRequestId; 106 | } 107 | 108 | public void setClientRequestId(String clientRequestId) { 109 | this.clientRequestId = clientRequestId; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/serialize/DeserializableObject.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.serialize; 2 | 3 | import org.hongxi.jaws.codec.Serialization; 4 | 5 | import java.io.IOException; 6 | 7 | /** 8 | * Created by shenhongxi on 2020/7/28. 9 | */ 10 | public class DeserializableObject { 11 | private Serialization serialization; 12 | private byte[] objBytes; 13 | 14 | public DeserializableObject(Serialization serialization, byte[] objBytes) { 15 | this.serialization = serialization; 16 | this.objBytes = objBytes; 17 | } 18 | 19 | public T deserialize(Class clz) throws IOException { 20 | return serialization.deserialize(objBytes, clz); 21 | } 22 | 23 | public Object[] deserializeMulti(Class[] paramTypes) throws IOException { 24 | Object[] ret = null; 25 | if (paramTypes != null && paramTypes.length > 0) { 26 | ret = serialization.deserializeMulti(objBytes, paramTypes); 27 | } 28 | return ret; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/serialize/FastJsonSerialization.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.serialize; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.alibaba.fastjson.serializer.JSONSerializer; 5 | import com.alibaba.fastjson.serializer.SerializeWriter; 6 | import com.alibaba.fastjson.serializer.SerializerFeature; 7 | import org.hongxi.jaws.codec.Serialization; 8 | import org.hongxi.jaws.common.extension.SpiMeta; 9 | 10 | import java.io.IOException; 11 | import java.util.List; 12 | 13 | /** 14 | * fastjson 序列化 15 | * 16 | *
17 |  * 对于嵌套场景无法支持
18 |  * 
19 | * 20 | * Created by shenhongxi on 2020/7/28. 21 | * 22 | */ 23 | @SpiMeta(name = "fastjson") 24 | public class FastJsonSerialization implements Serialization { 25 | 26 | @Override 27 | public byte[] serialize(Object data) throws IOException { 28 | SerializeWriter out = new SerializeWriter(); 29 | JSONSerializer serializer = new JSONSerializer(out); 30 | serializer.config(SerializerFeature.WriteEnumUsingToString, true); 31 | serializer.config(SerializerFeature.WriteClassName, true); 32 | serializer.write(data); 33 | return out.toBytes("UTF-8"); 34 | } 35 | 36 | @Override 37 | public T deserialize(byte[] data, Class clz) throws IOException { 38 | return JSON.parseObject(new String(data), clz); 39 | } 40 | 41 | @Override 42 | public byte[] serializeMulti(Object[] data) throws IOException { 43 | return serialize(data); 44 | } 45 | 46 | @Override 47 | public Object[] deserializeMulti(byte[] data, Class[] classes) throws IOException { 48 | List list = JSON.parseArray(new String(data), classes); 49 | if (list != null) { 50 | return list.toArray(); 51 | } 52 | return null; 53 | } 54 | 55 | @Override 56 | public int getSerializationNumber() { 57 | return 2; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/serialize/Hessian2Serialization.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.serialize; 2 | 3 | import com.caucho.hessian.io.Hessian2Input; 4 | import com.caucho.hessian.io.Hessian2Output; 5 | import org.hongxi.jaws.codec.Serialization; 6 | import org.hongxi.jaws.common.extension.SpiMeta; 7 | 8 | import java.io.ByteArrayInputStream; 9 | import java.io.ByteArrayOutputStream; 10 | import java.io.IOException; 11 | 12 | /** 13 | * hession2 序列化,要求序列化的对象实现 java.io.Serializable 接口 14 | * 15 | * Created by shenhongxi on 2020/7/28. 16 | * 17 | */ 18 | @SpiMeta(name = "hessian2") 19 | public class Hessian2Serialization implements Serialization { 20 | 21 | @Override 22 | public byte[] serialize(Object data) throws IOException { 23 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 24 | Hessian2Output out = new Hessian2Output(bos); 25 | out.writeObject(data); 26 | out.flush(); 27 | return bos.toByteArray(); 28 | } 29 | 30 | @SuppressWarnings("unchecked") 31 | @Override 32 | public T deserialize(byte[] data, Class clz) throws IOException { 33 | Hessian2Input input = new Hessian2Input(new ByteArrayInputStream(data)); 34 | return (T) input.readObject(clz); 35 | } 36 | 37 | @Override 38 | public byte[] serializeMulti(Object[] data) throws IOException { 39 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 40 | Hessian2Output out = new Hessian2Output(bos); 41 | for(Object obj: data){ 42 | out.writeObject(obj); 43 | } 44 | out.flush(); 45 | return bos.toByteArray(); 46 | } 47 | 48 | @Override 49 | public Object[] deserializeMulti(byte[] data, Class[] classes) throws IOException { 50 | Hessian2Input input = new Hessian2Input(new ByteArrayInputStream(data)); 51 | Object[] objects = new Object[classes.length]; 52 | for (int i = 0; i < classes.length; i++) { 53 | objects[i] = input.readObject(classes[i]); 54 | } 55 | return objects; 56 | } 57 | 58 | @Override 59 | public int getSerializationNumber() { 60 | return 0; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/switcher/JawsSwitcherUtils.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.switcher; 2 | 3 | /** 4 | * 静态开关工具类。一般全局开关使用此类。 可以替换switcherService为不同实现 5 | * 6 | * Created by shenhongxi on 2021/4/25. 7 | */ 8 | public class JawsSwitcherUtils { 9 | private static SwitcherService switcherService = new LocalSwitcherService(); 10 | 11 | public static void initSwitcher(String switcherName, boolean initialValue) { 12 | switcherService.initSwitcher(switcherName, initialValue); 13 | } 14 | 15 | /** 16 | * 检查开关是否开启。 17 | * 18 | * @param switcherName 19 | * @return true :设置了开关,并且开关值为true false:未设置开关或开关为false 20 | */ 21 | public static boolean isOpen(String switcherName) { 22 | return switcherService.isOpen(switcherName); 23 | } 24 | 25 | /** 26 | * 检查开关是否开启,如果开关不存在则将开关置默认值,并返回。 27 | * 28 | * @param switcherName 29 | * @param defaultValue 30 | * @return 开关存在时返回开关值,开关不存在时设置开关为默认值,并返回默认值。 31 | */ 32 | public static boolean switcherIsOpenWithDefault(String switcherName, boolean defaultValue) { 33 | return switcherService.isOpen(switcherName, defaultValue); 34 | } 35 | 36 | /** 37 | * 设置开关状态。 38 | * 39 | * @param switcherName 40 | * @param value 41 | * @return 42 | */ 43 | public static void setSwitcherValue(String switcherName, boolean value) { 44 | switcherService.setValue(switcherName, value); 45 | } 46 | 47 | public static SwitcherService getSwitcherService() { 48 | return switcherService; 49 | } 50 | 51 | public static void setSwitcherService(SwitcherService switcherService) { 52 | JawsSwitcherUtils.switcherService = switcherService; 53 | } 54 | 55 | public static void registerSwitcherListener(String switcherName, SwitcherListener listener) { 56 | switcherService.registerListener(switcherName, listener); 57 | } 58 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/switcher/LocalSwitcherService.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.switcher; 2 | 3 | import org.hongxi.jaws.common.extension.SpiMeta; 4 | import org.hongxi.jaws.exception.JawsFrameworkException; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Collections; 8 | import java.util.List; 9 | import java.util.concurrent.ConcurrentHashMap; 10 | import java.util.concurrent.ConcurrentMap; 11 | 12 | @SpiMeta(name = "localSwitcherService") 13 | public class LocalSwitcherService implements SwitcherService { 14 | 15 | private static ConcurrentMap switchers = new ConcurrentHashMap<>(); 16 | 17 | private ConcurrentHashMap> listenerMap = new ConcurrentHashMap<>(); 18 | 19 | public static Switcher getSwitcherStatic(String name) { 20 | return switchers.get(name); 21 | } 22 | 23 | @Override 24 | public Switcher getSwitcher(String name) { 25 | return switchers.get(name); 26 | } 27 | 28 | @Override 29 | public List getAllSwitchers() { 30 | return new ArrayList<>(switchers.values()); 31 | } 32 | 33 | public static void putSwitcher(Switcher switcher) { 34 | if (switcher == null) { 35 | throw new JawsFrameworkException("LocalSwitcherService addSwitcher Error: switcher is null"); 36 | } 37 | 38 | switchers.put(switcher.getName(), switcher); 39 | } 40 | 41 | @Override 42 | public void initSwitcher(String switcherName, boolean initialValue) { 43 | setValue(switcherName, initialValue); 44 | } 45 | 46 | @Override 47 | public boolean isOpen(String switcherName) { 48 | Switcher switcher = switchers.get(switcherName); 49 | return switcher != null && switcher.isOn(); 50 | } 51 | 52 | @Override 53 | public boolean isOpen(String switcherName, boolean defaultValue) { 54 | Switcher switcher = switchers.get(switcherName); 55 | if (switcher == null) { 56 | switchers.putIfAbsent(switcherName, new Switcher(switcherName, defaultValue)); 57 | switcher = switchers.get(switcherName); 58 | } 59 | return switcher.isOn(); 60 | } 61 | 62 | @Override 63 | public void setValue(String switcherName, boolean value) { 64 | putSwitcher(new Switcher(switcherName, value)); 65 | 66 | List listeners = listenerMap.get(switcherName); 67 | if (listeners != null) { 68 | for (SwitcherListener listener : listeners) { 69 | listener.onValueChanged(switcherName, value); 70 | } 71 | } 72 | } 73 | 74 | @Override 75 | public void registerListener(String switcherName, SwitcherListener listener) { 76 | List listeners = Collections.synchronizedList(new ArrayList<>()); 77 | List preListeners= listenerMap.putIfAbsent(switcherName, listeners); 78 | if (preListeners == null) { 79 | listeners.add(listener); 80 | } else { 81 | preListeners.add(listener); 82 | } 83 | } 84 | 85 | @Override 86 | public void unRegisterListener(String switcherName, SwitcherListener listener) { 87 | List listeners = listenerMap.get(switcherName); 88 | if (listener == null) { 89 | // keep empty listeners 90 | listeners.clear(); 91 | } else { 92 | listeners.remove(listener); 93 | } 94 | } 95 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/switcher/Switcher.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.switcher; 2 | 3 | /** 4 | * Created by shenhongxi on 2021/4/25. 5 | */ 6 | public class Switcher { 7 | private boolean on = true; 8 | private String name; // 开关名 9 | 10 | public Switcher(String name, boolean on) { 11 | this.name = name; 12 | this.on = on; 13 | } 14 | 15 | public String getName() { 16 | return name; 17 | } 18 | 19 | /** 20 | * isOn: true,服务可用; isOn: false, 服务不可用 21 | * 22 | * @return 23 | */ 24 | public boolean isOn() { 25 | return on; 26 | } 27 | 28 | /** 29 | * turn on switcher 30 | */ 31 | public void onSwitcher() { 32 | this.on = true; 33 | } 34 | 35 | /** 36 | * turn off switcher 37 | */ 38 | public void offSwitcher() { 39 | this.on = false; 40 | } 41 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/switcher/SwitcherListener.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.switcher; 2 | 3 | /** 4 | * Created by shenhongxi on 2021/4/25. 5 | */ 6 | public interface SwitcherListener { 7 | 8 | void onValueChanged(String key,Boolean value); 9 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/switcher/SwitcherService.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.switcher; 2 | 3 | import org.hongxi.jaws.common.extension.Scope; 4 | import org.hongxi.jaws.common.extension.Spi; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * Created by shenhongxi on 2021/4/25. 10 | */ 11 | @Spi(scope = Scope.SINGLETON) 12 | public interface SwitcherService { 13 | /** 14 | * 获取接口降级开关 15 | * 16 | * @param name 17 | * @return 18 | */ 19 | Switcher getSwitcher(String name); 20 | 21 | /** 22 | * 获取所有接口降级开关 23 | * 24 | * @return 25 | */ 26 | List getAllSwitchers(); 27 | 28 | /** 29 | * 初始化开关。 30 | * 31 | * @param switcherName 32 | * @param initialValue 33 | */ 34 | void initSwitcher(String switcherName, boolean initialValue); 35 | 36 | /** 37 | * 检查开关是否开启。 38 | * 39 | * @param switcherName 40 | * @return true :设置来开关,并且开关值为true false:未设置开关或开关为false 41 | */ 42 | boolean isOpen(String switcherName); 43 | 44 | /** 45 | * 检查开关是否开启,如果开关不存在则将开关置默认值,并返回。 46 | * 47 | * @param switcherName 48 | * @param defaultValue 49 | * @return 开关存在时返回开关值,开关不存在时设置开关为默认值,并返回默认值。 50 | */ 51 | boolean isOpen(String switcherName, boolean defaultValue); 52 | 53 | /** 54 | * 设置开关状态。 55 | * 56 | * @param switcherName 57 | * @param value 58 | */ 59 | void setValue(String switcherName, boolean value); 60 | 61 | /** 62 | * register a listener for switcher value change, register a listener twice will only fire once 63 | * 64 | * @param switcherName 65 | * @param listener 66 | */ 67 | void registerListener(String switcherName, SwitcherListener listener); 68 | 69 | /** 70 | * unregister a listener 71 | * 72 | * @param switcherName 73 | * @param listener the listener to be unregistered, null for all listeners for this switcherName 74 | */ 75 | void unRegisterListener(String switcherName, SwitcherListener listener); 76 | 77 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/transport/AbstractClient.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.transport; 2 | 3 | import org.hongxi.jaws.codec.Codec; 4 | import org.hongxi.jaws.common.ChannelState; 5 | import org.hongxi.jaws.common.URLParamType; 6 | import org.hongxi.jaws.common.extension.ExtensionLoader; 7 | import org.hongxi.jaws.exception.JawsFrameworkException; 8 | import org.hongxi.jaws.rpc.Request; 9 | import org.hongxi.jaws.rpc.URL; 10 | import org.hongxi.jaws.common.util.JawsFrameworkUtils; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | 14 | import java.net.InetSocketAddress; 15 | 16 | /** 17 | * Created by shenhongxi on 2020/7/28. 18 | */ 19 | public abstract class AbstractClient implements Client { 20 | private static final Logger logger = LoggerFactory.getLogger(AbstractClient.class); 21 | 22 | protected InetSocketAddress localAddress; 23 | protected InetSocketAddress remoteAddress; 24 | 25 | protected URL url; 26 | protected Codec codec; 27 | 28 | protected volatile ChannelState state = ChannelState.UNINIT; 29 | 30 | public AbstractClient(URL url) { 31 | this.url = url; 32 | this.codec = 33 | ExtensionLoader.getExtensionLoader(Codec.class).getExtension( 34 | url.getParameter(URLParamType.codec.getName(), URLParamType.codec.value())); 35 | logger.info("init netty client. url: " + url.getHost() + "-" + url.getPath() + ", use codec: " + codec.getClass().getSimpleName()); 36 | } 37 | 38 | @Override 39 | public InetSocketAddress getLocalAddress() { 40 | return localAddress; 41 | } 42 | 43 | @Override 44 | public InetSocketAddress getRemoteAddress() { 45 | return remoteAddress; 46 | } 47 | 48 | @Override 49 | public void heartbeat(Request request) { 50 | throw new JawsFrameworkException("heartbeat not support: " + JawsFrameworkUtils.toString(request)); 51 | } 52 | 53 | public void setLocalAddress(InetSocketAddress localAddress) { 54 | this.localAddress = localAddress; 55 | } 56 | 57 | public void setRemoteAddress(InetSocketAddress remoteAddress) { 58 | this.remoteAddress = remoteAddress; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/transport/AbstractServer.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.transport; 2 | 3 | import org.hongxi.jaws.codec.Codec; 4 | import org.hongxi.jaws.common.ChannelState; 5 | import org.hongxi.jaws.common.URLParamType; 6 | import org.hongxi.jaws.common.extension.ExtensionLoader; 7 | import org.hongxi.jaws.exception.JawsFrameworkException; 8 | import org.hongxi.jaws.rpc.URL; 9 | 10 | import java.net.InetSocketAddress; 11 | import java.util.Collection; 12 | 13 | /** 14 | * Created by shenhongxi on 2020/6/25. 15 | */ 16 | public abstract class AbstractServer implements Server { 17 | protected InetSocketAddress localAddress; 18 | protected InetSocketAddress remoteAddress; 19 | 20 | protected URL url; 21 | protected Codec codec; 22 | 23 | protected volatile ChannelState state = ChannelState.UNINIT; 24 | 25 | public AbstractServer() {} 26 | 27 | public AbstractServer(URL url) { 28 | this.url = url; 29 | this.codec = ExtensionLoader.getExtensionLoader(Codec.class).getExtension( 30 | url.getParameter(URLParamType.codec.getName(), URLParamType.codec.value())); 31 | } 32 | 33 | @Override 34 | public Collection getChannels() { 35 | throw new JawsFrameworkException(this.getClass().getName() + " getChannels() method not support " + url); 36 | } 37 | 38 | @Override 39 | public Channel getChannel(InetSocketAddress remoteAddress) { 40 | throw new JawsFrameworkException(this.getClass().getName() + " getChannels(InetSocketAddress) method not support " + url); 41 | } 42 | 43 | @Override 44 | public InetSocketAddress getLocalAddress() { 45 | return localAddress; 46 | } 47 | 48 | @Override 49 | public InetSocketAddress getRemoteAddress() { 50 | return remoteAddress; 51 | } 52 | 53 | public void setLocalAddress(InetSocketAddress localAddress) { 54 | this.localAddress = localAddress; 55 | } 56 | 57 | public void setRemoteAddress(InetSocketAddress remoteAddress) { 58 | this.remoteAddress = remoteAddress; 59 | } 60 | 61 | public void setUrl(URL url) { 62 | this.url = url; 63 | } 64 | 65 | public void setCodec(Codec codec) { 66 | this.codec = codec; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/transport/Channel.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.transport; 2 | 3 | import org.hongxi.jaws.rpc.Request; 4 | import org.hongxi.jaws.rpc.Response; 5 | import org.hongxi.jaws.rpc.URL; 6 | 7 | import java.net.InetSocketAddress; 8 | 9 | /** 10 | * Created by shenhongxi on 2020/6/14. 11 | */ 12 | public interface Channel { 13 | 14 | InetSocketAddress getLocalAddress(); 15 | 16 | InetSocketAddress getRemoteAddress(); 17 | 18 | Response request(Request request) throws TransportException; 19 | 20 | boolean open(); 21 | 22 | void close(); 23 | 24 | void close(int timeout); 25 | 26 | boolean isClosed(); 27 | 28 | boolean isAvailable(); 29 | 30 | URL getUrl(); 31 | } 32 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/transport/Client.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.transport; 2 | 3 | import org.hongxi.jaws.rpc.Request; 4 | 5 | /** 6 | * Created by shenhongxi on 2020/7/28. 7 | */ 8 | public interface Client extends Endpoint { 9 | 10 | void heartbeat(Request request); 11 | } 12 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/transport/Endpoint.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.transport; 2 | 3 | /** 4 | * Created by shenhongxi on 2020/6/14. 5 | */ 6 | public interface Endpoint extends Channel { 7 | } 8 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/transport/EndpointFactory.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.transport; 2 | 3 | import org.hongxi.jaws.common.extension.Scope; 4 | import org.hongxi.jaws.common.extension.Spi; 5 | import org.hongxi.jaws.rpc.URL; 6 | 7 | /** 8 | * Created by shenhongxi on 2020/7/31. 9 | */ 10 | @Spi(scope = Scope.SINGLETON) 11 | public interface EndpointFactory { 12 | 13 | /** 14 | * create remote server 15 | * 16 | * @param url 17 | * @param messageHandler 18 | * @return 19 | */ 20 | Server createServer(URL url, MessageHandler messageHandler); 21 | 22 | /** 23 | * create remote client 24 | * 25 | * @param url 26 | * @return 27 | */ 28 | Client createClient(URL url); 29 | 30 | /** 31 | * safe release server 32 | * 33 | * @param server 34 | * @param url 35 | */ 36 | void safeReleaseResource(Server server, URL url); 37 | 38 | /** 39 | * safe release client 40 | * 41 | * @param client 42 | * @param url 43 | */ 44 | void safeReleaseResource(Client client, URL url); 45 | } 46 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/transport/MessageHandler.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.transport; 2 | 3 | /** 4 | * Created by shenhongxi on 2020/6/27. 5 | */ 6 | public interface MessageHandler { 7 | 8 | Object handle(Channel channel, Object message); 9 | } 10 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/transport/ProviderProtectedStrategy.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.transport; 2 | 3 | import org.hongxi.jaws.common.extension.Scope; 4 | import org.hongxi.jaws.common.extension.Spi; 5 | import org.hongxi.jaws.rpc.Provider; 6 | import org.hongxi.jaws.rpc.Request; 7 | import org.hongxi.jaws.rpc.Response; 8 | 9 | import java.util.concurrent.atomic.AtomicInteger; 10 | 11 | /** 12 | * Created by shenhongxi on 2021/4/21. 13 | */ 14 | @Spi(scope = Scope.PROTOTYPE) 15 | public interface ProviderProtectedStrategy { 16 | 17 | Response call(Request request, Provider provider); 18 | 19 | void setMethodCounter(AtomicInteger methodCounter); 20 | 21 | } -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/transport/Server.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.transport; 2 | 3 | import java.net.InetSocketAddress; 4 | import java.util.Collection; 5 | 6 | /** 7 | * Created by shenhongxi on 2020/6/25. 8 | */ 9 | public interface Server extends Endpoint { 10 | 11 | boolean isBound(); 12 | 13 | Collection getChannels(); 14 | 15 | Channel getChannel(InetSocketAddress remoteAddress); 16 | } 17 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/transport/SharedObjectFactory.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.transport; 2 | 3 | /** 4 | * Created by shenhongxi on 2020/7/28. 5 | */ 6 | public interface SharedObjectFactory { 7 | 8 | /** 9 | * 创建对象 10 | * 11 | * @return 12 | */ 13 | T makeObject(); 14 | 15 | /** 16 | * 重建对象 17 | * 18 | * @param obj 19 | * @param async 20 | * @return 21 | */ 22 | boolean rebuildObject(T obj, boolean async); 23 | } 24 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/transport/TransportException.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.transport; 2 | 3 | import java.io.IOException; 4 | import java.net.InetSocketAddress; 5 | 6 | /** 7 | * Created by shenhongxi on 2020/6/14. 8 | */ 9 | public class TransportException extends IOException { 10 | private static final long serialVersionUID = -6184671228777275302L; 11 | 12 | private InetSocketAddress localAddress; 13 | private InetSocketAddress remoteAddress; 14 | 15 | public TransportException(String message, InetSocketAddress localAddress, InetSocketAddress remoteAddress) { 16 | super(message); 17 | this.localAddress = localAddress; 18 | this.remoteAddress = remoteAddress; 19 | } 20 | 21 | public TransportException(String message, Throwable cause, InetSocketAddress localAddress, InetSocketAddress remoteAddress) { 22 | super(message, cause); 23 | this.localAddress = localAddress; 24 | this.remoteAddress = remoteAddress; 25 | } 26 | 27 | public InetSocketAddress getLocalAddress() { 28 | return localAddress; 29 | } 30 | 31 | public InetSocketAddress getRemoteAddress() { 32 | return remoteAddress; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /jaws-core/src/main/java/org/hongxi/jaws/transport/UnprotectedStrategy.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.transport; 2 | 3 | import org.hongxi.jaws.common.extension.SpiMeta; 4 | import org.hongxi.jaws.rpc.Provider; 5 | import org.hongxi.jaws.rpc.Request; 6 | import org.hongxi.jaws.rpc.Response; 7 | 8 | import java.util.concurrent.atomic.AtomicInteger; 9 | 10 | /** 11 | * Created by shenhongxi on 2021/4/22. 12 | */ 13 | @SpiMeta(name = "none") 14 | public class UnprotectedStrategy implements ProviderProtectedStrategy { 15 | 16 | public UnprotectedStrategy() { 17 | } 18 | 19 | @Override 20 | public Response call(Request request, Provider provider) { 21 | return provider.call(request); 22 | } 23 | 24 | @Override 25 | public void setMethodCounter(AtomicInteger methodCounter) { 26 | } 27 | } -------------------------------------------------------------------------------- /jaws-core/src/main/resources/META-INF/services/org.hongxi.jaws.cluster.Cluster: -------------------------------------------------------------------------------- 1 | org.hongxi.jaws.cluster.support.ClusterSpi -------------------------------------------------------------------------------- /jaws-core/src/main/resources/META-INF/services/org.hongxi.jaws.cluster.HaStrategy: -------------------------------------------------------------------------------- 1 | org.hongxi.jaws.cluster.ha.FailoverHaStrategy 2 | org.hongxi.jaws.cluster.ha.FailfastHaStrategy -------------------------------------------------------------------------------- /jaws-core/src/main/resources/META-INF/services/org.hongxi.jaws.cluster.LoadBalance: -------------------------------------------------------------------------------- 1 | org.hongxi.jaws.cluster.loadbalance.LocalFirstLoadBalance 2 | org.hongxi.jaws.cluster.loadbalance.ConfigurableWeightLoadBalance 3 | org.hongxi.jaws.cluster.loadbalance.ActiveWeightLoadBalance 4 | org.hongxi.jaws.cluster.loadbalance.ConsistentHashLoadBalance 5 | org.hongxi.jaws.cluster.loadbalance.RandomLoadBalance 6 | org.hongxi.jaws.cluster.loadbalance.RoundRobinLoadBalance -------------------------------------------------------------------------------- /jaws-core/src/main/resources/META-INF/services/org.hongxi.jaws.codec.Codec: -------------------------------------------------------------------------------- 1 | org.hongxi.jaws.protocol.jaws.JawsCodec -------------------------------------------------------------------------------- /jaws-core/src/main/resources/META-INF/services/org.hongxi.jaws.codec.Serialization: -------------------------------------------------------------------------------- 1 | org.hongxi.jaws.serialize.Hessian2Serialization 2 | org.hongxi.jaws.serialize.FastJsonSerialization -------------------------------------------------------------------------------- /jaws-core/src/main/resources/META-INF/services/org.hongxi.jaws.config.handler.ConfigHandler: -------------------------------------------------------------------------------- 1 | org.hongxi.jaws.config.handler.SimpleConfigHandler -------------------------------------------------------------------------------- /jaws-core/src/main/resources/META-INF/services/org.hongxi.jaws.filter.Filter: -------------------------------------------------------------------------------- 1 | org.hongxi.jaws.filter.AccessLogFilter -------------------------------------------------------------------------------- /jaws-core/src/main/resources/META-INF/services/org.hongxi.jaws.proxy.ProxyFactory: -------------------------------------------------------------------------------- 1 | org.hongxi.jaws.proxy.support.CommonProxyFactory 2 | org.hongxi.jaws.proxy.support.JdkProxyFactory -------------------------------------------------------------------------------- /jaws-core/src/main/resources/META-INF/services/org.hongxi.jaws.registry.Registry: -------------------------------------------------------------------------------- 1 | org.hongxi.jaws.registry.support.LocalRegistry -------------------------------------------------------------------------------- /jaws-core/src/main/resources/META-INF/services/org.hongxi.jaws.registry.RegistryFactory: -------------------------------------------------------------------------------- 1 | org.hongxi.jaws.registry.support.LocalRegistryFactory 2 | org.hongxi.jaws.registry.support.DirectRegistryFactory -------------------------------------------------------------------------------- /jaws-core/src/main/resources/META-INF/services/org.hongxi.jaws.rpc.Protocol: -------------------------------------------------------------------------------- 1 | org.hongxi.jaws.protocol.injvm.InjvmProtocol 2 | org.hongxi.jaws.protocol.jaws.JawsProtocol -------------------------------------------------------------------------------- /jaws-core/src/main/resources/META-INF/services/org.hongxi.jaws.switcher.SwitcherService: -------------------------------------------------------------------------------- 1 | org.hongxi.jaws.switcher.LocalSwitcherService -------------------------------------------------------------------------------- /jaws-core/src/main/resources/META-INF/services/org.hongxi.jaws.transport.ProviderProtectedStrategy: -------------------------------------------------------------------------------- 1 | org.hongxi.jaws.transport.DefaultProtectedStrategy 2 | org.hongxi.jaws.transport.UnprotectedStrategy -------------------------------------------------------------------------------- /jaws-core/src/test/java/org/hongxi/jaws/MockServiceConfig.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws; 2 | 3 | import org.hongxi.jaws.config.ServiceConfig; 4 | import org.hongxi.jaws.rpc.URL; 5 | 6 | /** 7 | * Created by shenhongxi on 2021/4/21. 8 | */ 9 | public class MockServiceConfig extends ServiceConfig { 10 | private static final long serialVersionUID = 7965700855475224943L; 11 | 12 | protected boolean serviceExists(URL url) { 13 | return false; 14 | } 15 | } -------------------------------------------------------------------------------- /jaws-core/src/test/java/org/hongxi/jaws/ThreadPoolTest.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws; 2 | 3 | import org.hongxi.jaws.common.threadpool.DefaultThreadFactory; 4 | import org.hongxi.jaws.common.threadpool.StandardThreadPoolExecutor; 5 | import org.junit.After; 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | 9 | import java.util.concurrent.ThreadPoolExecutor; 10 | 11 | /** 12 | * Created by shenhongxi on 2020/8/23. 13 | */ 14 | public class ThreadPoolTest { 15 | 16 | private ThreadPoolExecutor threadPoolExecutor; 17 | 18 | @Before 19 | public void setUp() { 20 | threadPoolExecutor = new StandardThreadPoolExecutor(20, 200, 1000, 21 | new DefaultThreadFactory("NettyServer", true)); 22 | threadPoolExecutor.prestartAllCoreThreads(); 23 | } 24 | 25 | @After 26 | public void clear() { 27 | threadPoolExecutor.shutdown(); 28 | } 29 | 30 | @Test 31 | public void submit() { 32 | threadPoolExecutor.submit(() -> System.out.println(123)); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /jaws-core/src/test/java/org/hongxi/jaws/config/ServiceConfigTest.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.config; 2 | 3 | import org.hongxi.jaws.BaseTestCase; 4 | import org.hongxi.jaws.common.JawsConstants; 5 | import org.hongxi.jaws.protocol.example.IWorld; 6 | import org.junit.Test; 7 | 8 | import static org.junit.Assert.*; 9 | 10 | /** 11 | * Created by shenhongxi on 2021/4/21. 12 | */ 13 | public class ServiceConfigTest extends BaseTestCase { 14 | 15 | private ServiceConfig serviceConfig = null; 16 | 17 | @Override 18 | public void setUp() throws Exception { 19 | super.setUp(); 20 | serviceConfig = mockIWorldServiceConfig(); 21 | serviceConfig.setProtocol(mockProtocolConfig(JawsConstants.PROTOCOL_INJVM)); 22 | serviceConfig.setRegistry(mockLocalRegistryConfig()); 23 | serviceConfig.setExport(JawsConstants.PROTOCOL_INJVM + ":" + 0); 24 | } 25 | 26 | @Override 27 | public void tearDown() throws Exception { 28 | super.tearDown(); 29 | if (serviceConfig != null) { 30 | serviceConfig.unexport(); 31 | } 32 | } 33 | 34 | @Test 35 | public void testExport() { 36 | serviceConfig.export(); 37 | 38 | assertTrue(serviceConfig.getExported().get()); 39 | assertEquals(serviceConfig.getExporters().size(), 1); 40 | assertEquals(serviceConfig.getRegistryUrls().size(), 1); 41 | } 42 | 43 | @Test 44 | public void testUnexport() { 45 | testExport(); 46 | serviceConfig.unexport(); 47 | assertFalse(serviceConfig.getExported().get()); 48 | assertEquals(serviceConfig.getExporters().size(), 0); 49 | } 50 | } -------------------------------------------------------------------------------- /jaws-core/src/test/java/org/hongxi/jaws/mock/MockChannel.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.mock; 2 | 3 | import org.hongxi.jaws.rpc.Request; 4 | import org.hongxi.jaws.rpc.Response; 5 | import org.hongxi.jaws.rpc.URL; 6 | import org.hongxi.jaws.transport.Channel; 7 | import org.hongxi.jaws.transport.TransportException; 8 | 9 | import java.net.InetSocketAddress; 10 | 11 | /** 12 | * Created by shenhongxi on 2021/4/21. 13 | */ 14 | public class MockChannel implements Channel { 15 | private URL url; 16 | 17 | public MockChannel(URL url) { 18 | this.url = url; 19 | } 20 | 21 | @Override 22 | public InetSocketAddress getLocalAddress() { 23 | return null; 24 | } 25 | 26 | @Override 27 | public InetSocketAddress getRemoteAddress() { 28 | return null; 29 | } 30 | 31 | @Override 32 | public Response request(Request request) throws TransportException { 33 | return null; 34 | } 35 | 36 | @Override 37 | public boolean open() { 38 | return false; 39 | } 40 | 41 | @Override 42 | public void close() {} 43 | 44 | @Override 45 | public void close(int timeout) {} 46 | 47 | @Override 48 | public boolean isClosed() { 49 | return false; 50 | } 51 | 52 | @Override 53 | public boolean isAvailable() { 54 | return true; 55 | } 56 | 57 | @Override 58 | public URL getUrl() { 59 | return url; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /jaws-core/src/test/java/org/hongxi/jaws/mock/MockClient.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.mock; 2 | 3 | import org.hongxi.jaws.rpc.DefaultResponse; 4 | import org.hongxi.jaws.rpc.Request; 5 | import org.hongxi.jaws.rpc.Response; 6 | import org.hongxi.jaws.rpc.URL; 7 | import org.hongxi.jaws.transport.Client; 8 | import org.hongxi.jaws.transport.TransportException; 9 | 10 | import java.net.InetSocketAddress; 11 | import java.util.concurrent.ConcurrentHashMap; 12 | import java.util.concurrent.atomic.AtomicInteger; 13 | 14 | /** 15 | * Created by shenhongxi on 2021/4/21. 16 | */ 17 | public class MockClient implements Client { 18 | 19 | public static Response mockResponse; 20 | public static ConcurrentHashMap urlMap = new ConcurrentHashMap<>(); 21 | URL url; 22 | 23 | public MockClient(URL url) { 24 | this.url = url; 25 | urlMap.putIfAbsent(url, new AtomicInteger()); 26 | mockResponse = new DefaultResponse(); 27 | } 28 | 29 | @Override 30 | public InetSocketAddress getLocalAddress() { 31 | 32 | return null; 33 | } 34 | 35 | @Override 36 | public InetSocketAddress getRemoteAddress() { 37 | 38 | return null; 39 | } 40 | 41 | @Override 42 | public Response request(Request request) throws TransportException { 43 | urlMap.get(url).incrementAndGet(); 44 | // TODO 根据不同request 返回指定repsonse 45 | return mockResponse; 46 | } 47 | 48 | @Override 49 | public boolean open() { 50 | 51 | return true; 52 | } 53 | 54 | @Override 55 | public void close() { 56 | 57 | 58 | } 59 | 60 | @Override 61 | public void close(int timeout) { 62 | 63 | 64 | } 65 | 66 | @Override 67 | public boolean isClosed() { 68 | 69 | return false; 70 | } 71 | 72 | @Override 73 | public boolean isAvailable() { 74 | 75 | return true; 76 | } 77 | 78 | @Override 79 | public URL getUrl() { 80 | return url; 81 | } 82 | 83 | @Override 84 | public void heartbeat(Request request) {} 85 | 86 | 87 | } 88 | -------------------------------------------------------------------------------- /jaws-core/src/test/java/org/hongxi/jaws/mock/MockEndpointFactory.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.mock; 2 | 3 | import org.hongxi.jaws.common.extension.SpiMeta; 4 | import org.hongxi.jaws.rpc.URL; 5 | import org.hongxi.jaws.transport.Client; 6 | import org.hongxi.jaws.transport.MessageHandler; 7 | import org.hongxi.jaws.transport.Server; 8 | import org.hongxi.jaws.transport.support.AbstractEndpointFactory; 9 | 10 | /** 11 | * Created by shenhongxi on 2021/4/21. 12 | */ 13 | @SpiMeta(name = "mockEndpoint") 14 | public class MockEndpointFactory extends AbstractEndpointFactory { 15 | 16 | @Override 17 | protected Server innerCreateServer(URL url, MessageHandler messageHandler) { 18 | return new MockServer(url); 19 | } 20 | 21 | @Override 22 | protected Client innerCreateClient(URL url) { 23 | return new MockClient(url); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /jaws-core/src/test/java/org/hongxi/jaws/mock/MockReferer.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.mock; 2 | 3 | import org.hongxi.jaws.rpc.Referer; 4 | import org.hongxi.jaws.rpc.Request; 5 | import org.hongxi.jaws.rpc.Response; 6 | import org.hongxi.jaws.rpc.URL; 7 | 8 | /** 9 | * Created by shenhongxi on 2021/4/21. 10 | */ 11 | public class MockReferer implements Referer { 12 | public Class clz = null; 13 | public int active = 0; 14 | public boolean available = true; 15 | public String desc = this.getClass().getSimpleName(); 16 | public URL url = null; 17 | public URL serviceUrl = null; 18 | 19 | public MockReferer() { 20 | 21 | } 22 | 23 | public MockReferer(URL serviceUrl) { 24 | this.serviceUrl = serviceUrl; 25 | } 26 | 27 | @Override 28 | public Class getInterface() { 29 | return clz; 30 | } 31 | 32 | @Override 33 | public Response call(Request request) { 34 | return null; 35 | } 36 | 37 | @Override 38 | public void init() {} 39 | 40 | @Override 41 | public void destroy() {} 42 | 43 | @Override 44 | public boolean isAvailable() { 45 | return available; 46 | } 47 | 48 | @Override 49 | public String desc() { 50 | return desc; 51 | } 52 | 53 | @Override 54 | public URL getUrl() { 55 | return url; 56 | } 57 | 58 | @Override 59 | public int activeRefererCount() { 60 | return active; 61 | } 62 | 63 | @Override 64 | public URL getServiceUrl() { 65 | return serviceUrl; 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /jaws-core/src/test/java/org/hongxi/jaws/mock/MockServer.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.mock; 2 | 3 | import org.hongxi.jaws.rpc.Request; 4 | import org.hongxi.jaws.rpc.Response; 5 | import org.hongxi.jaws.rpc.URL; 6 | import org.hongxi.jaws.transport.Channel; 7 | import org.hongxi.jaws.transport.Server; 8 | import org.hongxi.jaws.transport.TransportException; 9 | 10 | import java.net.InetSocketAddress; 11 | import java.util.Collection; 12 | 13 | /** 14 | * Created by shenhongxi on 2021/4/21. 15 | */ 16 | public class MockServer implements Server { 17 | URL url; 18 | 19 | public MockServer(URL url) { 20 | this.url = url; 21 | } 22 | 23 | @Override 24 | public InetSocketAddress getLocalAddress() { 25 | 26 | return null; 27 | } 28 | 29 | @Override 30 | public InetSocketAddress getRemoteAddress() { 31 | 32 | return null; 33 | } 34 | 35 | @Override 36 | public Response request(Request request) throws TransportException { 37 | 38 | return null; 39 | } 40 | 41 | @Override 42 | public boolean open() { 43 | 44 | return true; 45 | } 46 | 47 | @Override 48 | public void close() { 49 | 50 | 51 | } 52 | 53 | @Override 54 | public void close(int timeout) { 55 | 56 | 57 | } 58 | 59 | @Override 60 | public boolean isClosed() { 61 | 62 | return false; 63 | } 64 | 65 | @Override 66 | public boolean isAvailable() { 67 | 68 | return false; 69 | } 70 | 71 | @Override 72 | public URL getUrl() { 73 | return url; 74 | } 75 | 76 | @Override 77 | public boolean isBound() { 78 | 79 | return false; 80 | } 81 | 82 | @Override 83 | public Collection getChannels() { 84 | 85 | return null; 86 | } 87 | 88 | @Override 89 | public Channel getChannel(InetSocketAddress remoteAddress) { 90 | 91 | return null; 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /jaws-core/src/test/java/org/hongxi/jaws/protocol/example/Hello.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.protocol.example; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * Created by shenhongxi on 2021/4/23. 7 | */ 8 | public class Hello implements IHello { 9 | private String protocol; 10 | 11 | public String hello() { 12 | return protocol + ": " + "void"; 13 | } 14 | 15 | public String hello(String name) { 16 | return protocol + ": " + name; 17 | } 18 | 19 | public String hello(Model model) { 20 | return protocol + ": " + model.toString(); 21 | } 22 | 23 | public String hello(int age) { 24 | return protocol + ": " + age; 25 | } 26 | 27 | public String hello(byte age) { 28 | return protocol + ": " + age; 29 | } 30 | 31 | public String hello(String name, int age, Model model) { 32 | return protocol + ": " + age + name + model.toString(); 33 | } 34 | 35 | public String hello(byte[] bs) { 36 | return protocol + ": " + Arrays.toString(bs); 37 | } 38 | 39 | public String hello(int[] bs) { 40 | return protocol + ": " + Arrays.toString(bs); 41 | } 42 | 43 | public String hello(String[] bs) { 44 | return protocol + ": " + Arrays.toString(bs); 45 | } 46 | 47 | public String hello(Model[] bs) { 48 | return protocol + ": " + Arrays.toString(bs); 49 | } 50 | 51 | public String hello(byte[][] bs) { 52 | return protocol + ": " + Arrays.toString(bs[0]); 53 | } 54 | 55 | public String hello(int[][] bs) { 56 | return protocol + ": " + Arrays.toString(bs[0]); 57 | } 58 | 59 | public String hello(String[][] bs) { 60 | return protocol + ": " + Arrays.toString(bs[0]); 61 | } 62 | 63 | public String hello(Model[][] bs) { 64 | return protocol + ": " + Arrays.toString(bs[0]); 65 | } 66 | 67 | public Model objResult(String name, int age) { 68 | Model mode = new Model(name, age, Model.class); 69 | 70 | return mode; 71 | } 72 | 73 | public Model[] objArrayResult(String name, int age) { 74 | Model mode = new Model(name, age, Model.class); 75 | 76 | return new Model[] {mode}; 77 | } 78 | 79 | public Model nullResult() { 80 | return null; 81 | } 82 | 83 | public void voidResult(String name, int age) { 84 | String result = "voidResult: " + name + "," + age; 85 | System.out.println("server say: " + result); 86 | } 87 | 88 | public void helloException() { 89 | throw new RuntimeException(protocol + " hello exception"); 90 | } 91 | 92 | public void setProtocol(String protocol) { 93 | this.protocol = protocol; 94 | } 95 | 96 | @Override 97 | public UnSerializableClass helloSerializable() { 98 | return new UnSerializableClass(); 99 | } 100 | 101 | @Override 102 | public void helloSerializable(UnSerializableClass unSerializableClass) { 103 | System.out.println("I've been called"); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /jaws-core/src/test/java/org/hongxi/jaws/protocol/example/IHello.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.protocol.example; 2 | 3 | /** 4 | * Created by shenhongxi on 2021/4/23. 5 | */ 6 | public interface IHello { 7 | String hello(); 8 | 9 | String hello(String name); 10 | 11 | String hello(Model model); 12 | 13 | String hello(int age); 14 | 15 | String hello(byte b); 16 | 17 | String hello(String name, int age, Model model); 18 | 19 | String hello(byte[] bs); 20 | 21 | String hello(int[] is); 22 | 23 | String hello(String[] s); 24 | 25 | String hello(Model[] model); 26 | 27 | String hello(byte[][] bs); 28 | 29 | String hello(int[][] is); 30 | 31 | String hello(String[][] s); 32 | 33 | String hello(Model[][] model); 34 | 35 | Model objResult(String name, int age); 36 | 37 | Model[] objArrayResult(String name, int age); 38 | 39 | void voidResult(String name, int age); 40 | 41 | Model nullResult(); 42 | 43 | void helloException(); 44 | 45 | UnSerializableClass helloSerializable(); 46 | 47 | void helloSerializable(UnSerializableClass unSerializableClass); 48 | } 49 | -------------------------------------------------------------------------------- /jaws-core/src/test/java/org/hongxi/jaws/protocol/example/IHelloMock.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.protocol.example; 2 | 3 | /** 4 | * Created by shenhongxi on 2021/4/23. 5 | */ 6 | public class IHelloMock implements IHello { 7 | 8 | @Override 9 | public String hello() { 10 | // TODO Auto-generated method stub 11 | return "I'm a mock service"; 12 | } 13 | 14 | @Override 15 | public String hello(String name) { 16 | // TODO Auto-generated method stub 17 | return null; 18 | } 19 | 20 | @Override 21 | public String hello(Model model) { 22 | // TODO Auto-generated method stub 23 | return null; 24 | } 25 | 26 | @Override 27 | public String hello(int age) { 28 | // TODO Auto-generated method stub 29 | return null; 30 | } 31 | 32 | @Override 33 | public String hello(byte b) { 34 | // TODO Auto-generated method stub 35 | return null; 36 | } 37 | 38 | @Override 39 | public String hello(String name, int age, Model model) { 40 | // TODO Auto-generated method stub 41 | return null; 42 | } 43 | 44 | @Override 45 | public String hello(byte[] bs) { 46 | // TODO Auto-generated method stub 47 | return null; 48 | } 49 | 50 | @Override 51 | public String hello(int[] is) { 52 | // TODO Auto-generated method stub 53 | return null; 54 | } 55 | 56 | @Override 57 | public String hello(String[] s) { 58 | // TODO Auto-generated method stub 59 | return null; 60 | } 61 | 62 | @Override 63 | public String hello(Model[] model) { 64 | // TODO Auto-generated method stub 65 | return null; 66 | } 67 | 68 | @Override 69 | public String hello(byte[][] bs) { 70 | // TODO Auto-generated method stub 71 | return null; 72 | } 73 | 74 | @Override 75 | public String hello(int[][] is) { 76 | // TODO Auto-generated method stub 77 | return null; 78 | } 79 | 80 | @Override 81 | public String hello(String[][] s) { 82 | // TODO Auto-generated method stub 83 | return null; 84 | } 85 | 86 | @Override 87 | public String hello(Model[][] model) { 88 | // TODO Auto-generated method stub 89 | return null; 90 | } 91 | 92 | @Override 93 | public Model objResult(String name, int age) { 94 | // TODO Auto-generated method stub 95 | return null; 96 | } 97 | 98 | @Override 99 | public Model[] objArrayResult(String name, int age) { 100 | // TODO Auto-generated method stub 101 | return null; 102 | } 103 | 104 | @Override 105 | public void voidResult(String name, int age) { 106 | // TODO Auto-generated method stub 107 | 108 | } 109 | 110 | @Override 111 | public Model nullResult() { 112 | // TODO Auto-generated method stub 113 | return null; 114 | } 115 | 116 | @Override 117 | public void helloException() { 118 | // TODO Auto-generated method stub 119 | 120 | } 121 | 122 | @Override 123 | public UnSerializableClass helloSerializable() { 124 | // TODO Auto-generated method stub 125 | return null; 126 | } 127 | 128 | @Override 129 | public void helloSerializable(UnSerializableClass unSerializableClass) { 130 | // TODO Auto-generated method stub 131 | 132 | } 133 | 134 | } 135 | -------------------------------------------------------------------------------- /jaws-core/src/test/java/org/hongxi/jaws/protocol/example/IWorld.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.protocol.example; 2 | 3 | public interface IWorld { 4 | String world(); 5 | 6 | String world(String world); 7 | 8 | String worldSleep(String world, int sleep); 9 | } -------------------------------------------------------------------------------- /jaws-core/src/test/java/org/hongxi/jaws/protocol/example/MockWorld.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.protocol.example; 2 | 3 | import java.util.concurrent.atomic.AtomicLong; 4 | 5 | public class MockWorld implements IWorld { 6 | public AtomicLong count = new AtomicLong(); 7 | public AtomicLong stringCount = new AtomicLong(); 8 | public AtomicLong sleepCount = new AtomicLong(); 9 | 10 | @Override 11 | public String world() { 12 | count.incrementAndGet(); 13 | return "mockWorld"; 14 | } 15 | 16 | @Override 17 | public String world(String world) { 18 | long num = stringCount.incrementAndGet(); 19 | return world + num; 20 | } 21 | 22 | @Override 23 | public String worldSleep(String world, int sleep) { 24 | long num = sleepCount.incrementAndGet(); 25 | try { 26 | Thread.sleep(sleep); 27 | } catch (InterruptedException ignore) {} 28 | return world + num; 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /jaws-core/src/test/java/org/hongxi/jaws/protocol/example/Model.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.protocol.example; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by shenhongxi on 2021/4/23. 7 | */ 8 | public class Model implements Serializable { 9 | private static final long serialVersionUID = -6642850886054518156L; 10 | 11 | private String name; 12 | private int age; 13 | private Class type; 14 | private long[] addTimes = null; // add attention/fan/filter times 15 | 16 | public Model() {} 17 | 18 | public Model(String name, int age, Class type) { 19 | this.name = name; 20 | this.age = age; 21 | this.type = type; 22 | } 23 | 24 | public String getName() { 25 | return name; 26 | } 27 | 28 | public void setName(String name) { 29 | this.name = name; 30 | } 31 | 32 | public int getAge() { 33 | return age; 34 | } 35 | 36 | public void setAge(int age) { 37 | this.age = age; 38 | } 39 | 40 | public Class getType() { 41 | return type; 42 | } 43 | 44 | public void setType(Class type) { 45 | this.type = type; 46 | } 47 | 48 | public String toString() { 49 | return name + "," + age + "," + type.getName(); 50 | } 51 | 52 | public long[] getAddTimes() { 53 | return addTimes; 54 | } 55 | 56 | public void setAddTimes(long[] addTimes) { 57 | this.addTimes = addTimes; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /jaws-core/src/test/java/org/hongxi/jaws/protocol/example/SimpleObject.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.protocol.example; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by shenhongxi on 2021/4/23. 7 | */ 8 | public class SimpleObject implements Serializable { 9 | 10 | private static final long serialVersionUID = 1845894491038386456L; 11 | private String name = ""; 12 | private int age = 0; 13 | 14 | public SimpleObject(String name) { 15 | this.name = name; 16 | } 17 | 18 | public String getName() { 19 | return name; 20 | } 21 | 22 | public void setName(String name) { 23 | this.name = name; 24 | } 25 | 26 | public int getAge() { 27 | return age; 28 | } 29 | 30 | public void setAge(int age) { 31 | this.age = age; 32 | } 33 | 34 | @Override 35 | public String toString() { 36 | return "name: " + name + " age: " + age; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /jaws-core/src/test/java/org/hongxi/jaws/protocol/example/UnSerializableClass.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.protocol.example; 2 | 3 | /** 4 | * Created by shenhongxi on 2021/4/23. 5 | */ 6 | public class UnSerializableClass { 7 | 8 | public String hello() { 9 | return "I am a unserializable class"; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /jaws-core/src/test/java/org/hongxi/jaws/protocol/example/World.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.protocol.example; 2 | 3 | public class World implements IWorld { 4 | 5 | @Override 6 | public String world() { 7 | return "void"; 8 | } 9 | 10 | @Override 11 | public String world(String world) { 12 | return world; 13 | } 14 | 15 | public String worldSleep(String world, int sleep) { 16 | if (sleep > 0) { 17 | try { 18 | Thread.sleep(sleep); 19 | } catch (InterruptedException e) { 20 | e.printStackTrace(); 21 | } 22 | } 23 | return world; 24 | } 25 | } -------------------------------------------------------------------------------- /jaws-core/src/test/java/org/hongxi/jaws/protocol/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by shenhongxi on 2021/4/17. 3 | */ 4 | package org.hongxi.jaws.protocol; -------------------------------------------------------------------------------- /jaws-core/src/test/resources/META-INF/services/org.hongxi.jaws.transport.EndpointFactory: -------------------------------------------------------------------------------- 1 | org.hongxi.jaws.mock.MockEndpointFactory -------------------------------------------------------------------------------- /jaws-registry-zookeeper/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | org.hongxi 7 | jaws-parent 8 | 0.0.3-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | jaws-registry-zookeeper 13 | 14 | 15 | 16 | org.hongxi 17 | jaws-core 18 | ${project.version} 19 | 20 | 21 | org.apache.zookeeper 22 | zookeeper 23 | 24 | 25 | com.101tec 26 | zkclient 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /jaws-registry-zookeeper/src/main/java/org/hongxi/jaws/registry/zookeeper/StringSerializer.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.registry.zookeeper; 2 | 3 | import org.I0Itec.zkclient.exception.ZkMarshallingError; 4 | import org.I0Itec.zkclient.serialize.SerializableSerializer; 5 | import org.hongxi.jaws.common.util.ByteUtils; 6 | 7 | import java.io.ObjectStreamConstants; 8 | import java.nio.charset.StandardCharsets; 9 | 10 | /** 11 | * Created by shenhongxi on 2021/4/24. 12 | */ 13 | public class StringSerializer extends SerializableSerializer { 14 | @Override 15 | public Object deserialize(byte[] bytes) throws ZkMarshallingError { 16 | if (bytes == null){ 17 | return null; 18 | } 19 | if (bytes.length > 1 && ByteUtils.bytes2short(bytes, 0) == ObjectStreamConstants.STREAM_MAGIC) { 20 | return super.deserialize(bytes); 21 | } 22 | return new String(bytes, StandardCharsets.UTF_8); 23 | } 24 | 25 | @Override 26 | public byte[] serialize(Object obj) throws ZkMarshallingError { 27 | return obj.toString().getBytes(StandardCharsets.UTF_8); 28 | } 29 | } -------------------------------------------------------------------------------- /jaws-registry-zookeeper/src/main/java/org/hongxi/jaws/registry/zookeeper/ZkNodeType.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.registry.zookeeper; 2 | 3 | /** 4 | * Created by shenhongxi on 2021/4/24. 5 | */ 6 | public enum ZkNodeType { 7 | 8 | AVAILABLE_SERVER("server"), 9 | UNAVAILABLE_SERVER("unavailableServer"), 10 | CLIENT("client"); 11 | 12 | private String value; 13 | 14 | ZkNodeType(String value){ 15 | this.value = value; 16 | } 17 | 18 | public String getValue() { 19 | return value; 20 | } 21 | } -------------------------------------------------------------------------------- /jaws-registry-zookeeper/src/main/java/org/hongxi/jaws/registry/zookeeper/ZkUtils.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.registry.zookeeper; 2 | 3 | import org.hongxi.jaws.common.JawsConstants; 4 | import org.hongxi.jaws.rpc.URL; 5 | 6 | /** 7 | * Created by shenhongxi on 2021/4/24. 8 | */ 9 | public class ZkUtils { 10 | 11 | public static String toGroupPath(URL url) { 12 | return JawsConstants.ZOOKEEPER_REGISTRY_NAMESPACE + JawsConstants.PATH_SEPARATOR + url.getGroup(); 13 | } 14 | 15 | public static String toServicePath(URL url) { 16 | return toGroupPath(url) + JawsConstants.PATH_SEPARATOR + url.getPath(); 17 | } 18 | 19 | public static String toCommandPath(URL url) { 20 | return toGroupPath(url) + JawsConstants.ZOOKEEPER_REGISTRY_COMMAND; 21 | } 22 | 23 | public static String toNodeTypePath(URL url, ZkNodeType nodeType) { 24 | return toServicePath(url) + JawsConstants.PATH_SEPARATOR + nodeType.getValue(); 25 | } 26 | 27 | public static String toNodePath(URL url, ZkNodeType nodeType) { 28 | return toNodeTypePath(url, nodeType) + JawsConstants.PATH_SEPARATOR + url.getServerPortStr(); 29 | } 30 | } -------------------------------------------------------------------------------- /jaws-registry-zookeeper/src/main/java/org/hongxi/jaws/registry/zookeeper/ZookeeperRegistryFactory.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.registry.zookeeper; 2 | 3 | import org.I0Itec.zkclient.ZkClient; 4 | import org.I0Itec.zkclient.exception.ZkException; 5 | import org.hongxi.jaws.common.URLParamType; 6 | import org.hongxi.jaws.common.extension.SpiMeta; 7 | import org.hongxi.jaws.registry.Registry; 8 | import org.hongxi.jaws.registry.support.AbstractRegistryFactory; 9 | import org.hongxi.jaws.rpc.URL; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | /** 14 | * Created by shenhongxi on 2021/4/24. 15 | */ 16 | @SpiMeta(name = "zookeeper") 17 | public class ZookeeperRegistryFactory extends AbstractRegistryFactory { 18 | 19 | private static final Logger log = LoggerFactory.getLogger(ZookeeperRegistryFactory.class); 20 | 21 | @Override 22 | protected Registry createRegistry(URL registryUrl) { 23 | try { 24 | int timeout = registryUrl.getIntParameter(URLParamType.connectTimeout.getName(), URLParamType.connectTimeout.intValue()); 25 | int sessionTimeout = registryUrl.getIntParameter(URLParamType.registrySessionTimeout.getName(), URLParamType.registrySessionTimeout.intValue()); 26 | ZkClient zkClient = createInnerZkClient(registryUrl.getParameter("address"), sessionTimeout, timeout); 27 | return new ZookeeperRegistry(registryUrl, zkClient); 28 | } catch (ZkException e) { 29 | log.error("[ZookeeperRegistry] fail to connect zookeeper", e); 30 | throw e; 31 | } 32 | } 33 | 34 | protected ZkClient createInnerZkClient(String zkServers, int sessionTimeout, int connectionTimeout) { 35 | return new ZkClient(zkServers, sessionTimeout, connectionTimeout); 36 | } 37 | } -------------------------------------------------------------------------------- /jaws-registry-zookeeper/src/main/java/org/hongxi/jaws/registry/zookeeper/ZookeeperStringSerializerRegistryFactory.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.registry.zookeeper; 2 | 3 | import org.I0Itec.zkclient.ZkClient; 4 | import org.hongxi.jaws.common.extension.SpiMeta; 5 | 6 | /** 7 | * Created by shenhongxi on 2021/4/24. 8 | */ 9 | @SpiMeta(name = "zk") 10 | public class ZookeeperStringSerializerRegistryFactory extends ZookeeperRegistryFactory { 11 | @Override 12 | protected ZkClient createInnerZkClient(String zkServers, int sessionTimeout, int connectionTimeout) { 13 | return new ZkClient(zkServers, sessionTimeout, connectionTimeout, new StringSerializer()); 14 | } 15 | } -------------------------------------------------------------------------------- /jaws-registry-zookeeper/src/main/resources/META-INF/services/org.hongxi.jaws.registry.RegistryFactory: -------------------------------------------------------------------------------- 1 | org.hongxi.jaws.registry.zookeeper.ZookeeperRegistryFactory 2 | org.hongxi.jaws.registry.zookeeper.ZookeeperStringSerializerRegistryFactory -------------------------------------------------------------------------------- /jaws-registry-zookeeper/src/test/java/org/hongxi/jaws/registry/zookeeper/EmbeddedZookeeper.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.registry.zookeeper; 2 | 3 | import org.apache.zookeeper.server.ServerConfig; 4 | import org.apache.zookeeper.server.ZooKeeperServerMain; 5 | import org.apache.zookeeper.server.quorum.QuorumPeerConfig; 6 | 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | import java.util.Properties; 10 | 11 | /** 12 | * Created by shenhongxi on 2021/4/24. 13 | */ 14 | public class EmbeddedZookeeper { 15 | private ZooKeeperServerMain zookeeperServer; 16 | 17 | public void start() throws IOException, QuorumPeerConfig.ConfigException { 18 | Properties properties = new Properties(); 19 | InputStream in = EmbeddedZookeeper.class.getResourceAsStream("/zoo.cfg"); 20 | properties.load(in); 21 | 22 | QuorumPeerConfig quorumConfiguration = new QuorumPeerConfig(); 23 | quorumConfiguration.parseProperties(properties); 24 | in.close(); 25 | 26 | zookeeperServer = new ZooKeeperServerMain(); 27 | final ServerConfig configuration = new ServerConfig(); 28 | configuration.readFrom(quorumConfiguration); 29 | 30 | new Thread(() -> { 31 | try { 32 | zookeeperServer.runFromConfig(configuration); 33 | } catch (IOException ignore) { 34 | } 35 | }).start(); 36 | } 37 | } -------------------------------------------------------------------------------- /jaws-registry-zookeeper/src/test/java/org/hongxi/jaws/registry/zookeeper/ZkStartup.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.registry.zookeeper; 2 | 3 | import org.apache.zookeeper.server.quorum.QuorumPeerConfig; 4 | 5 | import java.io.IOException; 6 | 7 | /** 8 | * Created by shenhongxi on 2021/4/24. 9 | */ 10 | public class ZkStartup { 11 | 12 | public static void main(String[] args) throws QuorumPeerConfig.ConfigException, IOException { 13 | new EmbeddedZookeeper().start(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /jaws-registry-zookeeper/src/test/resources/zoo.cfg: -------------------------------------------------------------------------------- 1 | # The number of milliseconds of each tick 2 | tickTime=2000 3 | # The number of ticks that the initial 4 | # synchronization phase can take 5 | initLimit=10 6 | # The number of ticks that can pass between 7 | # sending a request and getting an acknowledgement 8 | syncLimit=5 9 | # the directory where the snapshot is stored. 10 | # do not use /tmp for storage, /tmp here is just 11 | # example sakes. 12 | dataDir=/tmp/zookeeper/jaws-test 13 | # the port at which the clients will connect 14 | clientPort=2181 15 | # the maximum number of client connections. 16 | # increase this if you need to handle more clients 17 | #maxClientCnxns=60 18 | # 19 | # Be sure to read the maintenance section of the 20 | # administrator guide before turning on autopurge. 21 | # 22 | # http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance 23 | # 24 | # The number of snapshots to retain in dataDir 25 | #autopurge.snapRetainCount=3 26 | # Purge task interval in hours 27 | # Set to "0" to disable auto purge feature 28 | #autopurge.purgeInterval=1 -------------------------------------------------------------------------------- /jaws-samples/README.md: -------------------------------------------------------------------------------- 1 | ### 演示: 2 | - 启动 zk `org.hongxi.jaws.zk.ZKStartup` 3 | - 启动 provider `org.hongxi.jaws.sample.provider.SampleProvider` 4 | - 启动 consumer `org.hongxi.jaws.sample.consumer.SampleConsumer` 5 | - 启动 zkcli 查看 zk 内部数据 `org.hongxi.jaws.zk.ZKClient` 6 | -------------------------------------------------------------------------------- /jaws-samples/jaws-sample-api/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | org.hongxi 7 | jaws-samples 8 | 0.0.3-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | jaws-sample-api 13 | 14 | -------------------------------------------------------------------------------- /jaws-samples/jaws-sample-api/src/main/java/org/hongxi/jaws/sample/api/DemoService.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.sample.api; 2 | 3 | import org.hongxi.jaws.sample.api.model.Contacts; 4 | import org.hongxi.jaws.sample.api.model.User; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | /** 10 | * Created by shenhongxi on 2021/4/25. 11 | */ 12 | public interface DemoService { 13 | 14 | String hello(String name); 15 | 16 | User rename(User user, String name); 17 | 18 | List getUsers(); 19 | 20 | Map map(List users); 21 | 22 | void save(Contacts contacts); 23 | 24 | int save(List contactsList); 25 | } 26 | -------------------------------------------------------------------------------- /jaws-samples/jaws-sample-api/src/main/java/org/hongxi/jaws/sample/api/model/Contacts.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.sample.api.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.io.Serializable; 8 | import java.util.List; 9 | 10 | /** 11 | * Created by shenhongxi on 2021/4/26. 12 | */ 13 | @Data 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | public class Contacts implements Serializable { 17 | private static final long serialVersionUID = 9095342848908217853L; 18 | 19 | private Long id; 20 | 21 | private User user; 22 | 23 | private List phones; 24 | 25 | private List addresses; 26 | } 27 | -------------------------------------------------------------------------------- /jaws-samples/jaws-sample-api/src/main/java/org/hongxi/jaws/sample/api/model/Phone.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.sample.api.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.io.Serializable; 8 | 9 | /** 10 | * Created by shenhongxi on 2021/4/26. 11 | */ 12 | @Data 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | public class Phone implements Serializable { 16 | private static final long serialVersionUID = -56932839374275492L; 17 | 18 | private Integer number; 19 | } 20 | -------------------------------------------------------------------------------- /jaws-samples/jaws-sample-api/src/main/java/org/hongxi/jaws/sample/api/model/User.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.sample.api.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.io.Serializable; 8 | 9 | /** 10 | * Created by shenhongxi on 2021/4/25. 11 | */ 12 | @Data 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | public class User implements Serializable { 16 | 17 | private static final long serialVersionUID = 6190590587012468969L; 18 | 19 | private String name; 20 | 21 | private int age; 22 | } 23 | -------------------------------------------------------------------------------- /jaws-samples/jaws-sample-consumer/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | org.hongxi 7 | jaws-samples 8 | 0.0.3-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | jaws-sample-consumer 13 | 14 | 15 | 16 | org.hongxi 17 | jaws-core 18 | ${project.version} 19 | 20 | 21 | org.hongxi 22 | jaws-transport-netty 23 | ${project.version} 24 | 25 | 26 | org.hongxi 27 | jaws-registry-zookeeper 28 | ${project.version} 29 | 30 | 31 | 32 | org.hongxi 33 | jaws-sample-api 34 | ${project.version} 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /jaws-samples/jaws-sample-consumer/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | ${log.context.name} 9 | 10 | 11 | 12 | ${log.pattern} 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /jaws-samples/jaws-sample-provider/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | org.hongxi 7 | jaws-samples 8 | 0.0.3-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | jaws-sample-provider 13 | 14 | 15 | 16 | org.hongxi 17 | jaws-core 18 | ${project.version} 19 | 20 | 21 | org.hongxi 22 | jaws-transport-netty 23 | ${project.version} 24 | 25 | 26 | org.hongxi 27 | jaws-registry-zookeeper 28 | ${project.version} 29 | 30 | 31 | 32 | org.hongxi 33 | jaws-sample-api 34 | ${project.version} 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /jaws-samples/jaws-sample-provider/src/main/java/org/hongxi/jaws/sample/provider/SampleProvider.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.sample.provider; 2 | 3 | import org.hongxi.jaws.common.JawsConstants; 4 | import org.hongxi.jaws.config.ProtocolConfig; 5 | import org.hongxi.jaws.config.RegistryConfig; 6 | import org.hongxi.jaws.config.ServiceConfig; 7 | import org.hongxi.jaws.sample.api.DemoService; 8 | import org.hongxi.jaws.sample.provider.service.DemoServiceImpl; 9 | import org.hongxi.jaws.switcher.JawsSwitcherUtils; 10 | 11 | /** 12 | * Created by shenhongxi on 2021/4/25. 13 | */ 14 | public class SampleProvider { 15 | 16 | public static void main(String[] args) { 17 | ServiceConfig serviceConfig = new ServiceConfig<>(); 18 | serviceConfig.setRef(new DemoServiceImpl()); 19 | serviceConfig.setApplication("sample-provider"); 20 | serviceConfig.setModule("sample"); 21 | serviceConfig.setCheck("true"); 22 | serviceConfig.setInterface(DemoService.class); 23 | serviceConfig.setGroup("test"); 24 | serviceConfig.setShareChannel(true); 25 | serviceConfig.setVersion("2.0"); 26 | serviceConfig.setProtocol(createProtocolConfig(JawsConstants.PROTOCOL_JAWS)); 27 | serviceConfig.setRegistry(createRegistryConfig(JawsConstants.REGISTRY_PROTOCOL_ZOOKEEPER)); 28 | serviceConfig.setExport(JawsConstants.PROTOCOL_JAWS + ":" + 10000); 29 | 30 | serviceConfig.export(); 31 | 32 | JawsSwitcherUtils.setSwitcherValue(JawsConstants.REGISTRY_HEARTBEAT_SWITCHER, true); 33 | } 34 | 35 | private static ProtocolConfig createProtocolConfig(String protocolName) { 36 | ProtocolConfig protocolConfig = new ProtocolConfig(); 37 | protocolConfig.setName(protocolName); 38 | protocolConfig.setId(protocolConfig.getName()); 39 | protocolConfig.setEndpointFactory("jaws"); 40 | return protocolConfig; 41 | } 42 | 43 | private static RegistryConfig createRegistryConfig(String protocolName) { 44 | RegistryConfig registryConfig = new RegistryConfig(); 45 | registryConfig.setRegProtocol(protocolName); 46 | registryConfig.setName("defaultRegistry"); 47 | registryConfig.setId(registryConfig.getName()); 48 | registryConfig.setAddress("127.0.0.1"); 49 | registryConfig.setPort(2181); 50 | return registryConfig; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /jaws-samples/jaws-sample-provider/src/main/java/org/hongxi/jaws/sample/provider/service/DemoServiceImpl.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.sample.provider.service; 2 | 3 | import org.hongxi.jaws.sample.api.DemoService; 4 | import org.hongxi.jaws.sample.api.model.Contacts; 5 | import org.hongxi.jaws.sample.api.model.User; 6 | 7 | import java.util.ArrayList; 8 | import java.util.HashMap; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | /** 13 | * Created by shenhongxi on 2021/4/25. 14 | */ 15 | public class DemoServiceImpl implements DemoService { 16 | 17 | @Override 18 | public String hello(String name) { 19 | return "Hello, " + name; 20 | } 21 | 22 | @Override 23 | public User rename(User user, String name) { 24 | user.setName(name); 25 | return user; 26 | } 27 | 28 | @Override 29 | public List getUsers() { 30 | List users = new ArrayList<>(); 31 | users.add(new User("lily", 24)); 32 | users.add(new User("lucy", 25)); 33 | return users; 34 | } 35 | 36 | @Override 37 | public Map map(List users) { 38 | Map map = new HashMap<>(); 39 | users.forEach(e -> map.put(e.getName(), e)); 40 | return map; 41 | } 42 | 43 | @Override 44 | public void save(Contacts contacts) { 45 | System.out.println(contacts); 46 | } 47 | 48 | @Override 49 | public int save(List contactsList) { 50 | System.out.println(contactsList); 51 | return contactsList.size(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /jaws-samples/jaws-sample-provider/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | ${log.context.name} 9 | 10 | 11 | 12 | ${log.pattern} 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /jaws-samples/jaws-test/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | org.hongxi 7 | jaws-samples 8 | 0.0.3-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | jaws-test 13 | 14 | 15 | 16 | org.hongxi 17 | jaws-core 18 | ${project.version} 19 | 20 | 21 | org.hongxi 22 | jaws-transport-netty 23 | ${project.version} 24 | 25 | 26 | org.hongxi 27 | jaws-registry-zookeeper 28 | ${project.version} 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /jaws-samples/jaws-test/src/test/java/org/jaws/test/HelloService.java: -------------------------------------------------------------------------------- 1 | package org.jaws.test; 2 | 3 | /** 4 | * Created by shenhongxi on 2021/4/25. 5 | */ 6 | public interface HelloService { 7 | 8 | String hello(String name); 9 | 10 | User rename(User user, String name); 11 | } 12 | -------------------------------------------------------------------------------- /jaws-samples/jaws-test/src/test/java/org/jaws/test/HelloServiceImpl.java: -------------------------------------------------------------------------------- 1 | package org.jaws.test; 2 | 3 | public class HelloServiceImpl implements HelloService { 4 | 5 | @Override 6 | public String hello(String name) { 7 | return "Hello, " + name; 8 | } 9 | 10 | @Override 11 | public User rename(User user, String name) { 12 | user.setName(name); 13 | return user; 14 | } 15 | } -------------------------------------------------------------------------------- /jaws-samples/jaws-test/src/test/java/org/jaws/test/RefererConfigTest.java: -------------------------------------------------------------------------------- 1 | package org.jaws.test; 2 | 3 | import org.hongxi.jaws.common.JawsConstants; 4 | import org.hongxi.jaws.config.ProtocolConfig; 5 | import org.hongxi.jaws.config.RefererConfig; 6 | import org.hongxi.jaws.config.RegistryConfig; 7 | import org.hongxi.jaws.config.ServiceConfig; 8 | import org.hongxi.jaws.switcher.JawsSwitcherUtils; 9 | import org.junit.Test; 10 | 11 | import static org.junit.Assert.assertEquals; 12 | 13 | /** 14 | * Created by shenhongxi on 2021/4/23. 15 | */ 16 | public class RefererConfigTest extends BaseTestCase { 17 | 18 | private RefererConfig refererConfig = null; 19 | private ServiceConfig serviceConfig = null; 20 | 21 | @Override 22 | public void setUp() throws Exception { 23 | super.setUp(); 24 | 25 | RegistryConfig registryConfig = createRegistryConfig(JawsConstants.REGISTRY_PROTOCOL_ZOOKEEPER); 26 | ProtocolConfig protocolConfig = createProtocolConfig(JawsConstants.PROTOCOL_JAWS); 27 | 28 | serviceConfig = createServiceConfig(); 29 | serviceConfig.setProtocol(protocolConfig); 30 | serviceConfig.setRegistry(registryConfig); 31 | serviceConfig.setExport(JawsConstants.PROTOCOL_JAWS + ":" + 10001); 32 | 33 | refererConfig = createRefererConfig(); 34 | refererConfig.setProtocol(protocolConfig); 35 | refererConfig.setRegistry(registryConfig); 36 | refererConfig.setCheck("false"); 37 | } 38 | 39 | @Override 40 | public void tearDown() throws Exception { 41 | super.tearDown(); 42 | if (refererConfig != null) { 43 | refererConfig.destroy(); 44 | } 45 | if (serviceConfig != null) { 46 | serviceConfig.unexport(); 47 | } 48 | } 49 | 50 | @Test 51 | public void testInvocation() { 52 | serviceConfig.export(); 53 | JawsSwitcherUtils.setSwitcherValue(JawsConstants.REGISTRY_HEARTBEAT_SWITCHER, true); 54 | 55 | HelloService helloService = refererConfig.getRef(); 56 | String r = helloService.hello("lily"); 57 | assertEquals("Hello, lily", r); 58 | 59 | User user = new User(); 60 | user.setName("lily"); 61 | user.setAge(24); 62 | User newUser = helloService.rename(user, "lucy"); 63 | assertEquals("lucy", newUser.getName()); 64 | } 65 | } -------------------------------------------------------------------------------- /jaws-samples/jaws-test/src/test/java/org/jaws/test/ServiceConfigTest.java: -------------------------------------------------------------------------------- 1 | package org.jaws.test; 2 | 3 | import org.hongxi.jaws.common.JawsConstants; 4 | import org.hongxi.jaws.config.ServiceConfig; 5 | import org.junit.Test; 6 | 7 | import static org.junit.Assert.*; 8 | 9 | /** 10 | * Created by shenhongxi on 2021/4/21. 11 | */ 12 | public class ServiceConfigTest extends BaseTestCase { 13 | 14 | private ServiceConfig serviceConfig = null; 15 | 16 | @Override 17 | public void setUp() throws Exception { 18 | super.setUp(); 19 | serviceConfig = createServiceConfig(); 20 | serviceConfig.setProtocol(createProtocolConfig(JawsConstants.PROTOCOL_JAWS)); 21 | serviceConfig.setRegistry(createRegistryConfig(JawsConstants.REGISTRY_PROTOCOL_ZOOKEEPER)); 22 | serviceConfig.setExport(JawsConstants.PROTOCOL_JAWS + ":" + 10001); 23 | } 24 | 25 | @Override 26 | public void tearDown() throws Exception { 27 | super.tearDown(); 28 | if (serviceConfig != null) { 29 | serviceConfig.unexport(); 30 | } 31 | } 32 | 33 | @Test 34 | public void testExport() { 35 | serviceConfig.export(); 36 | 37 | assertTrue(serviceConfig.getExported().get()); 38 | assertEquals(serviceConfig.getExporters().size(), 1); 39 | assertEquals(serviceConfig.getRegistryUrls().size(), 1); 40 | } 41 | 42 | @Test 43 | public void testUnexport() { 44 | testExport(); 45 | serviceConfig.unexport(); 46 | assertFalse(serviceConfig.getExported().get()); 47 | assertEquals(serviceConfig.getExporters().size(), 0); 48 | } 49 | } -------------------------------------------------------------------------------- /jaws-samples/jaws-test/src/test/java/org/jaws/test/User.java: -------------------------------------------------------------------------------- 1 | package org.jaws.test; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * Created by shenhongxi on 2021/4/25. 9 | */ 10 | @Data 11 | public class User implements Serializable { 12 | 13 | private static final long serialVersionUID = 6190590587012468969L; 14 | 15 | private String name; 16 | 17 | private int age; 18 | } 19 | -------------------------------------------------------------------------------- /jaws-samples/jaws-test/src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | ${log.context.name} 9 | 10 | 11 | 12 | ${log.pattern} 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /jaws-samples/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | org.hongxi 7 | jaws-parent 8 | 0.0.3-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | jaws-samples 13 | pom 14 | 15 | 16 | jaws-sample-provider 17 | jaws-sample-consumer 18 | jaws-sample-api 19 | jaws-test 20 | zk 21 | 22 | 23 | 24 | 25 | org.projectlombok 26 | lombok 27 | 1.18.18 28 | compile 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /jaws-samples/zk/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | org.hongxi 7 | jaws-samples 8 | 0.0.3-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | zk 13 | 14 | 15 | 16 | org.apache.zookeeper 17 | zookeeper 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /jaws-samples/zk/src/main/java/org/hongxi/jaws/zk/ZKClient.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.zk; 2 | 3 | import org.apache.zookeeper.ZooKeeperMain; 4 | 5 | /** 6 | * Created by shenhongxi on 2020/9/17. 7 | */ 8 | public class ZKClient { 9 | 10 | public static void main(String[] args) throws Exception { 11 | ZooKeeperMain.main(args); 12 | // 列出根节点下的所有子节点:ls / 13 | // 列出某节点下的所有子节点:ls /jaws 14 | } 15 | } -------------------------------------------------------------------------------- /jaws-samples/zk/src/main/java/org/hongxi/jaws/zk/ZKStartup.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.zk; 2 | 3 | import org.apache.zookeeper.server.ServerConfig; 4 | import org.apache.zookeeper.server.ZooKeeperServerMain; 5 | import org.apache.zookeeper.server.quorum.QuorumPeerConfig; 6 | 7 | import java.io.InputStream; 8 | import java.util.Properties; 9 | 10 | public class ZKStartup { 11 | 12 | public static void main(String[] args) throws Exception { 13 | QuorumPeerConfig quorumPeerConfig = new QuorumPeerConfig(); 14 | InputStream inputStream = ZKStartup.class.getResourceAsStream("/zookeeper.properties"); 15 | Properties properties = new Properties(); 16 | properties.load(inputStream); 17 | quorumPeerConfig.parseProperties(properties); 18 | ServerConfig serverConfig = new ServerConfig(); 19 | serverConfig.readFrom(quorumPeerConfig); 20 | new ZooKeeperServerMain().runFromConfig(serverConfig); 21 | } 22 | } -------------------------------------------------------------------------------- /jaws-samples/zk/src/main/resources/zookeeper.properties: -------------------------------------------------------------------------------- 1 | dataDir=/tmp/zookeeper 2 | # the port at which the clients will connect 3 | clientPort=2181 4 | # disable the per-ip limit on the number of connections since this is a non-production config 5 | maxClientCnxns=0 6 | -------------------------------------------------------------------------------- /jaws-spring-boot-starter/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | org.hongxi 7 | jaws-parent 8 | 0.0.3-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | jaws-spring-boot-starter 13 | 14 | 15 | 2.4.3 16 | 17 | 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-parent 23 | ${spring.boot.version} 24 | import 25 | pom 26 | 27 | 28 | 29 | 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter 34 | true 35 | 36 | 37 | 38 | org.hongxi 39 | jaws-core 40 | ${project.version} 41 | 42 | 43 | org.hongxi 44 | jaws-transport-netty 45 | ${project.version} 46 | 47 | 48 | org.hongxi 49 | jaws-registry-zookeeper 50 | ${project.version} 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /jaws-spring-boot-starter/src/main/java/org/hongxi/jaws/spring/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by shenhongxi on 2020/6/14. 3 | */ 4 | package org.hongxi.jaws.spring; -------------------------------------------------------------------------------- /jaws-spring-boot-starter/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/javahongxi/jaws/7af29a7eed45403772c382ba190af13afa73937b/jaws-spring-boot-starter/src/main/resources/META-INF/spring.factories -------------------------------------------------------------------------------- /jaws-transport-netty/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | org.hongxi 7 | jaws-parent 8 | 0.0.3-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | jaws-transport-netty 13 | 14 | 15 | 16 | org.hongxi 17 | jaws-core 18 | ${project.version} 19 | 20 | 21 | io.netty 22 | netty-all 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /jaws-transport-netty/src/main/java/org/hongxi/jaws/transport/netty/NettyChannelFactory.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.transport.netty; 2 | 3 | import org.hongxi.jaws.common.threadpool.DefaultThreadFactory; 4 | import org.hongxi.jaws.common.threadpool.StandardThreadPoolExecutor; 5 | import org.hongxi.jaws.transport.SharedObjectFactory; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import java.util.concurrent.ExecutorService; 10 | import java.util.concurrent.ThreadPoolExecutor; 11 | import java.util.concurrent.TimeUnit; 12 | import java.util.concurrent.locks.ReentrantLock; 13 | 14 | /** 15 | * Created by shenhongxi on 2020/7/30. 16 | */ 17 | public class NettyChannelFactory implements SharedObjectFactory { 18 | private static final Logger logger = LoggerFactory.getLogger(NettyChannelFactory.class); 19 | 20 | private static final ExecutorService rebuildExecutorService = new StandardThreadPoolExecutor( 21 | 5, 30, 10L, TimeUnit.SECONDS, 100, 22 | new DefaultThreadFactory("RebuildExecutorService", true), 23 | new ThreadPoolExecutor.CallerRunsPolicy()); 24 | private NettyClient nettyClient; 25 | private String factoryName; 26 | 27 | public NettyChannelFactory(NettyClient nettyClient) { 28 | this.nettyClient = nettyClient; 29 | this.factoryName = "NettyChannelFactory_" + nettyClient.getUrl().getHost() + 30 | "_" + nettyClient.getUrl().getPort(); 31 | } 32 | 33 | @Override 34 | public NettyChannel makeObject() { 35 | return new NettyChannel(nettyClient); 36 | } 37 | 38 | @Override 39 | public boolean rebuildObject(NettyChannel nettyChannel, boolean async) { 40 | ReentrantLock lock = nettyChannel.getLock(); 41 | if (lock.tryLock()) { 42 | try { 43 | if (!nettyChannel.isAvailable() && !nettyChannel.isReconnect()) { 44 | nettyChannel.reconnect(); 45 | if (async) { 46 | rebuildExecutorService.submit(new RebuildTask(nettyChannel)); 47 | } else { 48 | nettyChannel.close(); 49 | nettyChannel.open(); 50 | logger.info("rebuild channel success: {}", nettyChannel.getUrl()); 51 | } 52 | } 53 | } catch (Exception e) { 54 | logger.error("rebuild error: {}, {}", this.toString(), nettyChannel.getUrl(), e); 55 | } finally { 56 | lock.unlock(); 57 | } 58 | return true; 59 | } 60 | return false; 61 | } 62 | 63 | @Override 64 | public String toString() { 65 | return factoryName; 66 | } 67 | 68 | class RebuildTask implements Runnable { 69 | private NettyChannel channel; 70 | 71 | public RebuildTask(NettyChannel channel) { 72 | this.channel = channel; 73 | } 74 | 75 | @Override 76 | public void run() { 77 | try { 78 | channel.getLock().lock(); 79 | channel.close(); 80 | channel.open(); 81 | logger.info("rebuild channel success: {}", channel.getUrl()); 82 | } catch (Exception e) { 83 | logger.error("rebuild error: {}, {}", this.toString(), channel.getUrl(), e); 84 | } finally { 85 | channel.getLock().unlock(); 86 | } 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /jaws-transport-netty/src/main/java/org/hongxi/jaws/transport/netty/NettyEncoder.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.transport.netty; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import io.netty.handler.codec.MessageToByteEncoder; 6 | 7 | /** 8 | * Created by shenhongxi on 2020/7/6. 9 | */ 10 | public class NettyEncoder extends MessageToByteEncoder { 11 | @Override 12 | protected void encode(ChannelHandlerContext ctx, byte[] msg, ByteBuf out) throws Exception { 13 | out.writeBytes(msg); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /jaws-transport-netty/src/main/java/org/hongxi/jaws/transport/netty/NettyEndpointFactory.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.transport.netty; 2 | 3 | import org.hongxi.jaws.common.extension.SpiMeta; 4 | import org.hongxi.jaws.rpc.URL; 5 | import org.hongxi.jaws.transport.Client; 6 | import org.hongxi.jaws.transport.MessageHandler; 7 | import org.hongxi.jaws.transport.Server; 8 | import org.hongxi.jaws.transport.support.AbstractEndpointFactory; 9 | 10 | /** 11 | * Created by shenhongxi on 2020/7/31. 12 | */ 13 | @SpiMeta(name = "jaws") 14 | public class NettyEndpointFactory extends AbstractEndpointFactory { 15 | @Override 16 | protected Server innerCreateServer(URL url, MessageHandler messageHandler) { 17 | return new NettyServer(url, messageHandler); 18 | } 19 | 20 | @Override 21 | protected Client innerCreateClient(URL url) { 22 | return new NettyClient(url); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /jaws-transport-netty/src/main/java/org/hongxi/jaws/transport/netty/NettyMessage.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.transport.netty; 2 | 3 | /** 4 | * Created by shenhongxi on 2020/7/25. 5 | */ 6 | public class NettyMessage { 7 | private boolean isRequest; 8 | private long requestId; 9 | private byte[] data; 10 | private long startTime; 11 | 12 | public NettyMessage(boolean isRequest, long requestId, byte[] data) { 13 | this.isRequest = isRequest; 14 | this.requestId = requestId; 15 | this.data = data; 16 | } 17 | 18 | public boolean isRequest() { 19 | return isRequest; 20 | } 21 | 22 | public void setRequest(boolean request) { 23 | isRequest = request; 24 | } 25 | 26 | public long getRequestId() { 27 | return requestId; 28 | } 29 | 30 | public void setRequestId(long requestId) { 31 | this.requestId = requestId; 32 | } 33 | 34 | public byte[] getData() { 35 | return data; 36 | } 37 | 38 | public void setData(byte[] data) { 39 | this.data = data; 40 | } 41 | 42 | public long getStartTime() { 43 | return startTime; 44 | } 45 | 46 | public void setStartTime(long startTime) { 47 | this.startTime = startTime; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /jaws-transport-netty/src/main/java/org/hongxi/jaws/transport/netty/NettyServerChannelManage.java: -------------------------------------------------------------------------------- 1 | package org.hongxi.jaws.transport.netty; 2 | 3 | import io.netty.channel.Channel; 4 | import io.netty.channel.ChannelHandler; 5 | import io.netty.channel.ChannelHandlerContext; 6 | import io.netty.channel.ChannelInboundHandlerAdapter; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | import java.net.InetSocketAddress; 11 | import java.util.Map; 12 | import java.util.concurrent.ConcurrentHashMap; 13 | import java.util.concurrent.ConcurrentMap; 14 | 15 | /** 16 | * Created by shenhongxi on 2020/6/27. 17 | */ 18 | @ChannelHandler.Sharable 19 | public class NettyServerChannelManage extends ChannelInboundHandlerAdapter { 20 | private static final Logger logger = LoggerFactory.getLogger(NettyServerChannelManage.class); 21 | 22 | private ConcurrentMap channels = new ConcurrentHashMap<>(); 23 | 24 | private int maxChannels; 25 | 26 | public NettyServerChannelManage(int maxChannels) { 27 | super(); 28 | this.maxChannels = maxChannels; 29 | } 30 | 31 | @Override 32 | public void channelRegistered(ChannelHandlerContext ctx) throws Exception { 33 | Channel channel = ctx.channel(); 34 | if (channels.size() >= maxChannels) { 35 | logger.warn("connected channel size out of limit: limit={} current={}", maxChannels, channels.size()); 36 | channel.close(); 37 | } else { 38 | String channelKey = getChannelKey((InetSocketAddress) channel.localAddress(), (InetSocketAddress) channel.remoteAddress()); 39 | channels.put(channelKey, channel); 40 | ctx.fireChannelRegistered(); 41 | } 42 | } 43 | 44 | @Override 45 | public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { 46 | Channel channel = ctx.channel(); 47 | String channelKey = getChannelKey((InetSocketAddress) channel.localAddress(), (InetSocketAddress) channel.remoteAddress()); 48 | channels.remove(channelKey); 49 | ctx.fireChannelUnregistered(); 50 | } 51 | 52 | public Map getChannels() { 53 | return channels; 54 | } 55 | 56 | private String getChannelKey(InetSocketAddress localAddress, InetSocketAddress remoteAddress) { 57 | String key = ""; 58 | if (localAddress == null || localAddress.getAddress() == null) { 59 | key += "null-"; 60 | } else { 61 | key += localAddress.getAddress().getHostAddress() + ":" + localAddress.getPort() + "-"; 62 | } 63 | 64 | if (remoteAddress == null || remoteAddress.getAddress() == null) { 65 | key += "null"; 66 | } else { 67 | key += remoteAddress.getAddress().getHostAddress() + ":" + remoteAddress.getPort(); 68 | } 69 | return key; 70 | } 71 | 72 | public void close() { 73 | channels.forEach((k, v) -> { 74 | if (v != null) { 75 | try { 76 | v.close(); 77 | } catch (Exception e) { 78 | logger.error("close channel error, {}", k, e); 79 | } 80 | } 81 | }); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /jaws-transport-netty/src/main/resources/META-INF/services/org.hongxi.jaws.transport.EndpointFactory: -------------------------------------------------------------------------------- 1 | org.hongxi.jaws.transport.netty.NettyEndpointFactory --------------------------------------------------------------------------------