作者: vangoleo
官网: http://www.vangoleo.com/iris-java/
背景
时光荏苒, 进入阿里中间件团队已经快两年时间了. 这期间, 有幸参与了第四届中间件性能挑战赛的题目组, 筹备了以 "Dubbo Mesh" 为主题的初赛题; 和团队一起开展了 Dubbo 线下 meetup 活动; 将阿里多年双 11 积累的中间件基础设施最佳实践和方法论, 通过阿里云的商业化产品, 为广大开发者和企业提供服务. 很庆幸能有这样一段难忘的经历. 回想起来, 能进入中间件团队, 和我当初的一个 GitHub 项目还有关系. 今天把该项目分享给大家.
Q: 什么是中间件团队?
A: 阿里巴巴中间件技术部, 是世界顶尖的 Java 技术团队之一, 起源于淘宝平台架构组, 是跟随着阿里电商业务和双十一成长起来的技术团队, 解决复杂的业务场景, 飞速的业务增长, 高并发的大促洪峰, 层出不穷的稳定性问题. 产品包括高分布式 RPC 服务框架, 高可靠分布式消息中间件, 分布式数据层, 海量数据存储, 实时计算, 系统性能优化, 架构高可用等几大领域的多个产品, 这些产品支撑阿里巴巴集团 (淘宝, 天猫, 聚划算, 1688, 菜鸟) 的所有交易和非交易业务系统, 安然平稳度过双十一 917 亿交易成交的挑战. 我们开源的中间件组件 Dubbo,Rocketmq,Nacos,tengine,Seata 等都被很多企业和个人在使用.
来自中间件的邀请
2017 年的时候, 我带领团队对后端架构进行了微服务重构. 选型时使用了 Dubbo 框架. 得益于 Dubbo 的高性能, 使用简单和高扩展性, 微服务改造很顺利, 公司的业务也越来越稳定. 我对 Dubbo 也产生了浓厚的兴趣, 希望可以更深入地了解这个优秀的 RPC 框架. 我研究了下 Dubbo 的源码, 自己从零开始编写了一个 mini 版的 Dubbo.
恰好时值阿里又重启了 Dubbo 项目, 且成为 Apache 的孵化项目(编写文本时已正式成为 Apache 项目).Dubbo 新的官网有一个 "Wanted: who's using dubbo" 页面, 我也留下了自己的信息, 来给 Dubbo 点个赞. 其中包含了 mini 版 Dubbo 的项目地址.
其实是很随意的一个举动, 没想到会发生后面的故事. 一个小时后, 我收到了一封邮件:
这是一封来自中间件团队 Dubbo 负责人的邮件. 当时感觉挺意外的, 也很欣喜. 中间件团队一直是我认为技术和影响力都很强的团队, 如果可以加入该团队, 是一个很好的机会.
于是接下来就是例行的投简历, 面试流程. 要吐槽下阿里的面试流程, 前后历时快两个月了, 一共有五轮, 真的是持久战呀. 面试的时候, 面试官问了一些关于 mini Dubbo 的问题. 结果还不错, 很侥幸的通过了面试, 正式加入中间件的 Dubbo 团队. 后来听我的老板说, 当初是因为对我的 mini Dubbo 项目感兴趣, 才有了面试邀约.
iris
mini 版 Dubbo 的项目地址为: https://github.com/vangoleo/iris-java . 我给它取名为 iris.
iris 是一个轻量级, 微内核加插件机制, 基于 Java 的 RPC 框架. 提供服务注册, 发现, 负载均衡, 支持 API 调用, Spring 集成和 Spring Boot starter 使用.
有如下特性:
网络通信: Netty4.
注册中心: 可扩展, 已支持 etcd.
动态代理: byte-buddy.
序列化: Protobuff(Protostuff).
可以脱离 Spring, 提供 API 调用. 自己实现了 IoC 容器.
集成 Spring, 提供 xml,Java 配置.
提供 Spring Boot Starter(开发该项目时, Dubbo 官方还不支持 Spring Boot Starter).
提供 SPI 机制, 实现微内核加插件的架构. 实现可扩展, 开发者可以为 iris 开发组件, 以插件的形式集成到 iris 中. 插件的加载使用另一个微容器框架见 coco 项目. 该项目 fork 于阿里的 cooma.
说明: iris 完全是我个人学习的项目, 麻雀虽小, 五脏俱全, 涵盖了 RPC 框架的基本功能. 它只是实现了从 0 到 1, 但是从 1 到 100 还有很多的事情需要去做.
如何使用
iris 支持以下使用方式:
原生 API 形式, 不依赖 Spring, 非 Spring 项目也可以使用.
Spring 配置方式, 和 Spring 很好的集成.
Spring Boot 配置方式, 提供了一个 spring boot starter, 以自动配置, 快速启动.
API 使用
Iris 核心代码不依赖 Spring, 可脱离 Spring 使用.
第一步: 启动 etcd 注册中心
编写一个接口 IHelloService
- public interface IHelloService {
- String hello(String name);
- }
第二步: 编写一个 IHelloService 的实现
- public class HelloService implements IHelloService {
- @Override
- public String hello(String name){
- return "Hello," + name;
- }
- }
第三步: 启动 Server
- IRegistry registry = new EtcdRegistry("http://127.0.0.1:2379");
- RpcServer server = new RpcServer(registry)
- .port(2017)
- .exposeService(IHelloService.class,new HelloService());
- server.run();
第四步: 启动 client
- RpcClient client = new RpcClient(registry);
- IHelloService helloService = client.create(IHelloService.class);
- String s = helloService.hello("leo");
- System.out.println(s); // hello, leo
第五步: 试着停止 server
因为服务没有 provider,client 报错找不到 provider
第六步: 启动 server
Server 启动后, 会去 etcd 注册中心注册服务, client 端马上正常工作.
Spring 配置方式
第一步: 编写服务提供者
服务提供者, 使用自定义注解 @Service 来暴露服务, 通过 interfaceClass 来指定服务的接口. 该 @Service 注解是 iris 提供的, 并非 Spring 的注解.
- @Service(interfaceClass = IHelloService.class)
- public class HelloService implements IHelloService {
- @Override
- public String hello(String name) throws Exception {
- return "hello" + name;
- }
- }
第二步: 编写服务消费者
服务使用者, 通过 @Reference 来引用远程服务, 就像使用本地的 SpringBean 一样. 背后的 SpringBean 封装和 Rpc 调用对开发者透明. 使用体验和 Dubbo 是一样的.
- public class Baz {
- @Reference(interfaceClass = IHelloService.class)
- private IHelloService helloService;
- public void hello(String name) throws Exception {
- System.out.println(helloService.hello(name));
- }
- }
第三步: 配置 Spring Bean
配置服务提供者, 本例子使用 xml 配置, 使用 Java Code 配置也可以.
- <bean id="registry" class="com.leibangzhu.iris.registry.EtcdRegistry">
- <constructor-arg name="registryAddress" value="http://127.0.0.1:2379"></constructor-arg>
- </bean>
- <bean id="server" class="com.leibangzhu.iris.server.RpcServer">
- <constructor-arg name="registry" ref="registry"></constructor-arg>
- </bean>
- <bean id="serviceAnnotationBeanPostProcessor" class="com.leibangzhu.iris.spring.ServiceAnnotationBeanPostProcessor"></bean>
- <bean id="helloService" class="com.leibangzhu.iris.spring.HelloService"></bean>
第四步: 配置服务消费者, 本例子使用 xml 配置, 使用 Java Code 配置也可以.
- <bean id="registry" class="com.leibangzhu.iris.registry.EtcdRegistry">
- <constructor-arg name="registryAddress" value="http://127.0.0.1:2379"></constructor-arg>
- </bean>
- <bean id="client" class="com.leibangzhu.iris.client.RpcClient">
- <constructor-arg name="registry" ref="registry"></constructor-arg>
- </bean>
- <bean id="referenceAnnotationBeanPostProcessor" class="com.leibangzhu.iris.spring.ReferenceAnnotationBeanPostProcessor"></bean>
- <bean id="foo" class="com.leibangzhu.iris.spring.Baz"></bean>
Spring Boot 配置
使用原生的 Spring 配置还是有些繁琐, 可以使用 Spring Boot 来获得更好的开发体验.
第一步: 编写服务提供者
- @Service(interfaceClass = IHelloService.class)
- public class HelloService implements IHelloService {
- @Override
- public String hello(String name) throws Exception {
- return "Hello," + name + ", from com.leibangzhu.iris.springboot.HelloService";
- }
- }
第二步: 编写服务消费者
- @Component
- public class Foo {
- @Reference(interfaceClass = IHelloService.class)
- private IHelloService helloService;
- public String hello(String name) throws Exception {
- return helloService.hello(name);
- }
- }
第三步: 在 application.properties 文件中配置服务提供者
- iris.registry.address=http://127.0.0.1:2379
- iris.server.enable=true
- iris.server.port=2017
- iris.annotation.package=com.leibangzhu.iris.springboot
第四步: 在 application.properties 文件中配置服务消费者
- iris.registry.address=http://127.0.0.1:2379
- iris.client.enable=true
使用 SpringBoot 时, 不许再手动配置相关的 spring bean,Iris 提供的 spring boot starter 会自动配置好这些 spring bean.
为什么取名 iris
iris 取名于梵高的画鸢尾花. 我自己比较喜欢绘画, 梵高是我比较喜欢的画家, 所以用梵高的鸢尾花为项目取名.
为什么会喜欢梵高?
其实吸引我的不是画家梵高, 而是那个虔诚, 善良又狂热的基督教徒梵高. 引用我多年前的一条朋友圈:
最近每天晚上睡觉前都会听一段梵高传. 其实之前并不了解梵高, 很庆幸可以听到蒋勋老师的这段梵高传, 可以了解这样精彩的一个生命. 梵高有生之年只卖出过一幅画, 还是以很低的价格, 然而在他死后, 他的画却成为最伟大的艺术作品. 为什么梵高的向日葵会燃烧的如此热烈, 很多人会说是因为他对艺术的热爱, 甚至有人说是因为梵高视觉上的残疾. 其实不是这样的. 在他短暂的 37 年的生命里, 他作为画家的身份其实只有生命中的最后 4 年, 梵高一生更重要的角色是一个虔诚, 狂热的基督教徒. 比利时矿工时的梵高, 当面对着一群衣衫褴褛, 骨瘦嶙峋的矿工, 梵高显得不安了, 作为一个基督教徒, 不应该看到这样的一群人们而无所作为, 作为一个基督徒, 应该看到人世间的苦难, 然后能够去承担它, 这才叫做救赎. 耶稣不是因为救赎才来到人间的吗, 耶稣不是因为救赎才被钉在十字架上的吗. 如果生命中看不到救赎的部分, 耶稣基督存在的意义又是什么呢. 他脱掉了身上华丽的黑袍, 摘掉了白领巾, 拿起铲子, 竟和他们一起下到矿坑里去. 因为面对这样的一群人, 华丽的布道语言根本不能帮助他们, 只有去真正的感受他们的生活, 才可以帮助, 救赎这些穷困的人们. 梵高还把教堂的椅子拆掉, 来安置矿难中受伤的矿工, 把自己的食物全部分给矿工, 这样的一个有着深沉的人道主义关怀的教徒, 收到的是教会的解雇书, 教会认为一个牧师应该穿着华丽的黑袍, 讲着非常冠冕堂皇的布道语言, 梵高没有维护教会的尊严. 那是梵高一生中收到的最大的打击. 在梵高濒临绝望的时候, 拯救他的竟然是艺术, 是画画. 是怎样的画笔可以描绘出阿尔如此热烈的向日葵, 又是怎样的精神上的折磨, 会让他割掉自己的耳朵, 梵高的那么多自画像, 预示着什么? 又是怎样的一个生命, 可以在精神病院, 被囚禁的那间小屋, 创作出了他一生最伟大的作品 starry night. 梵高最后一幅画麦田里的乌鸦, 是否已预言了他生命的终结. 这就是那个被叫做文森特 - 威廉 - 梵高的生命.
我的 GitHub 账号 vangoleo 其实就是 vangogh(梵高) + leo(我的英文名)的组合.
最后附上我自己的几幅画, 不知道大家能不能认出来他们 ^_^
来源: https://www.cnblogs.com/leiwei/p/11839018.html