├── .gitignore ├── LICENSE ├── README.md ├── iris ├── .gitignore ├── README.md ├── iris-bom │ └── pom.xml ├── iris-client │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── leiwei2094 │ │ │ └── iris │ │ │ └── client │ │ │ ├── ConnectManager.java │ │ │ ├── IConnectManager.java │ │ │ ├── IRpcClient.java │ │ │ ├── RpcClient.java │ │ │ ├── RpcClientHandler.java │ │ │ ├── RpcClientInitializer.java │ │ │ ├── RpcFuture.java │ │ │ ├── RpcInvokeInterceptor.java │ │ │ └── RpcRequestHolder.java │ │ └── test │ │ ├── java │ │ └── com │ │ │ └── leiwei2094 │ │ │ └── iris │ │ │ └── client │ │ │ ├── ClientTest.java │ │ │ └── bytebuddy │ │ │ ├── ByteBuddyTest.java │ │ │ └── GeneralInterceptor.java │ │ └── resources │ │ └── iris.properties ├── iris-core │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── leiwei2094 │ │ │ │ └── iris │ │ │ │ └── core │ │ │ │ ├── Endpoint.java │ │ │ │ ├── HelloService.java │ │ │ │ ├── IHelloService.java │ │ │ │ ├── IpHelper.java │ │ │ │ ├── IrisConfig.java │ │ │ │ ├── KeyValue.java │ │ │ │ ├── annotation │ │ │ │ ├── Reference.java │ │ │ │ └── Service.java │ │ │ │ └── loadbalance │ │ │ │ ├── ILoadBalance.java │ │ │ │ ├── RandomLoadBalance.java │ │ │ │ └── SelectFirstLoadBalance.java │ │ └── resources │ │ │ └── META-INF │ │ │ └── extensions │ │ │ └── com.leibangzhu.iris.core.loadbalance.ILoadBalance │ │ └── test │ │ └── java │ │ └── com │ │ └── leiwei2094 │ │ └── iris │ │ └── core │ │ └── Test1.java ├── iris-parent │ └── pom.xml ├── iris-protocol │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── leiwei2094 │ │ └── iris │ │ └── protocol │ │ ├── RpcDecoder.java │ │ ├── RpcEncoder.java │ │ ├── RpcRequest.java │ │ ├── RpcResponse.java │ │ └── SerializationUtil.java ├── iris-registry │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── leiwei2094 │ │ │ └── iris │ │ │ └── registry │ │ │ ├── EtcdRegistry.java │ │ │ ├── IEventCallback.java │ │ │ ├── IRegistry.java │ │ │ └── RegistryEvent.java │ │ └── test │ │ └── java │ │ └── com │ │ └── leiwei2094 │ │ └── iris │ │ └── registry │ │ └── etcd │ │ ├── EtcdRegistryTest.java │ │ ├── GetTest.java │ │ ├── IpHelperTest.java │ │ ├── LeaseTest.java │ │ ├── PutTest.java │ │ └── WatchTest.java ├── iris-server │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── leiwei2094 │ │ │ └── iris │ │ │ └── server │ │ │ ├── RpcServer.java │ │ │ ├── RpcServerHandler.java │ │ │ └── RpcServerInitializer.java │ │ └── test │ │ └── java │ │ └── com │ │ └── leiwei2094 │ │ └── iris │ │ └── server │ │ └── ServerTest.java ├── iris-spring-boot │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── leiwei2094 │ │ │ │ └── iris │ │ │ │ └── springboot │ │ │ │ ├── ServiceAnnotationBeanFactoryPostProcessor.java │ │ │ │ ├── ServiceAnnotationScanner.java │ │ │ │ ├── config │ │ │ │ └── IrisAutoConfiguration.java │ │ │ │ └── properties │ │ │ │ ├── RegistryProperties.java │ │ │ │ └── ServerProperties.java │ │ └── resources │ │ │ ├── META-INF │ │ │ └── spring.factories │ │ │ └── application.properties.sample │ │ └── test │ │ ├── java │ │ └── com │ │ │ └── leiwei2094 │ │ │ └── iris │ │ │ └── springboot │ │ │ ├── ClientApplication.java │ │ │ ├── ClientTest.java │ │ │ ├── Foo.java │ │ │ ├── HelloService.java │ │ │ └── ServerApplication.java │ │ └── resources │ │ ├── application-client.properties │ │ ├── application-server.properties │ │ └── iris.properties ├── iris-spring │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── leiwei2094 │ │ │ └── iris │ │ │ └── spring │ │ │ ├── IrisApplicationListener.java │ │ │ ├── ReferenceAnnotationBeanPostProcessor.java │ │ │ └── ServiceAnnotationBeanPostProcessor.java │ │ └── test │ │ ├── java │ │ └── com │ │ │ └── leiwei2094 │ │ │ └── iris │ │ │ └── spring │ │ │ ├── Baz.java │ │ │ ├── HelloService.java │ │ │ ├── XmlClient.java │ │ │ └── XmlServer.java │ │ └── resources │ │ ├── beans-client.xml │ │ └── beans-server.xml └── pom.xml └── samples ├── .gitignore ├── demo-a ├── build.gradle ├── demo-a-api │ ├── build.gradle │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── leibangzhu │ │ └── iris │ │ └── demoa │ │ └── api │ │ └── IHelloService.java ├── demo-a-service │ ├── build.gradle │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── leibangzhu │ │ │ └── iris │ │ │ └── demoa │ │ │ └── service │ │ │ ├── App.java │ │ │ ├── AppConfiguration.java │ │ │ ├── HelloService.java │ │ │ ├── aspect │ │ │ └── LogAspect.java │ │ │ └── service │ │ │ └── HelloService.java │ │ └── resources │ │ ├── application.properties │ │ └── dubbo-provider.xml └── settings.gradle └── demo-b ├── build.gradle ├── settings.gradle └── src └── main ├── java └── com │ └── qibeitech │ └── demob │ ├── App.java │ ├── AppConfiguration.java │ ├── Bar.java │ ├── Foo.java │ ├── ITestService.java │ ├── TestConfiguration.java │ └── TestService.java └── resources ├── application.properties ├── dubbo-consumer.xml └── dubbo-provider.xml /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .gradle 3 | *.iml 4 | 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Lei Wei 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # iris 2 | 3 | 一个基于Java的RPC框架。目前可以看成是mini版的Dubbo。有注册中心,提供服务的注册,发现和负载均衡。 4 | 5 | * 网络通信: Netty4 6 | * 注册中心: etcd,可扩展 7 | * 动态代理: byte-buddy 8 | * 序列化: Protobuff(Protostuff) 9 | * 可以脱离Spring,提供API调用。 10 | * 集成Spring,提供XML,Java配置 11 | * 提供Spring Boot Starter 12 | * 提供SPI机制,实现微内核加插件的架构。实现可扩展,开发者可以为iris开发组件,以插件的形式集成到iris中。插件的加载使用另一个微容器框架见[coco](https://github.com/vangoleo/coco)项目。该项目fork于阿里的[cooma](https://github.com/alibaba/cooma)。 13 | 14 | # Todo: 15 | * 支持优雅停机,不依赖Spring和Web容器。 16 | * 支持服务延迟暴露 17 | * 支持超时和重试配置 18 | * 添加监控系统,使用Prometheus 19 | * 更好的支持容器环境 20 | 21 | # How to use 22 | iris支持以下使用方式: 23 | 1. 原生API形式,不依赖Spring,非Spring项目也可以使用 24 | 2. Spring配置方式,和Spring很好的集成 25 | 3. Spring Boot配置方式,提供了一个spring boot starter,以自动配置,快速启动 26 | 27 | # API使用 28 | Iris核心代码不依赖Spring,可脱离Spring使用。 29 | 1. 启动etcd注册中心 30 | 2. 编写一个接口IHelloService 31 | ```java 32 | public interface IHelloService { 33 | String hello(String name); 34 | } 35 | ``` 36 | 3. 编写一个IHelloService的实现 37 | ```java 38 | public class HelloService implements IHelloService { 39 | @Override 40 | public String hello(String name){ 41 | return "Hello, " + name; 42 | } 43 | } 44 | ``` 45 | 4. 启动Server 46 | ```java 47 | IRegistry registry = new EtcdRegistry("http://127.0.0.1:2379"); 48 | RpcServer server = new RpcServer(registry) 49 | .port(2017) 50 | .exposeService(IHelloService.class,new HelloService()); 51 | server.run(); 52 | ``` 53 | 5. 启动client 54 | ```java 55 | RpcClient client = new RpcClient(registry); 56 | IHelloService helloService = client.create(IHelloService.class); 57 | String s = helloService.hello("leo"); 58 | System.out.println(s); // hello, leo 59 | ``` 60 | 6. 停止server 61 | ```text 62 | 因为服务没有provider,client报错找不到provider 63 | ``` 64 | 7. 启动server         65 | ```text 66 | server启动后,会去etcd注册中心注册服务,client端马上正常工作。 67 | ``` 68 | 69 | # Spring配置 70 | 服务提供者,使用自定义注解@Service来暴露服务,通过interfaceClass来指定服务的接口。         71 | 该@Service注解是iris提供的,并非Spring的注解 72 | ```java 73 | @Service(interfaceClass = IHelloService.class) 74 | public class HelloService implements IHelloService { 75 | @Override 76 | public String hello(String name) throws Exception { 77 | return "hello" + name; 78 | } 79 | } 80 | ``` 81 | 服务使用者,通过@Reference来引用远程服务,就像使用本地的SpringBean一样。背后的SpringBean封装和Rpc调用对开发者透明。使用体验和Dubbo是一样的。 82 | ```java 83 | public class Baz { 84 | 85 | @Reference(interfaceClass = IHelloService.class) 86 | private IHelloService helloService; 87 | 88 | public void hello(String name) throws Exception { 89 | System.out.println(helloService.hello(name)); 90 | } 91 | } 92 | 93 | ``` 94 | 配置服务提供者,本例子使用XML配置,使用Java Code配置也可以。 95 | ```xml 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | ``` 108 | 配置服务消费者,本例子使用XML配置,使用Java Code配置也可以。 109 | ```xml 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | ``` 122 | 123 | # Spring Boot配置 124 | 使用原生的Spring配置还是有些繁琐,可以使用Spring Boot来获得更好的开发体验。 125 | 服务提供者 126 | ```java 127 | @Service(interfaceClass = IHelloService.class) 128 | public class HelloService implements IHelloService { 129 | @Override 130 | public String hello(String name) throws Exception { 131 | return "Hello, " + name + ", from com.leibangzhu.iris.springboot.HelloService"; 132 | } 133 | } 134 | ``` 135 | 服务消费者 136 | ```java 137 | @Component 138 | public class Foo { 139 | 140 | @Reference(interfaceClass = IHelloService.class) 141 | private IHelloService helloService; 142 | 143 | public String hello(String name) throws Exception { 144 | return helloService.hello(name); 145 | } 146 | } 147 | ``` 148 | 在application.properties文件中配置服务提供者 149 | ```properties 150 | iris.registry.address=http://127.0.0.1:2379 151 | 152 | iris.server.enable=true 153 | iris.server.port=2017 154 | iris.annotation.package=com.leibangzhu.iris.springboot 155 | ``` 156 | 在application.properties文件中配置服务消费者 157 | ```properties 158 | iris.registry.address=http://127.0.0.1:2379 159 | 160 | iris.client.enable=true 161 | ``` 162 | 使用SpringBoot时,不许再手动配置相关的spring bean,Iris提供的spring boot starter会自动配置好这些spring bean。 163 | 164 | # Iris的微内核加插件机制 165 | * Iris使用了SPI机制,实现了微内核加插件的架构。 166 | * Iris里的许多功能都是以插件的形式加载的。一个功能点就是一个扩展点,就是一个接口。通过注入的方式,将某个实现注入到Iris中。         167 | * 扩展点的加载没有使用第三方的容器,比如Spring,而是自己实现了一个轻量级的容器。对Java的SPI机制进行了一下扩展和加强。 168 | * 每个扩展点会有多个实现,开发者可以自己配置使用哪个,比如使用zookeeper注册中心或etcd注册中心。 169 | * Iris内置的扩展实现满足大部分要求,开发者也可以自己编写扩展点的实现,加载到Iris中。 170 | * Iris会扫描classpath下面的`/META/extensions`文件夹中的文件,读取扩展点信息,然后运行时动态加载。 171 | * 使用时通过ExtensionLoader加载对应的插件 172 | * ExtensionLoader支持类似于Spring的IoC和AoP功能。即,扩展点中可以自动装配其他的扩展点。Iris提供Wrapper使用Decrator模式来实现AOP。 173 | * 所有的扩展点元数据文件都在`/META-INF/extensions`文件夹下,文件名是实现的扩展点的接口的全类名。 174 | * 文件的内容是key=value的形式。key是扩展点实现的name,value是实现类的全类名。实现类是一个简单的Java类,不依赖任何第三方接口和注解。 175 | * 使用Wrapper实现AOP时,在扩展点name前加上`+`。比如:`+logWrapper=com.leibangzhu.iris.core.SomeExtension` 176 | 177 | ### 一个负载均衡器的Demo 178 | Iris中的服务提供者有多个,client端调用的时候,有一个负载均衡的策略。 179 | Iris目前提供了1个实现:随机选择一个提供者。以后会提供更多的负载均衡策略。如果有多个,只需要在iris.properties或application.properties中添加配置: 180 | ```properties 181 | iris.loadbalance=random 182 | ``` 183 | Iris提供的的`ILoadBalance`接口。 184 | ```java 185 | @Extension(defaultValue = "random") 186 | public interface ILoadBalance { 187 | int select(@Adaptive("loadbalance")Map config,int amount) throws Exception; 188 | } 189 | ``` 190 | * @Extension注解声明这是一个扩展点 191 | * defaultValue表示默认使用random这个扩展点实现 192 | * @Adaptive注解声明这是一个自适应扩展方法,会根据运行时信息动态选择对应的扩展点实现。类似于一个动态代理。 193 | 自带的随机的负载均衡是在下面的文件中定义的: 194 | `/src/main/resources/META-INF/extensions/com.leibangzhu.iris.core.loadbalance.ILoadBalance`文件的内容: 195 | ```text 196 | random=com.leibangzhu.iris.core.loadbalance.RandomLoadBalance 197 | ``` 198 | 通过ExtensionLoader获取扩展点: 199 | ```java 200 | ILoadBalance loadBalance = ExtensionLoader.getExtensionLoader(ILoadBalance.class).getAdaptiveInstance(); 201 | // get runtime configuration and load config to map 202 | // get actual loadbalance from iris.properties or application.properties file 203 | String loadbalance = IrisConfig.getLoadbalance(); 204 | map.put("loadbalance",loadbalance) 205 | loadBalance.select(map,size); 206 | ``` 207 | 208 | ### 扩展自己的负载均衡器 209 | 开发者想使用轮询的负载均衡策略,可以按照以下步骤来扩展: 210 | 1. 编写一个类,实现ILoadBalance接口 211 | ```java 212 | public class RoundRobinLoadBalance implements ILoadBalance { 213 | @Override 214 | public int select(Map config, int amount) throws Exception { 215 | // put your code here ... 216 | } 217 | } 218 | ``` 219 | 2. 在classpath中添加一个文件: 220 | `/META-INF/extensions/com.leibangzhu.iris.core.loadbalande.ILoadBalance` 221 | ```properties 222 | roundrobin=com.mycompany.foo.bar.RoundRobinLoadBalance 223 | ``` 224 | 3. 在`iris.properties`或`application.properties`中添加配置: 225 | ```properties 226 | iris.loadbalance=roundrobin 227 | ``` 228 | 这样,Iris就会使用我们自定义的轮询负载均衡了。 229 | 230 | # Why iris 231 | `iris`取名于梵高的画**鸢尾花** 232 | -------------------------------------------------------------------------------- /iris/.gitignore: -------------------------------------------------------------------------------- 1 | iris-client/target 2 | iris-core/target 3 | iris-spring/target 4 | iris-spring-boot/target 5 | iris-protocol/target 6 | iris-registry/target 7 | iris-server/target 8 | .flattened-pom.xml 9 | -------------------------------------------------------------------------------- /iris/README.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /iris/iris-bom/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | iris 7 | com.leiwei2094 8 | ${revision} 9 | 10 | 4.0.0 11 | 12 | iris-bom 13 | pom 14 | 15 | 16 | 0.0.1 17 | 4.12 18 | 4.1.12.Final 19 | 1.7.9 20 | 1.5.2 21 | 2.6 22 | 0.0.1-SNAPSHOT 23 | 4.3.13.RELEASE 24 | 1.5.9.RELEASE 25 | 26 | 27 | 28 | 29 | 30 | com.coreos 31 | jetcd-core 32 | ${etcd.version} 33 | 34 | 35 | io.netty 36 | netty-codec-http2 37 | 38 | 39 | io.netty 40 | netty-handler-proxy 41 | 42 | 43 | 44 | 45 | junit 46 | junit 47 | ${junit.version} 48 | test 49 | 50 | 51 | io.netty 52 | netty-all 53 | ${netty.version} 54 | 55 | 56 | net.bytebuddy 57 | byte-buddy 58 | ${byte-buddy.version} 59 | 60 | 61 | io.protostuff 62 | protostuff-core 63 | ${protostuff.version} 64 | 65 | 66 | io.protostuff 67 | protostuff-runtime 68 | ${protostuff.version} 69 | 70 | 71 | org.objenesis 72 | objenesis 73 | ${objenesis.version} 74 | 75 | 76 | com.leiwei2094 77 | coco 78 | ${com.leiwei2094.coco.version} 79 | 80 | 81 | org.springframework 82 | spring-context 83 | ${spring.version} 84 | 85 | 86 | org.springframework.boot 87 | spring-boot-starter 88 | ${springboot.version} 89 | 90 | 91 | org.slf4j 92 | slf4j-api 93 | 94 | 95 | 96 | 97 | org.springframework.boot 98 | spring-boot-configuration-processor 99 | ${springboot.version} 100 | true 101 | 102 | 103 | org.springframework.boot 104 | spring-boot-starter-test 105 | ${springboot.version} 106 | 107 | 108 | org.slf4j 109 | slf4j-api 110 | 111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /iris/iris-client/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | iris-parent 7 | com.leiwei2094 8 | ${revision} 9 | ../iris-parent/pom.xml 10 | 11 | 4.0.0 12 | 13 | iris-client 14 | 15 | 16 | 17 | com.leiwei2094 18 | iris-registry 19 | ${project.version} 20 | 21 | 22 | com.leiwei2094 23 | iris-protocol 24 | ${project.version} 25 | 26 | 27 | net.bytebuddy 28 | byte-buddy 29 | 30 | 31 | junit 32 | junit 33 | 34 | 35 | junit 36 | junit 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /iris/iris-client/src/main/java/com/leiwei2094/iris/client/ConnectManager.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.client; 2 | 3 | import com.leiwei2094.coco.ExtensionLoader; 4 | import com.leiwei2094.iris.core.Endpoint; 5 | import com.leiwei2094.iris.core.IrisConfig; 6 | import com.leiwei2094.iris.core.loadbalance.ILoadBalance; 7 | import com.leiwei2094.iris.registry.IEventCallback; 8 | import com.leiwei2094.iris.registry.IRegistry; 9 | import com.leiwei2094.iris.registry.RegistryEvent; 10 | import io.netty.bootstrap.Bootstrap; 11 | import io.netty.channel.Channel; 12 | import io.netty.channel.EventLoopGroup; 13 | import io.netty.channel.nio.NioEventLoopGroup; 14 | import io.netty.channel.socket.nio.NioSocketChannel; 15 | 16 | import java.util.*; 17 | 18 | public class ConnectManager implements IConnectManager, IEventCallback { 19 | 20 | private IRegistry registry; 21 | private EventLoopGroup eventLoopGroup = new NioEventLoopGroup(4); 22 | private Map> channelsByService = new LinkedHashMap<>(); 23 | 24 | public ConnectManager(IRegistry registry) { 25 | this.registry = registry; 26 | this.registry.watch(this); 27 | } 28 | 29 | @Override 30 | public Channel getChannel(String serviceName) throws Exception { 31 | if (!channelsByService.containsKey(serviceName)) { 32 | List endpoints = registry.find(serviceName); 33 | List channels = new ArrayList<>(); 34 | for (Endpoint endpoint : endpoints) { 35 | channels.add(connect(endpoint.getHost(), endpoint.getPort())); 36 | } 37 | channelsByService.put(serviceName, channels); 38 | } 39 | 40 | // select one channel from all available channels 41 | int size = channelsByService.get(serviceName).size(); 42 | ILoadBalance loadBalance = ExtensionLoader.getExtensionLoader(ILoadBalance.class).getAdaptiveInstance(); 43 | if (0 == size) { 44 | System.out.println("NO available providers for service: " + serviceName); 45 | } 46 | 47 | String loadbalance = IrisConfig.get("iris.loadbalance"); 48 | Map map = new LinkedHashMap<>(); 49 | map.put("loadbalance", loadbalance); 50 | int index = loadBalance.select(map, size); 51 | ChannelWrapper channelWrapper = channelsByService.get(serviceName).get(index); 52 | System.out.println("Load balance:" + loadbalance + "; Selected endpoint: " + channelWrapper.toString()); 53 | return channelWrapper.getChannel(); 54 | } 55 | 56 | private ChannelWrapper connect(String host, int port) throws Exception { 57 | 58 | Bootstrap b = new Bootstrap() 59 | .group(eventLoopGroup) 60 | .channel(NioSocketChannel.class) 61 | .handler(new RpcClientInitializer()); 62 | 63 | Channel channel = b.connect(host, port).sync().channel(); 64 | ChannelWrapper channelWrapper = new ChannelWrapper(new Endpoint(host, port), channel); 65 | return channelWrapper; 66 | } 67 | 68 | @Override 69 | public void execute(RegistryEvent event) { 70 | if (event.getEventType() == RegistryEvent.EventType.DELETE) { 71 | 72 | // key: /iris/com.leiwei2094.iris.bytebuddy.IHelloService/192.168.41.215:2017 73 | 74 | String s = event.getKeyValue().getKey(); 75 | String serviceName = s.split("/")[2]; // com.leiwei2094.iris.bytebuddy.IHelloService 76 | String endpointStr = s.split("/")[3]; 77 | 78 | String host = endpointStr.split(":")[0]; // 192.168.41.215 79 | int port = Integer.valueOf(endpointStr.split(":")[1]); // 2017 80 | 81 | Iterator iterator = channelsByService.get(serviceName).iterator(); 82 | while (iterator.hasNext()) { 83 | Endpoint endpoint = iterator.next().getEndpoint(); 84 | if (endpoint.getHost().equals(host) && (endpoint.getPort() == port)) { 85 | iterator.remove(); 86 | } 87 | } 88 | } 89 | 90 | if (event.getEventType() == RegistryEvent.EventType.PUT) { 91 | 92 | // key: /iris/com.leiwei2094.iris.bytebuddy.IHelloService/192.168.41.215:2017 93 | 94 | String s = event.getKeyValue().getKey(); 95 | String serviceName = s.split("/")[2]; // com.leiwei2094.iris.bytebuddy.IHelloService 96 | String endpointStr = s.split("/")[3]; 97 | 98 | String host = endpointStr.split(":")[0]; // 192.168.41.215 99 | int port = Integer.valueOf(endpointStr.split(":")[1]); // 2017 100 | 101 | try { 102 | channelsByService.get(serviceName).add(connect(host, port)); 103 | } catch (Exception e) { 104 | e.printStackTrace(); 105 | } 106 | } 107 | } 108 | 109 | private static class ChannelWrapper { 110 | private Endpoint endpoint; 111 | private Channel channel; 112 | 113 | public ChannelWrapper(Endpoint endpoint, Channel channel) { 114 | this.endpoint = endpoint; 115 | this.channel = channel; 116 | } 117 | 118 | public Endpoint getEndpoint() { 119 | return endpoint; 120 | } 121 | 122 | public Channel getChannel() { 123 | return channel; 124 | } 125 | 126 | @Override 127 | public String toString() { 128 | return endpoint.getHost() + ":" + endpoint.getPort(); 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /iris/iris-client/src/main/java/com/leiwei2094/iris/client/IConnectManager.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.client; 2 | 3 | import io.netty.channel.Channel; 4 | 5 | public interface IConnectManager { 6 | Channel getChannel(String serviceName) throws Exception; 7 | } 8 | -------------------------------------------------------------------------------- /iris/iris-client/src/main/java/com/leiwei2094/iris/client/IRpcClient.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.client; 2 | 3 | public interface IRpcClient { 4 | 5 | T create(Class clazz) throws Exception; 6 | } 7 | -------------------------------------------------------------------------------- /iris/iris-client/src/main/java/com/leiwei2094/iris/client/RpcClient.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.client; 2 | 3 | import com.leiwei2094.iris.registry.IRegistry; 4 | import net.bytebuddy.ByteBuddy; 5 | import net.bytebuddy.implementation.MethodDelegation; 6 | 7 | import java.util.LinkedHashMap; 8 | import java.util.Map; 9 | 10 | import static net.bytebuddy.matcher.ElementMatchers.isDeclaredBy; 11 | 12 | public class RpcClient implements IRpcClient { 13 | 14 | ConnectManager connectManager; 15 | private IRegistry registry; 16 | private Map proxyByClass = new LinkedHashMap<>(); 17 | 18 | public RpcClient(IRegistry registry) { 19 | this.registry = registry; 20 | this.connectManager = new ConnectManager(registry); 21 | //this.registry.watch(); 22 | } 23 | 24 | @Override 25 | public T create(Class clazz) throws Exception { 26 | if (!proxyByClass.containsKey(clazz.getName())) { 27 | T proxy = new ByteBuddy() 28 | .subclass(clazz) 29 | .method(isDeclaredBy(clazz)).intercept(MethodDelegation.to(new RpcInvokeInterceptor(connectManager))) 30 | .make() 31 | .load(getClass().getClassLoader()) 32 | .getLoaded() 33 | .newInstance(); 34 | 35 | proxyByClass.put(clazz.getName(), proxy); 36 | } 37 | 38 | return (T)proxyByClass.get(clazz.getName()); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /iris/iris-client/src/main/java/com/leiwei2094/iris/client/RpcClientHandler.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.client; 2 | 3 | import com.leiwei2094.iris.protocol.RpcResponse; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import io.netty.channel.SimpleChannelInboundHandler; 6 | 7 | public class RpcClientHandler extends SimpleChannelInboundHandler { 8 | 9 | @Override 10 | protected void channelRead0(ChannelHandlerContext channelHandlerContext, RpcResponse response) throws Exception { 11 | String requestId = response.getRequestId(); 12 | RpcFuture future = RpcRequestHolder.get(requestId); 13 | if (null != future) { 14 | RpcRequestHolder.remove(requestId); 15 | future.done(response); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /iris/iris-client/src/main/java/com/leiwei2094/iris/client/RpcClientInitializer.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.client; 2 | 3 | import com.leiwei2094.iris.protocol.RpcDecoder; 4 | import com.leiwei2094.iris.protocol.RpcEncoder; 5 | import com.leiwei2094.iris.protocol.RpcRequest; 6 | import com.leiwei2094.iris.protocol.RpcResponse; 7 | import io.netty.channel.ChannelInitializer; 8 | import io.netty.channel.ChannelPipeline; 9 | import io.netty.channel.socket.SocketChannel; 10 | import io.netty.handler.codec.LengthFieldBasedFrameDecoder; 11 | 12 | public class RpcClientInitializer extends ChannelInitializer { 13 | @Override 14 | protected void initChannel(SocketChannel socketChannel) throws Exception { 15 | ChannelPipeline pipeline = socketChannel.pipeline(); 16 | pipeline.addLast(new RpcEncoder(RpcRequest.class)); 17 | pipeline.addLast(new LengthFieldBasedFrameDecoder(65536, 0, 4, 0, 0)); 18 | pipeline.addLast(new RpcDecoder(RpcResponse.class)); 19 | pipeline.addLast(new RpcClientHandler()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /iris/iris-client/src/main/java/com/leiwei2094/iris/client/RpcFuture.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.client; 2 | 3 | import com.leiwei2094.iris.protocol.RpcResponse; 4 | 5 | import java.util.concurrent.*; 6 | 7 | public class RpcFuture implements Future { 8 | private CountDownLatch latch = new CountDownLatch(1); 9 | 10 | private RpcResponse response; 11 | 12 | @Override 13 | public boolean cancel(boolean mayInterruptIfRunning) { 14 | return false; 15 | } 16 | 17 | @Override 18 | public boolean isCancelled() { 19 | return false; 20 | } 21 | 22 | @Override 23 | public boolean isDone() { 24 | return false; 25 | } 26 | 27 | @Override 28 | public Object get() throws InterruptedException, ExecutionException { 29 | boolean b = latch.await(5, TimeUnit.SECONDS); 30 | return response.getResult(); 31 | } 32 | 33 | @Override 34 | public Object get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { 35 | boolean b = latch.await(timeout, unit); 36 | return response.getResult(); 37 | } 38 | 39 | public void done(RpcResponse response) { 40 | this.response = response; 41 | latch.countDown(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /iris/iris-client/src/main/java/com/leiwei2094/iris/client/RpcInvokeInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.client; 2 | 3 | import com.leiwei2094.iris.protocol.RpcRequest; 4 | import io.netty.channel.Channel; 5 | import net.bytebuddy.implementation.bind.annotation.AllArguments; 6 | import net.bytebuddy.implementation.bind.annotation.Origin; 7 | import net.bytebuddy.implementation.bind.annotation.RuntimeType; 8 | 9 | import java.lang.reflect.Method; 10 | import java.util.UUID; 11 | 12 | public class RpcInvokeInterceptor { 13 | 14 | private IConnectManager connectManager; 15 | 16 | public RpcInvokeInterceptor(IConnectManager connectManager) { 17 | this.connectManager = connectManager; 18 | } 19 | 20 | @RuntimeType 21 | public Object intercept(@AllArguments Object[] args, @Origin Method method) throws Exception { 22 | String name = method.getDeclaringClass().getName(); 23 | System.out.println(name); 24 | // create rpc request 25 | RpcRequest request = new RpcRequest(); 26 | request.setRequestId(UUID.randomUUID().toString()); 27 | request.setClassName(method.getDeclaringClass().getName()); 28 | request.setMethodName(method.getName()); 29 | request.setParameterTypes(method.getParameterTypes()); 30 | request.setParameters(args); 31 | // get a connect from connect manager 32 | Channel channel = connectManager.getChannel(method.getDeclaringClass().getName()); 33 | // send the rpc request via the connect 34 | 35 | RpcFuture future = new RpcFuture(); 36 | RpcRequestHolder.put(request.getRequestId(), future); 37 | 38 | channel.writeAndFlush(request); 39 | 40 | Object result = null; 41 | try { 42 | result = future.get(); 43 | } catch (Exception e) { 44 | e.printStackTrace(); 45 | } 46 | return result; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /iris/iris-client/src/main/java/com/leiwei2094/iris/client/RpcRequestHolder.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.client; 2 | 3 | import java.util.concurrent.ConcurrentHashMap; 4 | 5 | public class RpcRequestHolder { 6 | 7 | // key: requestId value: RpcFuture 8 | private static ConcurrentHashMap processingRpc = new ConcurrentHashMap<>(); 9 | 10 | public static void put(String requestId, RpcFuture rpcFuture) { 11 | processingRpc.put(requestId, rpcFuture); 12 | } 13 | 14 | public static RpcFuture get(String requestId) { 15 | return processingRpc.get(requestId); 16 | } 17 | 18 | public static void remove(String requestId) { 19 | processingRpc.remove(requestId); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /iris/iris-client/src/test/java/com/leiwei2094/iris/client/ClientTest.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.client; 2 | 3 | import com.leiwei2094.iris.core.IHelloService; 4 | import com.leiwei2094.iris.registry.EtcdRegistry; 5 | import com.leiwei2094.iris.registry.IRegistry; 6 | import org.junit.Ignore; 7 | import org.junit.Test; 8 | 9 | import java.util.concurrent.Executors; 10 | import java.util.concurrent.TimeUnit; 11 | 12 | @Ignore 13 | public class ClientTest { 14 | 15 | @Test 16 | public void test() throws Exception { 17 | IRegistry registry = new EtcdRegistry("http://127.0.0.1:2379"); 18 | RpcClient client = new RpcClient(registry); 19 | 20 | Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> { 21 | try { 22 | IHelloService helloService = client.create(IHelloService.class); 23 | String s = helloService.hello("leo"); 24 | System.out.println("====" + s); 25 | 26 | String s2 = helloService.hello("tom"); 27 | System.out.println("====" + s2); 28 | 29 | String s3 = helloService.hello("jerry"); 30 | System.out.println("====" + s3); 31 | 32 | System.out.println("==== rpc invoke finished..."); 33 | Thread.sleep(2 * 1000); 34 | } catch (Exception e) { 35 | e.printStackTrace(); 36 | } 37 | }, 5, 3, TimeUnit.SECONDS); 38 | 39 | Thread.sleep(3000 * 1000); 40 | } 41 | 42 | @Test 43 | public void test2() throws Exception { 44 | IRegistry registry = new EtcdRegistry("http://127.0.0.1:2379"); 45 | RpcClient client = new RpcClient(registry); 46 | 47 | com.leiwei2094.iris.core.IHelloService helloService = 48 | client.create(com.leiwei2094.iris.core.IHelloService.class); 49 | String s = helloService.hello("Hello"); 50 | System.out.println(s); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /iris/iris-client/src/test/java/com/leiwei2094/iris/client/bytebuddy/ByteBuddyTest.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.client.bytebuddy; 2 | 3 | import com.leiwei2094.iris.core.IHelloService; 4 | import net.bytebuddy.ByteBuddy; 5 | import net.bytebuddy.implementation.MethodDelegation; 6 | import org.junit.Test; 7 | 8 | import static net.bytebuddy.matcher.ElementMatchers.isDeclaredBy; 9 | 10 | public class ByteBuddyTest { 11 | 12 | @Test 13 | public void test() throws Exception { 14 | IHelloService helloService = new ByteBuddy() 15 | .subclass(IHelloService.class) 16 | .method(isDeclaredBy(IHelloService.class)).intercept(MethodDelegation.to(new GeneralInterceptor())) 17 | .make() 18 | .load(getClass().getClassLoader()) 19 | .getLoaded() 20 | .newInstance(); 21 | helloService.hello("world"); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /iris/iris-client/src/test/java/com/leiwei2094/iris/client/bytebuddy/GeneralInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.client.bytebuddy; 2 | 3 | import net.bytebuddy.implementation.bind.annotation.AllArguments; 4 | import net.bytebuddy.implementation.bind.annotation.Origin; 5 | import net.bytebuddy.implementation.bind.annotation.RuntimeType; 6 | 7 | import java.lang.reflect.Method; 8 | 9 | public class GeneralInterceptor { 10 | 11 | @RuntimeType 12 | public String intercept(@AllArguments Object[] allArguments, @Origin Method method) { 13 | String name = method.getDeclaringClass().getName(); 14 | System.out.println(name + "." + method.getName()); 15 | return ""; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /iris/iris-client/src/test/resources/iris.properties: -------------------------------------------------------------------------------- 1 | #iris.loadbalance=random 2 | iris.loadbalance=roundrobin -------------------------------------------------------------------------------- /iris/iris-core/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | iris-parent 7 | com.leiwei2094 8 | ${revision} 9 | ../iris-parent/pom.xml 10 | 11 | 4.0.0 12 | 13 | iris-core 14 | 15 | 16 | 17 | com.leiwei2094 18 | coco 19 | 20 | 21 | junit 22 | junit 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /iris/iris-core/src/main/java/com/leiwei2094/iris/core/Endpoint.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.core; 2 | 3 | /** 4 | * @author wei.lei 5 | * 代表一个RPC示例,包含主机和端口 6 | */ 7 | public class Endpoint { 8 | private final String host; 9 | private final int port; 10 | 11 | public Endpoint(String host, int port) { 12 | this.host = host; 13 | this.port = port; 14 | } 15 | 16 | public String getHost() { 17 | return host; 18 | } 19 | 20 | public int getPort() { 21 | return port; 22 | } 23 | 24 | @Override 25 | public String toString() { 26 | return host + ":" + port; 27 | } 28 | 29 | @Override 30 | public boolean equals(Object o) { 31 | if (!(o instanceof Endpoint)) { 32 | return false; 33 | } 34 | Endpoint other = (Endpoint)o; 35 | return other.host.equals(this.host) && other.port == this.port; 36 | } 37 | 38 | @Override 39 | public int hashCode() { 40 | return host.hashCode() + port; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /iris/iris-core/src/main/java/com/leiwei2094/iris/core/HelloService.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.core; 2 | 3 | /** 4 | * @author wei.lei 5 | */ 6 | public class HelloService implements IHelloService { 7 | @Override 8 | public String hello(String name) throws Exception { 9 | Thread.sleep(2 * 1000); 10 | return "Hello, " + name; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /iris/iris-core/src/main/java/com/leiwei2094/iris/core/IHelloService.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.core; 2 | 3 | /** 4 | * @author wei.lei 5 | */ 6 | public interface IHelloService { 7 | String hello(String name) throws Exception; 8 | } 9 | -------------------------------------------------------------------------------- /iris/iris-core/src/main/java/com/leiwei2094/iris/core/IpHelper.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.core; 2 | 3 | import java.net.InetAddress; 4 | 5 | /** 6 | * @author wei.lei 7 | */ 8 | public class IpHelper { 9 | 10 | public static String getHostIp() throws Exception { 11 | 12 | String ip = InetAddress.getLocalHost().getHostAddress(); 13 | return ip; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /iris/iris-core/src/main/java/com/leiwei2094/iris/core/IrisConfig.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.core; 2 | 3 | import java.io.InputStream; 4 | import java.util.LinkedHashMap; 5 | import java.util.Map; 6 | import java.util.Properties; 7 | 8 | /** 9 | * @author wei.lei 10 | */ 11 | public class IrisConfig { 12 | 13 | private static Map configs = new LinkedHashMap<>(); 14 | private static boolean initialized = false; 15 | 16 | private static void load() throws Exception { 17 | // load from classpath:/iris.properties 18 | Properties properties = new Properties(); 19 | InputStream in = IrisConfig.class.getClassLoader().getResourceAsStream("iris.properties"); 20 | properties.load(in); 21 | for (Map.Entry entry : properties.entrySet()) { 22 | configs.put((String)entry.getKey(), (String)entry.getValue()); 23 | } 24 | 25 | // load from application.properties 26 | // ... 27 | } 28 | 29 | public static String get(String key) { 30 | if (!initialized) { 31 | try { 32 | load(); 33 | initialized = true; 34 | } catch (Exception e) { 35 | e.printStackTrace(); 36 | } 37 | } 38 | return configs.get(key); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /iris/iris-core/src/main/java/com/leiwei2094/iris/core/KeyValue.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.core; 2 | 3 | /** 4 | * @author wei.lei 5 | */ 6 | public class KeyValue { 7 | private K key; 8 | private V value; 9 | 10 | public KeyValue() {} 11 | 12 | public KeyValue(K key, V value) { 13 | this.key = key; 14 | this.value = value; 15 | } 16 | 17 | public K getKey() { 18 | return this.key; 19 | } 20 | 21 | public void setKey(K key) { 22 | this.key = key; 23 | } 24 | 25 | public V getValue() { 26 | return this.value; 27 | } 28 | 29 | public void setValue(V value) { 30 | this.value = value; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /iris/iris-core/src/main/java/com/leiwei2094/iris/core/annotation/Reference.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.core.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * @author wei.lei 7 | */ 8 | @Target({ElementType.FIELD}) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Documented 11 | public @interface Reference { 12 | Class interfaceClass(); 13 | } 14 | -------------------------------------------------------------------------------- /iris/iris-core/src/main/java/com/leiwei2094/iris/core/annotation/Service.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.core.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * @author wei.lei 7 | */ 8 | @Documented 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Target({ElementType.TYPE}) 11 | @Inherited 12 | public @interface Service { 13 | Class interfaceClass() default void.class; 14 | } 15 | -------------------------------------------------------------------------------- /iris/iris-core/src/main/java/com/leiwei2094/iris/core/loadbalance/ILoadBalance.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.core.loadbalance; 2 | 3 | import com.leiwei2094.coco.Adaptive; 4 | import com.leiwei2094.coco.Extension; 5 | 6 | import java.util.Map; 7 | 8 | @Extension(defaultValue = "random") 9 | public interface ILoadBalance { 10 | int select(@Adaptive("loadbalance") Map config, int amount) throws Exception; 11 | } 12 | -------------------------------------------------------------------------------- /iris/iris-core/src/main/java/com/leiwei2094/iris/core/loadbalance/RandomLoadBalance.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.core.loadbalance; 2 | 3 | import java.util.Map; 4 | import java.util.Random; 5 | 6 | public class RandomLoadBalance implements ILoadBalance { 7 | 8 | private Random random = new Random(); 9 | 10 | @Override 11 | public int select(Map config, int amount) throws Exception { 12 | // System.out.println("RandomLoadBalance to select ..."); 13 | if (amount <= 0) { 14 | throw new Exception("RandomLoadBalance: no available items to select"); 15 | } else if (amount == 1) { 16 | return 0; 17 | } else { 18 | return random.nextInt(amount); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /iris/iris-core/src/main/java/com/leiwei2094/iris/core/loadbalance/SelectFirstLoadBalance.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.core.loadbalance; 2 | 3 | import java.util.Map; 4 | 5 | public class SelectFirstLoadBalance implements ILoadBalance { 6 | @Override 7 | public int select(Map config, int amount) throws Exception { 8 | System.out.println("SelectFirstLoadBalance to select ..."); 9 | return 0; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /iris/iris-core/src/main/resources/META-INF/extensions/com.leibangzhu.iris.core.loadbalance.ILoadBalance: -------------------------------------------------------------------------------- 1 | random=com.leiwei2094.iris.core.loadbalance.RandomLoadBalance 2 | first=com.leiwei2094.iris.core.loadbalance.SelectFirstLoadBalance -------------------------------------------------------------------------------- /iris/iris-core/src/test/java/com/leiwei2094/iris/core/Test1.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.core; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Random; 6 | 7 | public class Test1 { 8 | 9 | @Test 10 | public void test_random() { 11 | Random random = new Random(); 12 | for (int i = 0; i < 50; i++) { 13 | System.out.println(random.nextInt(10)); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /iris/iris-parent/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | iris 7 | com.leiwei2094 8 | ${revision} 9 | 10 | 4.0.0 11 | 12 | iris-parent 13 | pom 14 | 15 | 16 | 1.0-SNAPSHOT 17 | UTF-8 18 | 1.8 19 | ${java.version} 20 | ${java.version} 21 | 22 | 23 | 24 | 25 | 26 | com.leiwei2094 27 | iris-bom 28 | ${project.version} 29 | pom 30 | import 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /iris/iris-protocol/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | iris-parent 7 | com.leiwei2094 8 | ${revision} 9 | ../iris-parent/pom.xml 10 | 11 | 4.0.0 12 | 13 | iris-protocol 14 | 15 | 16 | 17 | io.netty 18 | netty-all 19 | 20 | 21 | io.protostuff 22 | protostuff-core 23 | 24 | 25 | io.protostuff 26 | protostuff-runtime 27 | 28 | 29 | org.objenesis 30 | objenesis 31 | 32 | 33 | -------------------------------------------------------------------------------- /iris/iris-protocol/src/main/java/com/leiwei2094/iris/protocol/RpcDecoder.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.protocol; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import io.netty.handler.codec.ByteToMessageDecoder; 6 | 7 | import java.util.List; 8 | 9 | public class RpcDecoder extends ByteToMessageDecoder { 10 | private Class clazz; 11 | 12 | public RpcDecoder(Class clazz) { 13 | this.clazz = clazz; 14 | } 15 | 16 | @Override 17 | protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) 18 | throws Exception { 19 | if (byteBuf.readableBytes() < 4) { 20 | return; 21 | } 22 | byteBuf.markReaderIndex(); 23 | int dataLength = byteBuf.readInt(); 24 | /*if (dataLength <= 0) { 25 | ctx.close(); 26 | }*/ 27 | if (byteBuf.readableBytes() < dataLength) { 28 | byteBuf.resetReaderIndex(); 29 | return; 30 | } 31 | byte[] data = new byte[dataLength]; 32 | byteBuf.readBytes(data); 33 | 34 | Object obj = SerializationUtil.deserialize(data, clazz); 35 | //Object obj = JsonUtil.deserialize(data,genericClass); // Not use this, have some bugs 36 | list.add(obj); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /iris/iris-protocol/src/main/java/com/leiwei2094/iris/protocol/RpcEncoder.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.protocol; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import io.netty.handler.codec.MessageToByteEncoder; 6 | 7 | public class RpcEncoder extends MessageToByteEncoder { 8 | private Class clazz; 9 | 10 | public RpcEncoder(Class clazz) { 11 | this.clazz = clazz; 12 | } 13 | 14 | @Override 15 | protected void encode(ChannelHandlerContext channelHandlerContext, Object o, ByteBuf byteBuf) throws Exception { 16 | if (clazz.isInstance(o)) { 17 | byte[] data = SerializationUtil.serialize(o); 18 | byteBuf.writeInt(data.length); 19 | byteBuf.writeBytes(data); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /iris/iris-protocol/src/main/java/com/leiwei2094/iris/protocol/RpcRequest.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.protocol; 2 | 3 | public class RpcRequest { 4 | 5 | private String requestId; 6 | private String className; 7 | private String methodName; 8 | private Class[] parameterTypes; 9 | private Object[] parameters; 10 | 11 | public String getRequestId() { 12 | return requestId; 13 | } 14 | 15 | public void setRequestId(String requestId) { 16 | this.requestId = requestId; 17 | } 18 | 19 | public String getClassName() { 20 | return className; 21 | } 22 | 23 | public void setClassName(String className) { 24 | this.className = className; 25 | } 26 | 27 | public String getMethodName() { 28 | return methodName; 29 | } 30 | 31 | public void setMethodName(String methodName) { 32 | this.methodName = methodName; 33 | } 34 | 35 | public Class[] getParameterTypes() { 36 | return parameterTypes; 37 | } 38 | 39 | public void setParameterTypes(Class[] parameterTypes) { 40 | this.parameterTypes = parameterTypes; 41 | } 42 | 43 | public Object[] getParameters() { 44 | return parameters; 45 | } 46 | 47 | public void setParameters(Object[] parameters) { 48 | this.parameters = parameters; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /iris/iris-protocol/src/main/java/com/leiwei2094/iris/protocol/RpcResponse.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.protocol; 2 | 3 | public class RpcResponse { 4 | 5 | private String requestId; 6 | private String error; 7 | private Object result; 8 | 9 | public String getRequestId() { 10 | return requestId; 11 | } 12 | 13 | public void setRequestId(String requestId) { 14 | this.requestId = requestId; 15 | } 16 | 17 | public String getError() { 18 | return error; 19 | } 20 | 21 | public void setError(String error) { 22 | this.error = error; 23 | } 24 | 25 | public Object getResult() { 26 | return result; 27 | } 28 | 29 | public void setResult(Object result) { 30 | this.result = result; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /iris/iris-protocol/src/main/java/com/leiwei2094/iris/protocol/SerializationUtil.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.protocol; 2 | 3 | import io.protostuff.LinkedBuffer; 4 | import io.protostuff.ProtostuffIOUtil; 5 | import io.protostuff.Schema; 6 | import io.protostuff.runtime.RuntimeSchema; 7 | import org.objenesis.Objenesis; 8 | import org.objenesis.ObjenesisStd; 9 | 10 | import java.util.Map; 11 | import java.util.concurrent.ConcurrentHashMap; 12 | 13 | public class SerializationUtil { 14 | 15 | private static Map, Schema> cacheSchemas = new ConcurrentHashMap<>(); 16 | private static Objenesis objenesis = new ObjenesisStd(true); 17 | 18 | private static Schema getSchema(Class clazz) { 19 | Schema schema = (Schema)cacheSchemas.get(clazz); 20 | if (null == schema) { 21 | schema = RuntimeSchema.createFrom(clazz); 22 | cacheSchemas.put(clazz, schema); 23 | } 24 | return schema; 25 | } 26 | 27 | /** 28 | * 序列化 ( Java对象 -> 字节数组) 29 | */ 30 | public static byte[] serialize(T obj) { 31 | Class cls = (Class)obj.getClass(); 32 | LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE); 33 | try { 34 | Schema schema = getSchema(cls); 35 | return ProtostuffIOUtil.toByteArray(obj, schema, buffer); 36 | } catch (Exception e) { 37 | throw new IllegalStateException(e.getMessage(), e); 38 | } finally { 39 | buffer.clear(); 40 | } 41 | } 42 | 43 | /** 44 | * 反序列化 (字节数组 -> Java对象) 45 | */ 46 | public static T deserialize(byte[] data, Class cls) { 47 | try { 48 | T message = (T)objenesis.newInstance(cls); 49 | Schema schema = getSchema(cls); 50 | ProtostuffIOUtil.mergeFrom(data, message, schema); 51 | return message; 52 | } catch (Exception e) { 53 | throw new IllegalStateException(e.getMessage(), e); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /iris/iris-registry/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | iris-parent 7 | com.leiwei2094 8 | ${revision} 9 | ../iris-parent/pom.xml 10 | 11 | 4.0.0 12 | 13 | iris-registry 14 | 15 | 16 | 17 | com.coreos 18 | jetcd-core 19 | 20 | 21 | com.leiwei2094 22 | iris-core 23 | ${project.version} 24 | 25 | 26 | junit 27 | junit 28 | 29 | 30 | io.netty 31 | netty-all 32 | 33 | 34 | -------------------------------------------------------------------------------- /iris/iris-registry/src/main/java/com/leiwei2094/iris/registry/EtcdRegistry.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.registry; 2 | 3 | import com.coreos.jetcd.Client; 4 | import com.coreos.jetcd.KV; 5 | import com.coreos.jetcd.Lease; 6 | import com.coreos.jetcd.Watch; 7 | import com.coreos.jetcd.data.ByteSequence; 8 | import com.coreos.jetcd.data.KeyValue; 9 | import com.coreos.jetcd.kv.GetResponse; 10 | import com.coreos.jetcd.options.GetOption; 11 | import com.coreos.jetcd.options.PutOption; 12 | import com.coreos.jetcd.options.WatchOption; 13 | import com.coreos.jetcd.watch.WatchEvent; 14 | import com.leiwei2094.iris.core.Endpoint; 15 | import com.leiwei2094.iris.core.IpHelper; 16 | 17 | import java.text.MessageFormat; 18 | import java.util.ArrayList; 19 | import java.util.LinkedHashMap; 20 | import java.util.List; 21 | import java.util.Map; 22 | import java.util.concurrent.Executors; 23 | 24 | public class EtcdRegistry implements IRegistry { 25 | 26 | private final String rootPath = "iris"; 27 | private String registryAddress = "http://127.0.0.1:2379"; 28 | private Lease lease; 29 | private KV kv; 30 | private Watch watch; 31 | private long leaseId; 32 | 33 | private Map> endpointsByService = new LinkedHashMap<>(); 34 | private IEventCallback callback; 35 | 36 | public EtcdRegistry(String registryAddress) throws Exception { 37 | this.registryAddress = registryAddress; 38 | Client client = Client.builder().endpoints(registryAddress).build(); 39 | this.lease = client.getLeaseClient(); 40 | this.kv = client.getKVClient(); 41 | this.watch = client.getWatchClient(); 42 | this.leaseId = lease.grant(30).get().getID(); 43 | //System.out.println("New lease, id:" + leaseId + ", Hex format: " + Long.toHexString(leaseId)); 44 | // keepAlive(); 45 | //watch(); 46 | } 47 | 48 | // 向ETCD中注册服务 49 | public void register(String serviceName, int port) throws Exception { 50 | // 服务注册的key为: /iris/com.some.package.IHelloService/192.168.100.100:2000 51 | String strKey = 52 | MessageFormat.format("/{0}/{1}/{2}:{3}", rootPath, serviceName, IpHelper.getHostIp(), String.valueOf(port)); 53 | ByteSequence key = ByteSequence.fromString(strKey); 54 | ByteSequence val = ByteSequence.fromString(""); // 目前只需要创建这个key,对应的value暂不使用,先留空 55 | kv.put(key, val, PutOption.newBuilder().withLeaseId(leaseId).build()).get(); 56 | System.out.println("Register a new service at:" + strKey); 57 | } 58 | 59 | // 发送心跳到ETCD,表明该host是活着的 60 | public void keepAlive() { 61 | Executors.newSingleThreadExecutor().submit( 62 | () -> { 63 | try { 64 | Lease.KeepAliveListener listener = lease.keepAlive(leaseId); 65 | listener.listen(); 66 | System.out.println("KeepAlive lease:" + leaseId + "; Hex format:" + Long.toHexString(leaseId)); 67 | } catch (Exception e) { 68 | e.printStackTrace(); 69 | } 70 | } 71 | ); 72 | } 73 | 74 | // 取消注册服务 75 | public void unRegistered(String serviceName) { 76 | 77 | } 78 | 79 | public List find(String serviceName) throws Exception { 80 | 81 | if (endpointsByService.containsKey(serviceName)) { 82 | return endpointsByService.get(serviceName); 83 | } 84 | 85 | String strKey = 86 | MessageFormat.format("/{0}/{1}", rootPath, serviceName); // /iris/com.leiwei2094.IHelloService 87 | ByteSequence key = ByteSequence.fromString(strKey); 88 | GetResponse response = kv.get(key, GetOption.newBuilder().withPrefix(key).build()).get(); 89 | 90 | List endpoints = new ArrayList<>(); 91 | 92 | for (KeyValue kv : response.getKvs()) { 93 | String s = kv.getKey().toStringUtf8(); 94 | int index = s.lastIndexOf("/"); 95 | String endpointStr = s.substring(index + 1, s.length()); 96 | 97 | String host = endpointStr.split(":")[0]; 98 | int port = Integer.valueOf(endpointStr.split(":")[1]); 99 | 100 | //System.out.println(host); 101 | //System.out.println(port); 102 | 103 | endpoints.add(new Endpoint(host, port)); 104 | } 105 | endpointsByService.put(serviceName, endpoints); 106 | return endpoints; 107 | } 108 | 109 | @Override 110 | public void watch(IEventCallback callback) { 111 | this.callback = callback; 112 | watch(); 113 | } 114 | 115 | private void watch() { 116 | Watch.Watcher watcher = watch.watch(ByteSequence.fromString("/" + rootPath), 117 | WatchOption.newBuilder().withPrefix(ByteSequence.fromString("/" + rootPath)).build()); 118 | 119 | Executors.newSingleThreadExecutor().submit((Runnable)() -> { 120 | while (true) { 121 | try { 122 | for (WatchEvent event : watcher.listen().getEvents()) { 123 | System.out.println(event.getEventType()); 124 | System.out.println(event.getKeyValue().getKey().toStringUtf8()); 125 | System.out.println(event.getKeyValue().getValue().toStringUtf8()); 126 | 127 | // /iris/com.leiwei2094.IHelloService/192.168.41.215:2000 128 | 129 | String s = event.getKeyValue().getKey().toStringUtf8(); 130 | String serviceName = s.split("/")[2]; 131 | String endpoint = s.split("/")[3]; 132 | 133 | String host = endpoint.split(":")[0]; 134 | int port = Integer.valueOf(endpoint.split(":")[1]); 135 | 136 | endpointsByService.get(serviceName).remove(new Endpoint(host, port)); 137 | 138 | if (null != callback) { 139 | RegistryEvent registryEvent = RegistryEvent 140 | .newBuilder() 141 | .eventType(RegistryEvent.EventType.valueOf(event.getEventType().toString())) 142 | .key(event.getKeyValue().getKey().toStringUtf8()) 143 | .value(event.getKeyValue().getValue().toStringUtf8()) 144 | .build(); 145 | 146 | callback.execute(registryEvent); 147 | } 148 | } 149 | } catch (InterruptedException e) { 150 | e.printStackTrace(); 151 | } 152 | } 153 | }); 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /iris/iris-registry/src/main/java/com/leiwei2094/iris/registry/IEventCallback.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.registry; 2 | 3 | public interface IEventCallback { 4 | void execute(RegistryEvent event); 5 | } 6 | -------------------------------------------------------------------------------- /iris/iris-registry/src/main/java/com/leiwei2094/iris/registry/IRegistry.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.registry; 2 | 3 | import com.leiwei2094.iris.core.Endpoint; 4 | 5 | import java.util.List; 6 | 7 | public interface IRegistry { 8 | 9 | // 注册服务 10 | void register(String serviceName, int port) throws Exception; 11 | 12 | // 取消注册服务 13 | void unRegistered(String serviceName); 14 | 15 | List find(String serviceName) throws Exception; 16 | 17 | void watch(IEventCallback callback); 18 | 19 | void keepAlive(); 20 | 21 | //void watch(); 22 | } 23 | -------------------------------------------------------------------------------- /iris/iris-registry/src/main/java/com/leiwei2094/iris/registry/RegistryEvent.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.registry; 2 | 3 | import com.leiwei2094.iris.core.KeyValue; 4 | 5 | public class RegistryEvent { 6 | 7 | private KeyValue preKeyValue = new KeyValue<>(); 8 | private KeyValue keyValue = new KeyValue<>(); 9 | private EventType eventType = EventType.UNRECOGNIZED; 10 | 11 | public static RegistryEventBuilder newBuilder() { 12 | return new RegistryEventBuilder(); 13 | } 14 | 15 | public KeyValue getPreKeyValue() { 16 | return preKeyValue; 17 | } 18 | 19 | public KeyValue getKeyValue() { 20 | return keyValue; 21 | } 22 | 23 | public EventType getEventType() { 24 | return eventType; 25 | } 26 | 27 | public static enum EventType { 28 | PUT, 29 | DELETE, 30 | UNRECOGNIZED; 31 | 32 | private EventType() { 33 | } 34 | } 35 | 36 | public static class RegistryEventBuilder { 37 | 38 | private RegistryEvent registryEvent = new RegistryEvent(); 39 | 40 | public RegistryEventBuilder preKey(String key) { 41 | registryEvent.preKeyValue.setKey(key); 42 | return this; 43 | } 44 | 45 | public RegistryEventBuilder preValue(String value) { 46 | registryEvent.preKeyValue.setValue(value); 47 | return this; 48 | } 49 | 50 | public RegistryEventBuilder key(String key) { 51 | registryEvent.keyValue.setKey(key); 52 | return this; 53 | } 54 | 55 | public RegistryEventBuilder value(String value) { 56 | registryEvent.keyValue.setValue(value); 57 | return this; 58 | } 59 | 60 | public RegistryEvent build() { 61 | return registryEvent; 62 | } 63 | 64 | public RegistryEventBuilder eventType(EventType eventType) { 65 | registryEvent.eventType = eventType; 66 | return this; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /iris/iris-registry/src/test/java/com/leiwei2094/iris/registry/etcd/EtcdRegistryTest.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.registry.etcd; 2 | 3 | import com.leiwei2094.iris.core.Endpoint; 4 | import com.leiwei2094.iris.registry.EtcdRegistry; 5 | import org.junit.Ignore; 6 | import org.junit.Test; 7 | 8 | import java.util.List; 9 | 10 | @Ignore 11 | public class EtcdRegistryTest { 12 | 13 | @Test 14 | public void test() throws Exception { 15 | EtcdRegistry registry = new EtcdRegistry("http://127.0.0.1:2379"); 16 | registry.register("com.leiwei2094.IHelloService", 2000); 17 | registry.register("com.leiwei2094.IHelloService", 2100); 18 | registry.register("com.leiwei2094.IHelloService", 2200); 19 | Thread.sleep(3 * 1000); 20 | //List endpoints = registry.find("com.leiwei2094.IHelloService"); 21 | Thread.sleep(100 * 1000); 22 | } 23 | 24 | @Test 25 | public void test002() throws Exception { 26 | 27 | EtcdRegistry registry = new EtcdRegistry("http://127.0.0.1:2379"); 28 | for (int i = 0; i < 50; i++) { 29 | List endpoints = registry.find("com.leiwei2094.IHelloService"); 30 | System.out.println(endpoints); 31 | Thread.sleep(2 * 1000); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /iris/iris-registry/src/test/java/com/leiwei2094/iris/registry/etcd/GetTest.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.registry.etcd; 2 | 3 | import com.coreos.jetcd.Client; 4 | import com.coreos.jetcd.KV; 5 | import com.coreos.jetcd.data.ByteSequence; 6 | import com.coreos.jetcd.data.KeyValue; 7 | import com.coreos.jetcd.kv.GetResponse; 8 | import com.coreos.jetcd.options.GetOption; 9 | import org.junit.Ignore; 10 | import org.junit.Test; 11 | 12 | @Ignore 13 | public class GetTest { 14 | 15 | @Test 16 | public void testGetWithPrefix() throws Exception { 17 | Client client = Client.builder().endpoints("http://localhost:2379").build(); 18 | KV kvClient = client.getKVClient(); 19 | 20 | String prefix = "test_key"; 21 | ByteSequence key = ByteSequence.fromString(prefix); 22 | 23 | for (int i = 0; i < 5; i++) { 24 | ByteSequence testKey = ByteSequence.fromString("test_key_" + i); 25 | ByteSequence testVal = ByteSequence.fromString("test_val_" + i); 26 | 27 | kvClient.put(testKey, testVal).get(); 28 | } 29 | 30 | ByteSequence dsfs = ByteSequence.fromString("dsfs"); 31 | GetResponse response = kvClient.get(dsfs, GetOption.newBuilder().withPrefix(key).build()).get(); 32 | 33 | for (KeyValue kv : response.getKvs()) { 34 | System.out.println(kv.getKey().toStringUtf8() + " : " + kv.getValue().toStringUtf8()); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /iris/iris-registry/src/test/java/com/leiwei2094/iris/registry/etcd/IpHelperTest.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.registry.etcd; 2 | 3 | import com.leiwei2094.iris.core.IpHelper; 4 | import org.junit.Ignore; 5 | import org.junit.Test; 6 | 7 | import java.text.MessageFormat; 8 | 9 | @Ignore 10 | public class IpHelperTest { 11 | 12 | @Test 13 | public void test() throws Exception { 14 | String ip = IpHelper.getHostIp(); 15 | System.out.println(ip); 16 | 17 | System.out.println(MessageFormat.format("a{0}b{1}c{2}", "foo", "bar", 100)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /iris/iris-registry/src/test/java/com/leiwei2094/iris/registry/etcd/LeaseTest.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.registry.etcd; 2 | 3 | import com.coreos.jetcd.Client; 4 | import com.coreos.jetcd.KV; 5 | import com.coreos.jetcd.Lease; 6 | import com.coreos.jetcd.data.ByteSequence; 7 | import com.coreos.jetcd.lease.LeaseGrantResponse; 8 | import com.coreos.jetcd.options.LeaseOption; 9 | import com.coreos.jetcd.options.PutOption; 10 | import org.junit.Ignore; 11 | import org.junit.Test; 12 | 13 | import java.util.concurrent.CompletableFuture; 14 | 15 | @Ignore 16 | public class LeaseTest { 17 | @Test 18 | public void test() throws Exception { 19 | Client client = Client.builder().endpoints("http://127.0.0.1:2379").build(); 20 | Lease lease = client.getLeaseClient(); 21 | 22 | CompletableFuture future = lease.grant(20); 23 | LeaseGrantResponse response = future.get(); 24 | long leaseId = response.getID(); 25 | System.out.println("New lease, id:" + leaseId + ", Hex format: " + Long.toHexString(leaseId)); 26 | 27 | ByteSequence key = ByteSequence.fromString("abc"); 28 | ByteSequence value = ByteSequence.fromString("220"); 29 | 30 | KV kv = client.getKVClient(); 31 | kv.put(key, value, PutOption.newBuilder().withLeaseId(leaseId).build()); 32 | } 33 | 34 | @Test 35 | public void test002() throws Exception { 36 | Client client = Client.builder().endpoints("http://127.0.0.1:2379").build(); 37 | Lease lease = client.getLeaseClient(); 38 | 39 | CompletableFuture future = lease.grant(20); 40 | LeaseGrantResponse response = future.get(); 41 | long leaseId = response.getID(); 42 | System.out.println("New lease, id:" + leaseId + ", Hex format: " + Long.toHexString(leaseId)); 43 | 44 | KV kvClient = client.getKVClient(); 45 | 46 | for (int i = 0; i < 5; i++) { 47 | ByteSequence testKey = ByteSequence.fromString("abc_key_" + i); 48 | ByteSequence testVal = ByteSequence.fromString("abc_val_" + i); 49 | 50 | kvClient.put(testKey, testVal, PutOption.newBuilder().withLeaseId(leaseId).build()).get(); 51 | Thread.sleep(3000); 52 | } 53 | } 54 | 55 | @Test 56 | public void test003() throws Exception { 57 | Client client = Client.builder().endpoints("http://127.0.0.1:2379").build(); 58 | Lease lease = client.getLeaseClient(); 59 | 60 | long leaseId = lease.grant(20).get().getID(); 61 | System.out.println("New lease, id:" + leaseId + ", Hex format: " + Long.toHexString(leaseId)); 62 | 63 | for (int i = 0; i < 10; i++) { 64 | System.out.println( 65 | "Time to alive before keep-alive: " + lease.timeToLive(leaseId, LeaseOption.DEFAULT).get().getTTl()); 66 | lease.keepAlive(leaseId).listen(); 67 | System.out.println( 68 | "Time to alive after keep-alive: " + lease.timeToLive(leaseId, LeaseOption.DEFAULT).get().getTTl()); 69 | Thread.sleep(3000); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /iris/iris-registry/src/test/java/com/leiwei2094/iris/registry/etcd/PutTest.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.registry.etcd; 2 | 3 | import com.coreos.jetcd.Client; 4 | import com.coreos.jetcd.KV; 5 | import com.coreos.jetcd.data.ByteSequence; 6 | import com.coreos.jetcd.kv.GetResponse; 7 | import org.junit.Ignore; 8 | import org.junit.Test; 9 | 10 | import java.util.concurrent.CompletableFuture; 11 | 12 | @Ignore 13 | public class PutTest { 14 | 15 | @Test 16 | public void test() throws Exception { 17 | 18 | Client client = Client.builder().endpoints("http://localhost:2379").build(); 19 | KV kvClient = client.getKVClient(); 20 | 21 | ByteSequence key = ByteSequence.fromString("abc"); 22 | ByteSequence value = ByteSequence.fromString("240"); 23 | 24 | // put the key-value 25 | kvClient.put(key, value).get(); 26 | // get the CompletableFuture 27 | CompletableFuture getFuture = kvClient.get(key); 28 | // get the value from CompletableFuture 29 | GetResponse response = getFuture.get(); 30 | // delete the key 31 | //DeleteResponse deleteRangeResponse = kvClient.delete(key).get(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /iris/iris-registry/src/test/java/com/leiwei2094/iris/registry/etcd/WatchTest.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.registry.etcd; 2 | 3 | import com.coreos.jetcd.Client; 4 | import com.coreos.jetcd.Watch; 5 | import com.coreos.jetcd.data.ByteSequence; 6 | import com.coreos.jetcd.options.WatchOption; 7 | import com.coreos.jetcd.watch.WatchEvent; 8 | import org.junit.Ignore; 9 | import org.junit.Test; 10 | 11 | @Ignore 12 | public class WatchTest { 13 | 14 | @Test 15 | public void testWatchPrefix() throws Exception { 16 | 17 | Client client = Client.builder().endpoints("http://127.0.0.1:2379").build(); 18 | Watch.Watcher watcher = client.getWatchClient().watch(ByteSequence.fromString("abc"), 19 | WatchOption.newBuilder().withPrefix(ByteSequence.fromString("abc")).build()); 20 | 21 | while (true) { 22 | for (WatchEvent event : watcher.listen().getEvents()) { 23 | System.out.println(event.getEventType()); 24 | System.out.println(event.getKeyValue().getKey().toStringUtf8()); 25 | System.out.println(event.getKeyValue().getValue().toStringUtf8()); 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /iris/iris-server/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | iris-parent 7 | com.leiwei2094 8 | ${revision} 9 | ../iris-parent/pom.xml 10 | 11 | 4.0.0 12 | 13 | iris-server 14 | 15 | 16 | 17 | com.leiwei2094 18 | iris-protocol 19 | ${project.version} 20 | 21 | 22 | io.netty 23 | netty-all 24 | 25 | 26 | com.leiwei2094 27 | iris-registry 28 | ${project.version} 29 | 30 | 31 | junit 32 | junit 33 | 34 | 35 | com.leiwei2094 36 | iris-core 37 | ${project.version} 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /iris/iris-server/src/main/java/com/leiwei2094/iris/server/RpcServer.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.server; 2 | 3 | import com.leiwei2094.iris.registry.IRegistry; 4 | import io.netty.bootstrap.ServerBootstrap; 5 | import io.netty.channel.ChannelFuture; 6 | import io.netty.channel.ChannelOption; 7 | import io.netty.channel.EventLoopGroup; 8 | import io.netty.channel.nio.NioEventLoopGroup; 9 | import io.netty.channel.socket.nio.NioServerSocketChannel; 10 | 11 | import java.util.LinkedHashMap; 12 | import java.util.Map; 13 | import java.util.concurrent.Executors; 14 | 15 | public class RpcServer { 16 | 17 | private String host = "127.0.0.1"; 18 | private IRegistry registry; 19 | private int port = 2017; 20 | 21 | private Map handlerMap = new LinkedHashMap<>(); 22 | 23 | public RpcServer(IRegistry registry) { 24 | this.registry = registry; 25 | } 26 | 27 | public RpcServer exposeService(Class clazz, Object handler) throws Exception { 28 | handlerMap.put(clazz.getName(), handler); 29 | // registry.register(clazz.getName(),port); 30 | registry.keepAlive(); 31 | 32 | return this; 33 | } 34 | 35 | public RpcServer port(int port) { 36 | this.port = port; 37 | return this; 38 | } 39 | 40 | public void run() throws Exception { 41 | 42 | Executors.newSingleThreadExecutor().submit(() -> { 43 | EventLoopGroup bossGroup = new NioEventLoopGroup(); 44 | EventLoopGroup workerGroup = new NioEventLoopGroup(); 45 | 46 | ServerBootstrap bootstrap = new ServerBootstrap() 47 | .group(bossGroup, workerGroup) 48 | .channel(NioServerSocketChannel.class) 49 | .childHandler(new RpcServerInitializer(handlerMap)) 50 | .option(ChannelOption.SO_BACKLOG, 128) 51 | .childOption(ChannelOption.SO_KEEPALIVE, true); 52 | ChannelFuture future = null; 53 | try { 54 | future = bootstrap.bind(port).sync(); 55 | } catch (InterruptedException e) { 56 | e.printStackTrace(); 57 | } 58 | 59 | for (String className : handlerMap.keySet()) { 60 | try { 61 | registry.register(className, port); 62 | } catch (Exception e) { 63 | e.printStackTrace(); 64 | } 65 | } 66 | 67 | try { 68 | future.channel().closeFuture().sync(); 69 | } catch (InterruptedException e) { 70 | e.printStackTrace(); 71 | } 72 | }); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /iris/iris-server/src/main/java/com/leiwei2094/iris/server/RpcServerHandler.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.server; 2 | 3 | import com.leiwei2094.iris.protocol.RpcRequest; 4 | import com.leiwei2094.iris.protocol.RpcResponse; 5 | import io.netty.channel.ChannelHandlerContext; 6 | import io.netty.channel.SimpleChannelInboundHandler; 7 | 8 | import java.lang.reflect.Method; 9 | import java.util.Map; 10 | 11 | public class RpcServerHandler extends SimpleChannelInboundHandler { 12 | 13 | // key: com.some.package.IHelloService value: new HelloService(); 14 | private final Map handlerMap; 15 | 16 | public RpcServerHandler(Map handlerMap) { 17 | this.handlerMap = handlerMap; 18 | } 19 | 20 | @Override 21 | protected void channelRead0(ChannelHandlerContext channelHandlerContext, RpcRequest rpcRequest) throws Exception { 22 | RpcResponse response = new RpcResponse(); 23 | response.setRequestId(rpcRequest.getRequestId()); 24 | 25 | // invoke method by reflection 26 | String className = rpcRequest.getClassName(); 27 | Object handlerObj = handlerMap.get(className); 28 | 29 | Class handlerClass = handlerObj.getClass(); 30 | String methodName = rpcRequest.getMethodName(); 31 | Class[] parameterTypes = rpcRequest.getParameterTypes(); 32 | Object[] parameters = rpcRequest.getParameters(); 33 | 34 | // JDK reflect 35 | Method method = handlerClass.getMethod(methodName, parameterTypes); 36 | method.setAccessible(true); 37 | Object result = method.invoke(handlerObj, parameters); 38 | response.setResult(result); 39 | channelHandlerContext.writeAndFlush(response); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /iris/iris-server/src/main/java/com/leiwei2094/iris/server/RpcServerInitializer.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.server; 2 | 3 | import com.leiwei2094.iris.protocol.RpcDecoder; 4 | import com.leiwei2094.iris.protocol.RpcEncoder; 5 | import com.leiwei2094.iris.protocol.RpcRequest; 6 | import com.leiwei2094.iris.protocol.RpcResponse; 7 | import io.netty.channel.ChannelInitializer; 8 | import io.netty.channel.ChannelPipeline; 9 | import io.netty.channel.socket.SocketChannel; 10 | import io.netty.handler.codec.LengthFieldBasedFrameDecoder; 11 | 12 | import java.util.Map; 13 | 14 | public class RpcServerInitializer extends ChannelInitializer { 15 | 16 | private final Map handlerMap; 17 | 18 | public RpcServerInitializer(Map handlerMap) { 19 | this.handlerMap = handlerMap; 20 | } 21 | 22 | @Override 23 | protected void initChannel(SocketChannel socketChannel) throws Exception { 24 | ChannelPipeline pipeline = socketChannel.pipeline(); 25 | pipeline.addLast(new LengthFieldBasedFrameDecoder(65536, 0, 4, 0, 0)); 26 | pipeline.addLast(new RpcDecoder(RpcRequest.class)); 27 | pipeline.addLast(new RpcEncoder(RpcResponse.class)); 28 | pipeline.addLast(new RpcServerHandler(handlerMap)); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /iris/iris-server/src/test/java/com/leiwei2094/iris/server/ServerTest.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.server; 2 | 3 | import com.leiwei2094.iris.core.HelloService; 4 | import com.leiwei2094.iris.core.IHelloService; 5 | import com.leiwei2094.iris.registry.EtcdRegistry; 6 | import com.leiwei2094.iris.registry.IRegistry; 7 | import org.junit.Ignore; 8 | import org.junit.Test; 9 | 10 | @Ignore 11 | public class ServerTest { 12 | 13 | @Test 14 | public void test() throws Exception { 15 | IRegistry registry = new EtcdRegistry("http://127.0.0.1:2379"); 16 | RpcServer server = new RpcServer(registry) 17 | .port(2017) 18 | .exposeService(IHelloService.class, new HelloService()); 19 | server.run(); 20 | Thread.sleep(100 * 1000); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /iris/iris-spring-boot/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | iris-parent 7 | com.leiwei2094 8 | ${revision} 9 | ../iris-parent/pom.xml 10 | 11 | 4.0.0 12 | 13 | iris-spring-boot 14 | 15 | 16 | 17 | org.springframework.boot 18 | spring-boot-starter 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-configuration-processor 23 | true 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter-test 28 | 29 | 30 | com.leiwei2094 31 | iris-spring 32 | ${project.version} 33 | 34 | 35 | com.leiwei2094 36 | iris-client 37 | ${project.version} 38 | 39 | 40 | com.leiwei2094 41 | iris-server 42 | ${project.version} 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /iris/iris-spring-boot/src/main/java/com/leiwei2094/iris/springboot/ServiceAnnotationBeanFactoryPostProcessor.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.springboot; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.beans.factory.config.BeanFactoryPostProcessor; 5 | import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; 6 | import org.springframework.beans.factory.support.BeanDefinitionRegistry; 7 | import org.springframework.context.ApplicationContext; 8 | import org.springframework.context.ApplicationContextAware; 9 | 10 | public class ServiceAnnotationBeanFactoryPostProcessor implements BeanFactoryPostProcessor, ApplicationContextAware { 11 | 12 | private ApplicationContext applicationContext; 13 | private String scanBasePackage; 14 | 15 | public ServiceAnnotationBeanFactoryPostProcessor(String scanBasePackage) { 16 | this.scanBasePackage = scanBasePackage; 17 | } 18 | 19 | @Override 20 | public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { 21 | ServiceAnnotationScanner scanner = new ServiceAnnotationScanner((BeanDefinitionRegistry)beanFactory); 22 | scanner.setResourceLoader(this.applicationContext); 23 | scanner.scan(scanBasePackage); 24 | } 25 | 26 | @Override 27 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 28 | this.applicationContext = applicationContext; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /iris/iris-spring-boot/src/main/java/com/leiwei2094/iris/springboot/ServiceAnnotationScanner.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.springboot; 2 | 3 | import com.leiwei2094.iris.core.annotation.Service; 4 | import org.springframework.beans.factory.config.BeanDefinitionHolder; 5 | import org.springframework.beans.factory.support.BeanDefinitionRegistry; 6 | import org.springframework.context.annotation.ClassPathBeanDefinitionScanner; 7 | import org.springframework.core.type.filter.AnnotationTypeFilter; 8 | 9 | import java.util.Set; 10 | 11 | public class ServiceAnnotationScanner extends ClassPathBeanDefinitionScanner { 12 | public ServiceAnnotationScanner(BeanDefinitionRegistry registry) { 13 | super(registry); 14 | } 15 | 16 | public void registerDefaultFilters() { 17 | this.addIncludeFilter(new AnnotationTypeFilter(Service.class)); 18 | } 19 | 20 | public Set doScan(String... basePackages) { 21 | Set beanDefinitions = super.doScan(basePackages); 22 | // for (BeanDefinitionHolder holder : beanDefinitions) { 23 | // GenericBeanDefinition definition = (GenericBeanDefinition) holder.getBeanDefinition(); 24 | // definition.getPropertyValues().add("innerClassName", definition.getBeanClassName()); 25 | // definition.setBeanClass(FactoryBeanTest.class); 26 | // } 27 | return beanDefinitions; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /iris/iris-spring-boot/src/main/java/com/leiwei2094/iris/springboot/config/IrisAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.springboot.config; 2 | 3 | import com.leiwei2094.iris.client.RpcClient; 4 | import com.leiwei2094.iris.registry.EtcdRegistry; 5 | import com.leiwei2094.iris.registry.IRegistry; 6 | import com.leiwei2094.iris.server.RpcServer; 7 | import com.leiwei2094.iris.spring.IrisApplicationListener; 8 | import com.leiwei2094.iris.spring.ReferenceAnnotationBeanPostProcessor; 9 | import com.leiwei2094.iris.spring.ServiceAnnotationBeanPostProcessor; 10 | import com.leiwei2094.iris.springboot.ServiceAnnotationBeanFactoryPostProcessor; 11 | import com.leiwei2094.iris.springboot.properties.RegistryProperties; 12 | import com.leiwei2094.iris.springboot.properties.ServerProperties; 13 | import org.springframework.beans.factory.annotation.Value; 14 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 15 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 16 | import org.springframework.context.annotation.Bean; 17 | import org.springframework.context.annotation.Configuration; 18 | 19 | @Configuration 20 | @EnableConfigurationProperties({RegistryProperties.class, ServerProperties.class}) 21 | public class IrisAutoConfiguration { 22 | 23 | @ConditionalOnProperty(prefix = "iris.server", value = "enable", havingValue = "true") 24 | @Bean 25 | public static ServiceAnnotationBeanFactoryPostProcessor beanFactoryPostProcessor( 26 | @Value("${iris.annotation.package}") String packageName) { 27 | ServiceAnnotationBeanFactoryPostProcessor processor = 28 | new ServiceAnnotationBeanFactoryPostProcessor(packageName); 29 | return processor; 30 | } 31 | 32 | @Bean 33 | public IRegistry registry(RegistryProperties properties) throws Exception { 34 | EtcdRegistry registry = new EtcdRegistry(properties.getAddress()); 35 | return registry; 36 | } 37 | 38 | @ConditionalOnProperty(prefix = "iris.server", value = "enable", havingValue = "true") 39 | @Bean 40 | public RpcServer rpcServer(IRegistry registry, ServerProperties properties) { 41 | RpcServer server = new RpcServer(registry); 42 | server.port(properties.getPort()); 43 | return server; 44 | } 45 | 46 | @ConditionalOnProperty(prefix = "iris.server", value = "enable", havingValue = "true") 47 | @Bean 48 | public ServiceAnnotationBeanPostProcessor serviceAnnotationBeanPostProcessor() { 49 | ServiceAnnotationBeanPostProcessor processor = new ServiceAnnotationBeanPostProcessor(); 50 | return processor; 51 | } 52 | 53 | @ConditionalOnProperty(prefix = "iris.client", value = "enable", havingValue = "true") 54 | @Bean 55 | public ReferenceAnnotationBeanPostProcessor referenceAnnotationBeanPostProcessor() { 56 | ReferenceAnnotationBeanPostProcessor processor = new ReferenceAnnotationBeanPostProcessor(); 57 | return processor; 58 | } 59 | 60 | @ConditionalOnProperty(prefix = "iris.server", value = "enable", havingValue = "true") 61 | @Bean 62 | public IrisApplicationListener applicationListener() { 63 | IrisApplicationListener applicationListener = new IrisApplicationListener(); 64 | return applicationListener; 65 | } 66 | 67 | @ConditionalOnProperty(prefix = "iris.client", value = "enable", havingValue = "true") 68 | @Bean 69 | public RpcClient client(IRegistry registry) { 70 | RpcClient client = new RpcClient(registry); 71 | return client; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /iris/iris-spring-boot/src/main/java/com/leiwei2094/iris/springboot/properties/RegistryProperties.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.springboot.properties; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | @ConfigurationProperties(prefix = "iris.registry") 6 | public class RegistryProperties { 7 | 8 | private String address = "http://127.0.0.1:2379"; 9 | 10 | public String getAddress() { 11 | return address; 12 | } 13 | 14 | public void setAddress(String address) { 15 | this.address = address; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /iris/iris-spring-boot/src/main/java/com/leiwei2094/iris/springboot/properties/ServerProperties.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.springboot.properties; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | @ConfigurationProperties(prefix = "iris.server") 6 | public class ServerProperties { 7 | 8 | private int port = 2017; 9 | 10 | public int getPort() { 11 | return port; 12 | } 13 | 14 | public void setPort(int port) { 15 | this.port = port; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /iris/iris-spring-boot/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 2 | com.leiwei2094.iris.springboot.config.IrisAutoConfiguration -------------------------------------------------------------------------------- /iris/iris-spring-boot/src/main/resources/application.properties.sample: -------------------------------------------------------------------------------- 1 | iris.registry.address=http://127.0.0.1:2379 2 | 3 | iris.server.enable=true 4 | iris.annotation.package=com.leiwei2094.iris.springboot -------------------------------------------------------------------------------- /iris/iris-spring-boot/src/test/java/com/leiwei2094/iris/springboot/ClientApplication.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.springboot; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.util.Properties; 9 | 10 | @SpringBootApplication 11 | public class ClientApplication { 12 | public static void main(String[] args) throws IOException { 13 | Properties properties = new Properties(); 14 | InputStream in = ClientApplication.class.getClassLoader().getResourceAsStream("application-client.properties"); 15 | properties.load(in); 16 | SpringApplication app = new SpringApplication(ClientApplication.class); 17 | app.setDefaultProperties(properties); 18 | app.run(args); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /iris/iris-spring-boot/src/test/java/com/leiwei2094/iris/springboot/ClientTest.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.springboot; 2 | 3 | import org.junit.Ignore; 4 | import org.junit.Test; 5 | import org.junit.runner.RunWith; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | import org.springframework.test.context.TestPropertySource; 9 | import org.springframework.test.context.junit4.SpringRunner; 10 | 11 | @TestPropertySource(value = "classpath:/application-client.properties") 12 | @RunWith(SpringRunner.class) 13 | @SpringBootTest(classes = ClientApplication.class) 14 | public class ClientTest { 15 | 16 | @Autowired 17 | private Foo foo; 18 | 19 | @Ignore 20 | @Test 21 | public void test() throws Exception { 22 | System.out.println("==tom=="); 23 | System.out.println(foo.hello("tom")); 24 | System.out.println("==leo=="); 25 | System.out.println(foo.hello("leo")); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /iris/iris-spring-boot/src/test/java/com/leiwei2094/iris/springboot/Foo.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.springboot; 2 | 3 | import com.leiwei2094.iris.core.IHelloService; 4 | import com.leiwei2094.iris.core.annotation.Reference; 5 | import org.springframework.stereotype.Component; 6 | 7 | @Component 8 | public class Foo { 9 | 10 | @Reference(interfaceClass = IHelloService.class) 11 | private IHelloService helloService; 12 | 13 | public String hello(String name) throws Exception { 14 | return helloService.hello(name); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /iris/iris-spring-boot/src/test/java/com/leiwei2094/iris/springboot/HelloService.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.springboot; 2 | 3 | import com.leiwei2094.iris.core.IHelloService; 4 | import com.leiwei2094.iris.core.annotation.Service; 5 | 6 | @Service(interfaceClass = IHelloService.class) 7 | public class HelloService implements IHelloService { 8 | @Override 9 | public String hello(String name) throws Exception { 10 | return "Hello, " + name + ", from com.leiwei2094.iris.springboot.HelloService"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /iris/iris-spring-boot/src/test/java/com/leiwei2094/iris/springboot/ServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.springboot; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.util.Properties; 9 | 10 | @SpringBootApplication 11 | public class ServerApplication { 12 | public static void main(String[] args) throws IOException { 13 | Properties properties = new Properties(); 14 | InputStream in = ClientApplication.class.getClassLoader().getResourceAsStream("application-server.properties"); 15 | properties.load(in); 16 | SpringApplication app = new SpringApplication(ClientApplication.class); 17 | app.setDefaultProperties(properties); 18 | app.run(args); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /iris/iris-spring-boot/src/test/resources/application-client.properties: -------------------------------------------------------------------------------- 1 | iris.registry.address=http://127.0.0.1:2379 2 | 3 | iris.client.enable=true -------------------------------------------------------------------------------- /iris/iris-spring-boot/src/test/resources/application-server.properties: -------------------------------------------------------------------------------- 1 | iris.registry.address=http://127.0.0.1:2379 2 | 3 | iris.server.enable=true 4 | iris.server.port=2017 5 | iris.annotation.package=com.leiwei2094.iris.springboot -------------------------------------------------------------------------------- /iris/iris-spring-boot/src/test/resources/iris.properties: -------------------------------------------------------------------------------- 1 | iris.loadbalance=first -------------------------------------------------------------------------------- /iris/iris-spring/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | iris-parent 7 | com.leiwei2094 8 | ${revision} 9 | ../iris-parent/pom.xml 10 | 11 | 4.0.0 12 | 13 | iris-spring 14 | 15 | 16 | 17 | org.springframework 18 | spring-context 19 | 20 | 21 | com.leiwei2094 22 | iris-core 23 | ${project.version} 24 | 25 | 26 | com.leiwei2094 27 | iris-server 28 | ${project.version} 29 | 30 | 31 | com.leiwei2094 32 | iris-client 33 | ${project.version} 34 | 35 | 36 | net.bytebuddy 37 | byte-buddy 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /iris/iris-spring/src/main/java/com/leiwei2094/iris/spring/IrisApplicationListener.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.spring; 2 | 3 | import com.leiwei2094.iris.server.RpcServer; 4 | import org.springframework.beans.BeansException; 5 | import org.springframework.context.ApplicationContext; 6 | import org.springframework.context.ApplicationContextAware; 7 | import org.springframework.context.ApplicationEvent; 8 | import org.springframework.context.ApplicationListener; 9 | import org.springframework.context.event.ContextRefreshedEvent; 10 | 11 | public class IrisApplicationListener implements ApplicationListener, ApplicationContextAware { 12 | private ApplicationContext applicationContext; 13 | 14 | @Override 15 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 16 | this.applicationContext = applicationContext; 17 | } 18 | 19 | @Override 20 | public void onApplicationEvent(ApplicationEvent applicationEvent) { 21 | // 所有bean都已经实例化好了 22 | // 可以启动RpcServer了 23 | if (applicationEvent instanceof ContextRefreshedEvent) { 24 | RpcServer server = applicationContext.getBean(RpcServer.class); 25 | try { 26 | server.run(); 27 | } catch (Exception e) { 28 | e.printStackTrace(); 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /iris/iris-spring/src/main/java/com/leiwei2094/iris/spring/ReferenceAnnotationBeanPostProcessor.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.spring; 2 | 3 | import com.leiwei2094.iris.client.RpcClient; 4 | import com.leiwei2094.iris.core.annotation.Reference; 5 | import org.springframework.beans.BeansException; 6 | import org.springframework.beans.factory.config.BeanPostProcessor; 7 | import org.springframework.context.ApplicationContext; 8 | import org.springframework.context.ApplicationContextAware; 9 | 10 | import java.lang.reflect.Field; 11 | 12 | public class ReferenceAnnotationBeanPostProcessor implements BeanPostProcessor, ApplicationContextAware { 13 | private ApplicationContext applicationContext; 14 | 15 | public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 16 | return bean; 17 | } 18 | 19 | public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 20 | Class beanClass = bean.getClass(); 21 | Field[] fields = beanClass.getDeclaredFields(); 22 | for (int i = 0; i < fields.length; i++) { 23 | Field field = fields[i]; 24 | if (field.isAnnotationPresent(Reference.class)) { 25 | Reference reference = field.getAnnotation(Reference.class); 26 | field.setAccessible(true); 27 | try { 28 | field.set(bean, applicationContext.getBean(RpcClient.class).create(reference.interfaceClass())); 29 | } catch (Exception e) { 30 | e.printStackTrace(); 31 | } 32 | } 33 | } 34 | return bean; 35 | } 36 | 37 | @Override 38 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 39 | this.applicationContext = applicationContext; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /iris/iris-spring/src/main/java/com/leiwei2094/iris/spring/ServiceAnnotationBeanPostProcessor.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.spring; 2 | 3 | import com.leiwei2094.iris.core.annotation.Service; 4 | import com.leiwei2094.iris.server.RpcServer; 5 | import org.springframework.beans.BeansException; 6 | import org.springframework.beans.factory.config.BeanPostProcessor; 7 | import org.springframework.context.ApplicationContext; 8 | import org.springframework.context.ApplicationContextAware; 9 | 10 | public class ServiceAnnotationBeanPostProcessor implements BeanPostProcessor, ApplicationContextAware { 11 | private ApplicationContext applicationContext; 12 | 13 | public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 14 | return bean; 15 | } 16 | 17 | public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 18 | Class beanClass = bean.getClass(); 19 | if (beanClass.isAnnotationPresent(Service.class)) { 20 | RpcServer rpcServer = applicationContext.getBean(RpcServer.class); 21 | Service serviceClass = beanClass.getDeclaredAnnotation(Service.class); 22 | try { 23 | rpcServer.exposeService(serviceClass.interfaceClass(), bean); 24 | } catch (Exception e) { 25 | e.printStackTrace(); 26 | } 27 | } 28 | return bean; 29 | } 30 | 31 | @Override 32 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 33 | this.applicationContext = applicationContext; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /iris/iris-spring/src/test/java/com/leiwei2094/iris/spring/Baz.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.spring; 2 | 3 | import com.leiwei2094.iris.core.IHelloService; 4 | import com.leiwei2094.iris.core.annotation.Reference; 5 | 6 | public class Baz { 7 | 8 | @Reference(interfaceClass = IHelloService.class) 9 | private IHelloService helloService; 10 | 11 | public void hello(String name) throws Exception { 12 | System.out.println(helloService.hello(name)); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /iris/iris-spring/src/test/java/com/leiwei2094/iris/spring/HelloService.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.spring; 2 | 3 | import com.leiwei2094.iris.core.IHelloService; 4 | import com.leiwei2094.iris.core.annotation.Service; 5 | 6 | @Service(interfaceClass = IHelloService.class) 7 | public class HelloService implements IHelloService { 8 | @Override 9 | public String hello(String name) throws Exception { 10 | return "hello" + name; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /iris/iris-spring/src/test/java/com/leiwei2094/iris/spring/XmlClient.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.spring; 2 | 3 | import org.springframework.context.support.ClassPathXmlApplicationContext; 4 | 5 | public class XmlClient { 6 | public static void main(String[] args) throws Exception { 7 | ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans-client.xml"); 8 | Baz baz = context.getBean(Baz.class); 9 | 10 | baz.hello("leo"); 11 | baz.hello("tom"); 12 | 13 | Thread.sleep(100 * 1000); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /iris/iris-spring/src/test/java/com/leiwei2094/iris/spring/XmlServer.java: -------------------------------------------------------------------------------- 1 | package com.leiwei2094.iris.spring; 2 | 3 | import com.leiwei2094.iris.server.RpcServer; 4 | import org.springframework.context.support.ClassPathXmlApplicationContext; 5 | 6 | public class XmlServer { 7 | public static void main(String[] args) throws Exception { 8 | ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans-server.xml"); 9 | RpcServer server = context.getBean(RpcServer.class); 10 | server.port(2017); 11 | server.run(); 12 | 13 | Thread.sleep(100 * 1000); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /iris/iris-spring/src/test/resources/beans-client.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /iris/iris-spring/src/test/resources/beans-server.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /iris/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.leiwei2094 8 | iris 9 | ${revision} 10 | 11 | 12 | 2022.07.21 13 | 1.2.5 14 | 15 | 16 | 17 | iris-core 18 | iris-client 19 | iris-protocol 20 | iris-registry 21 | iris-server 22 | iris-spring 23 | iris-spring-boot 24 | iris-bom 25 | iris-parent 26 | 27 | 28 | pom 29 | 30 | 31 | 32 | 33 | org.codehaus.mojo 34 | flatten-maven-plugin 35 | ${maven_flatten_version} 36 | 37 | true 38 | resolveCiFriendliesOnly 39 | 40 | 41 | 42 | flatten 43 | process-resources 44 | 45 | flatten 46 | 47 | 48 | 49 | flatten.clean 50 | clean 51 | 52 | clean 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /samples/.gitignore: -------------------------------------------------------------------------------- 1 | demo-a/demo-a-api/build 2 | demo-a/demo-a-service/out 3 | demo-a/demo-a-api/out 4 | demo-b/out 5 | 6 | -------------------------------------------------------------------------------- /samples/demo-a/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "io.spring.dependency-management" version "1.0.3.RELEASE" 3 | } 4 | 5 | group 'com.leibangzhu.iris' 6 | version '1.0.0-SNAPSHOT' 7 | 8 | apply plugin: 'java' 9 | 10 | sourceCompatibility = 1.8 11 | 12 | repositories { 13 | maven { url "http://100.100.100.100:8087/nexus/content/groups/public/" } 14 | mavenLocal() 15 | mavenCentral() 16 | } 17 | 18 | dependencies { 19 | testCompile group: 'junit', name: 'junit', version: '4.11' 20 | } 21 | -------------------------------------------------------------------------------- /samples/demo-a/demo-a-api/build.gradle: -------------------------------------------------------------------------------- 1 | group 'com.leibangzhu.iris' 2 | version '1.0.0-SNAPSHOT' 3 | //description 'iris-sample-api' 4 | 5 | apply plugin: 'java' 6 | apply plugin: 'maven' 7 | 8 | sourceCompatibility = 1.8 9 | 10 | repositories { 11 | mavenLocal() 12 | mavenCentral() 13 | } 14 | 15 | dependencies { 16 | testCompile group: 'junit', name: 'junit', version: '4.11' 17 | } 18 | 19 | uploadArchives { 20 | repositories { 21 | mavenLocal() 22 | // mavenDeployer { 23 | // repository(url: "file://Users/leiwei/.m2/repository") 24 | // } 25 | } 26 | } -------------------------------------------------------------------------------- /samples/demo-a/demo-a-api/src/main/java/com/leibangzhu/iris/demoa/api/IHelloService.java: -------------------------------------------------------------------------------- 1 | package com.leibangzhu.iris.demoa.api; 2 | 3 | public interface IHelloService { 4 | String sayHello(String name); 5 | 6 | String sayHello2(String name); 7 | } 8 | -------------------------------------------------------------------------------- /samples/demo-a/demo-a-service/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '1.5.7.RELEASE' 3 | id 'java' 4 | } 5 | 6 | repositories { 7 | maven { url "http://114.55.36.61:8087/nexus/content/groups/public/" } 8 | mavenLocal() 9 | mavenCentral() 10 | maven { url "http://repo.spring.io/snapshot" } 11 | maven { url "http://repo.spring.io/milestone" } 12 | } 13 | 14 | dependencies { 15 | compile project(":demo-a-api") 16 | compile("com.leibangzhu:iris-spring:1.0-SNAPSHOT") 17 | compile("com.leibangzhu:iris-server:1.0-SNAPSHOT") 18 | 19 | compile("org.springframework.boot:spring-boot-starter-web") 20 | testCompile("org.springframework.boot:spring-boot-starter-test") 21 | } 22 | 23 | sourceCompatibility = 1.8 24 | 25 | allprojects { 26 | configurations.all { 27 | // check for updates every build 28 | resolutionStrategy.cacheChangingModulesFor(0, 'seconds') 29 | } 30 | } 31 | 32 | springBoot { 33 | executable = true 34 | } 35 | 36 | dependencyManagement { 37 | resolutionStrategy { 38 | cacheChangingModulesFor 0, 'seconds' 39 | } 40 | 41 | // imports { 42 | // mavenBom 'com.qibeitech:qibei-bom:1.1.0-SNAPSHOT' 43 | // } 44 | } 45 | 46 | group 'com.leibangzhu.iris' 47 | version '1.0.0-SNAPSHOT' -------------------------------------------------------------------------------- /samples/demo-a/demo-a-service/src/main/java/com/leibangzhu/iris/demoa/service/App.java: -------------------------------------------------------------------------------- 1 | package com.leibangzhu.iris.demoa.service; 2 | 3 | 4 | import com.leibangzhu.iris.demoa.api.IHelloService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.SpringApplication; 7 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 8 | import org.springframework.boot.autoconfigure.SpringBootApplication; 9 | import org.springframework.context.annotation.ComponentScan; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | 14 | @SpringBootApplication 15 | @RestController 16 | public class App { 17 | 18 | // @Autowired 19 | // private IHelloService helloService; 20 | 21 | @RequestMapping("/") 22 | String home(){ 23 | return "Hello world!"; 24 | } 25 | 26 | // @RequestMapping("/hello") 27 | // String hello(){ 28 | // return helloService.sayHello("leo"); 29 | // } 30 | // 31 | // @RequestMapping("/hello2") 32 | // String hello2(){ 33 | // return helloService.sayHello2("leo"); 34 | // } 35 | 36 | public static void main(String[] args){ 37 | SpringApplication.run(App.class,args); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /samples/demo-a/demo-a-service/src/main/java/com/leibangzhu/iris/demoa/service/AppConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.leibangzhu.iris.demoa.service; 2 | 3 | //import com.leibangzhu.iris.core.HelloService; 4 | import com.leibangzhu.iris.demoa.api.IHelloService; 5 | import com.leibangzhu.iris.registry.EtcdRegistry; 6 | import com.leibangzhu.iris.registry.IRegistry; 7 | import com.leibangzhu.iris.server.RpcServer; 8 | import org.springframework.context.annotation.Bean; 9 | import org.springframework.context.annotation.Configuration; 10 | 11 | @Configuration 12 | public class AppConfiguration { 13 | 14 | @Bean 15 | public IRegistry registry() throws Exception { 16 | IRegistry registry = new EtcdRegistry("http://127.0.0.1:2379"); 17 | return registry; 18 | } 19 | 20 | @Bean 21 | public RpcServer rpcServer(IRegistry registry) throws Exception { 22 | 23 | RpcServer server = new RpcServer(registry) 24 | .port(2017) 25 | .exposeService(IHelloService.class,new HelloService()); 26 | server.run(); 27 | return server; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /samples/demo-a/demo-a-service/src/main/java/com/leibangzhu/iris/demoa/service/HelloService.java: -------------------------------------------------------------------------------- 1 | package com.leibangzhu.iris.demoa.service; 2 | 3 | import com.leibangzhu.iris.demoa.api.IHelloService; 4 | 5 | public class HelloService implements IHelloService { 6 | @Override 7 | public String sayHello(String name) { 8 | return "hello" + name; 9 | } 10 | 11 | @Override 12 | public String sayHello2(String name) { 13 | return "hello" + name; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /samples/demo-a/demo-a-service/src/main/java/com/leibangzhu/iris/demoa/service/aspect/LogAspect.java: -------------------------------------------------------------------------------- 1 | //package com.qibeitech.demoa.service.aspect; 2 | // 3 | // 4 | //import com.alibaba.fastjson.JSONObject; 5 | //import org.apache.commons.lang3.ArrayUtils; 6 | //import org.aspectj.lang.ProceedingJoinPoint; 7 | //import org.aspectj.lang.annotation.Around; 8 | //import org.aspectj.lang.annotation.Aspect; 9 | //import org.aspectj.lang.annotation.Pointcut; 10 | //import org.aspectj.lang.reflect.MethodSignature; 11 | //import org.slf4j.Logger; 12 | //import org.slf4j.LoggerFactory; 13 | //import org.springframework.stereotype.Component; 14 | // 15 | //import java.lang.reflect.Method; 16 | // 17 | //@Aspect 18 | //@Component 19 | //public class LogAspect { 20 | // 21 | // private static Logger logger = LoggerFactory.getLogger(LogAspect.class); 22 | // 23 | // //@Pointcut("execution(* com.qibeitech.demoa.service.service.*Service*.*(..))") 24 | // @Pointcut("@within(com.qibeitech.starters.common.Loggable) || @annotation(com.qibeitech.starters.common.Loggable)") 25 | // public void recordLog() { 26 | // 27 | // } 28 | // 29 | // @Around(value = "recordLog()") 30 | // public Object execute(ProceedingJoinPoint joinPoint) throws Throwable { 31 | // Object result = null; 32 | // MethodSignature signature = (MethodSignature) joinPoint.getSignature(); 33 | // Method method = signature.getMethod(); 34 | // try { 35 | // Object[] objects = joinPoint.getArgs(); 36 | // //String context = null; 37 | // //JSONObject.toJSONString(objects); 38 | // if (ArrayUtils.isNotEmpty(objects)) { 39 | // logger.info("方法:[{}], 参数列表:[{}]", method.getName(), JSONObject.toJSONString(objects)); 40 | // }else{ 41 | // logger.info("方法:[{}], 无参数列表", method.getName()); 42 | // } 43 | // }catch (Exception e){ 44 | // logger.error(e.getMessage()); 45 | // } 46 | // 47 | // result = joinPoint.proceed(); 48 | // 49 | // try{ 50 | // if (null != result) { 51 | // String json = JSONObject.toJSONString(result); 52 | // logger.info("方法:[{}], 返回值:[{}]", method.getName(), json); 53 | // } 54 | // } catch (Throwable throwable) { 55 | // logger.error(throwable.getMessage()); 56 | // } 57 | // 58 | // return result; 59 | // } 60 | //} -------------------------------------------------------------------------------- /samples/demo-a/demo-a-service/src/main/java/com/leibangzhu/iris/demoa/service/service/HelloService.java: -------------------------------------------------------------------------------- 1 | package com.leibangzhu.iris.demoa.service.service; 2 | 3 | import com.leibangzhu.iris.demoa.api.IHelloService; 4 | 5 | public class HelloService implements IHelloService { 6 | 7 | @Override 8 | public String sayHello(String name) { 9 | return "Hello, " + name; 10 | } 11 | 12 | @Override 13 | public String sayHello2(String name) { 14 | return "Hello, " + name; 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /samples/demo-a/demo-a-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=8081 2 | 3 | 4 | ## 项目名称设置,必须 5 | #dubbo.application.name=dubbo-demo-a 6 | #dubbo.application.logger=slf4j 7 | ## 包扫描设置,必须 8 | #dubbo.annotation.package=com.qibeitech.demoa.service.service 9 | ## 接口协议 10 | #dubbo.protocol.name=dubbo 11 | #dubbo.protocol.port=20880 12 | #dubbo.protocol.accessLog=true 13 | ## 服务的超时时间,单位毫秒 14 | #dubbo.provider.timeout=3000 15 | ##调用失败重试次数 16 | #dubbo.provider.retries=1 17 | ##是否延迟暴露,-1表示不延迟暴露 18 | #dubbo.provider.delay=-1 19 | ##接口协议 20 | #dubbo.registr.protocol=zookeeper 21 | ##注册中心地址 22 | #dubbo.registry.address=127.0.0.1:2181 23 | ##是否向注册中心注册服务 24 | #dubbo.registry.register=true 25 | ##是否向注册中心订阅服务 26 | #dubbo.registry.subscribe=true 27 | 28 | 29 | ## producer 30 | #message.etcd.producer.endpoints=http://127.0.0.1:2379 31 | # 32 | ## consumer 33 | #message.etcd.consumer.endpoints=http://127.0.0.1:2379 34 | #message.etcd.consumer.topic=myTopic 35 | #message.etcd.consumer.tags=tagA 36 | -------------------------------------------------------------------------------- /samples/demo-a/demo-a-service/src/main/resources/dubbo-provider.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /samples/demo-a/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'demo-a' 2 | include 'demo-a-api' 3 | include 'demo-a-service' 4 | 5 | -------------------------------------------------------------------------------- /samples/demo-b/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '1.5.7.RELEASE' 3 | id 'java' 4 | } 5 | 6 | repositories { 7 | maven { url "http://100.100.100.100:8087/nexus/content/groups/public/" } 8 | mavenLocal() 9 | mavenCentral() 10 | maven { url "http://repo.spring.io/snapshot" } 11 | maven { url "http://repo.spring.io/milestone" } 12 | } 13 | 14 | dependencies { 15 | compile("com.leibangzhu:iris-spring:1.0-SNAPSHOT") 16 | compile("com.leibangzhu:iris-client:1.0-SNAPSHOT") 17 | compile("com.leibangzhu.iris:demo-a-api:1.0.0-SNAPSHOT") 18 | 19 | compile("org.springframework.boot:spring-boot-starter-web") 20 | testCompile("org.springframework.boot:spring-boot-starter-test") 21 | } 22 | 23 | sourceCompatibility = 1.8 24 | 25 | allprojects { 26 | configurations.all { 27 | // check for updates every build 28 | resolutionStrategy.cacheChangingModulesFor(0, 'seconds') 29 | } 30 | } 31 | 32 | springBoot { 33 | executable = true 34 | } 35 | 36 | dependencyManagement { 37 | resolutionStrategy { 38 | cacheChangingModulesFor 0, 'seconds' 39 | } 40 | 41 | // imports { 42 | // mavenBom 'com.qibeitech:qibei-bom:1.1.0-SNAPSHOT' 43 | // } 44 | } 45 | 46 | group 'com.leibangzhu.iris' 47 | version '1.0.0-SNAPSHOT' 48 | -------------------------------------------------------------------------------- /samples/demo-b/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'demo-b' 2 | 3 | -------------------------------------------------------------------------------- /samples/demo-b/src/main/java/com/qibeitech/demob/App.java: -------------------------------------------------------------------------------- 1 | package com.qibeitech.demob; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | @SpringBootApplication 10 | @RestController 11 | public class App { 12 | 13 | @Autowired 14 | private Foo foo; 15 | 16 | // @Autowired 17 | // private Bar bar; 18 | 19 | @RequestMapping("/") 20 | String home() throws Exception { 21 | // String s = foo.hello(); 22 | String s = foo.hello(); 23 | return s; 24 | } 25 | 26 | public static void main(String[] args){ 27 | SpringApplication.run(App.class,args); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /samples/demo-b/src/main/java/com/qibeitech/demob/AppConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.qibeitech.demob; 2 | 3 | import com.leibangzhu.iris.client.IRpcClient; 4 | import com.leibangzhu.iris.client.RpcClient; 5 | import com.leibangzhu.iris.registry.EtcdRegistry; 6 | import com.leibangzhu.iris.registry.IRegistry; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | @Configuration 11 | public class AppConfiguration { 12 | 13 | @Bean 14 | public IRegistry registry() throws Exception { 15 | IRegistry registry = new EtcdRegistry("http://127.0.0.1:2379"); 16 | return registry; 17 | } 18 | 19 | @Bean 20 | public IRpcClient rpcClient(IRegistry registry){ 21 | RpcClient client = new RpcClient(registry); 22 | return client; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /samples/demo-b/src/main/java/com/qibeitech/demob/Bar.java: -------------------------------------------------------------------------------- 1 | //package com.qibeitech.demob; 2 | // 3 | //import com.qibeitech.demoa.api.IHelloService; 4 | // 5 | //public class Bar { 6 | // 7 | // private IHelloService helloService; 8 | // 9 | // public Bar(IHelloService helloService){ 10 | // this.helloService = helloService; 11 | // } 12 | // 13 | // public String hello(){ 14 | // return helloService.sayHello("...bar..."); 15 | // } 16 | //} 17 | -------------------------------------------------------------------------------- /samples/demo-b/src/main/java/com/qibeitech/demob/Foo.java: -------------------------------------------------------------------------------- 1 | package com.qibeitech.demob; 2 | 3 | import com.leibangzhu.iris.client.IRpcClient; 4 | import com.leibangzhu.iris.demoa.api.IHelloService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Component; 7 | 8 | @Component 9 | public class Foo { 10 | 11 | @Autowired 12 | private IRpcClient rpcClient; 13 | 14 | public String hello() throws Exception { 15 | IHelloService helloService = rpcClient.create(IHelloService.class); 16 | return helloService.sayHello("foo"); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /samples/demo-b/src/main/java/com/qibeitech/demob/ITestService.java: -------------------------------------------------------------------------------- 1 | //package com.qibeitech.demob; 2 | // 3 | //public interface ITestService { 4 | // String test(); 5 | //} 6 | -------------------------------------------------------------------------------- /samples/demo-b/src/main/java/com/qibeitech/demob/TestConfiguration.java: -------------------------------------------------------------------------------- 1 | //package com.qibeitech.demob; 2 | // 3 | ////import com.qibeitech.demoa.api.IHelloService; 4 | //import org.springframework.beans.factory.annotation.Autowired; 5 | //import org.springframework.context.annotation.Bean; 6 | //import org.springframework.context.annotation.Configuration; 7 | // 8 | //@Configuration 9 | //public class TestConfiguration { 10 | // 11 | //// @Autowired 12 | //// private IHelloService helloService; 13 | //// 14 | //// @Bean 15 | //// public Bar bar(){ 16 | //// return new Bar(helloService); 17 | //// } 18 | //} 19 | -------------------------------------------------------------------------------- /samples/demo-b/src/main/java/com/qibeitech/demob/TestService.java: -------------------------------------------------------------------------------- 1 | //package com.qibeitech.demob; 2 | // 3 | //@com.alibaba.dubbo.config.annotation.Service 4 | //public class TestService implements ITestService { 5 | // @Override 6 | // public String test() { 7 | // return "test"; 8 | // } 9 | //} 10 | -------------------------------------------------------------------------------- /samples/demo-b/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=8082 2 | 3 | 4 | # 项目名称设置,必须 5 | dubbo.application.name=dubbo-demo-b 6 | dubbo.application.logger=slf4j 7 | # 包扫描设置,必须 8 | dubbo.annotation.package=com.qibeitech.demob 9 | # 接口协议 10 | dubbo.protocol.name=dubbo 11 | dubbo.protocol.port=20881 12 | dubbo.protocol.accessLog=true 13 | # 服务的超时时间,单位毫秒 14 | dubbo.provider.timeout=3000 15 | #调用失败重试次数 16 | dubbo.provider.retries=1 17 | #是否延迟暴露,-1表示不延迟暴露 18 | dubbo.provider.delay=-1 19 | #接口协议 20 | dubbo.registr.protocol=zookeeper 21 | #注册中心地址 22 | dubbo.registry.address=127.0.0.1:2181 23 | #是否向注册中心注册服务 24 | dubbo.registry.register=true 25 | #是否向注册中心订阅服务 26 | dubbo.registry.subscribe=true 27 | 28 | -------------------------------------------------------------------------------- /samples/demo-b/src/main/resources/dubbo-consumer.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /samples/demo-b/src/main/resources/dubbo-provider.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | --------------------------------------------------------------------------------