dogfooding

时间:2024-09-29 12:26:35编辑:奇闻君

主流的RPC框架有哪些?

RPC是远程过程调用的简称,广泛应用在大规模分布式应用中,作用是有助于系统的垂直拆分,使系统更易拓展。Java中的RPC框架比较多,各有特色,广泛使用的有RMI、Hessian、Dubbo等。RPC还有一个特点就是能够跨语言。1、RMI(远程方法调用)JAVA自带的远程方法调用工具,不过有一定的局限性,毕竟是JAVA语言最开始时的设计,后来很多框架的原理都基于RMI,RMI的使用如下:对外接口public interface IService extends Remote { public String queryName(String no) throws RemoteException; }服务实现import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; // 服务实现 public class ServiceImpl extends UnicastRemoteObject implements IService { /** */ private static final long serialVersionUID = 682805210518738166L; /** * @throws RemoteException */ protected ServiceImpl() throws RemoteException { super(); } /* (non-Javadoc) * @see com.suning.ebuy.wd.web.IService#queryName(java.lang.String) */ @Override public String queryName(String no) throws RemoteException { // 方法的具体实现 System.out.println("hello" + no); return String.valueOf(System.currentTimeMillis()); } } RMI客户端[java] view plain copyimport java.rmi.AccessException; import java.rmi.NotBoundException; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; // RMI客户端 public class Client { public static void main(String[] args) { // 注册管理器 Registry registry = null; try { // 获取服务注册管理器 registry = LocateRegistry.getRegistry("127.0.0.1",8088); // 列出所有注册的服务 String[] list = registry.list(); for(String s : list){ System.out.println(s); } } catch (RemoteException e) { } try { // 根据命名获取服务 IService server = (IService) registry.lookup("vince"); // 调用远程方法 String result = server.queryName("ha ha ha ha"); // 输出调用结果 System.out.println("result from remote : " + result); } catch (AccessException e) { } catch (RemoteException e) { } catch (NotBoundException e) { } } } RMI服务端[java] view plain copyimport java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; // RMI服务端 public class Server { public static void main(String[] args) { // 注册管理器 Registry registry = null; try { // 创建一个服务注册管理器 registry = LocateRegistry.createRegistry(8088); } catch (RemoteException e) { } try { // 创建一个服务 ServiceImpl server = new ServiceImpl(); // 将服务绑定命名 registry.rebind("vince", server); System.out.println("bind server"); } catch (RemoteException e) { } } }2、Hessian(基于HTTP的远程方法调用)基于HTTP协议传输,在性能方面还不够完美,负载均衡和失效转移依赖于应用的负载均衡器,Hessian的使用则与RMI类似,区别在于淡化了Registry的角色,通过显示的地址调用,利用HessianProxyFactory根据配置的地址create一个代理对象,另外还要引入Hessian的Jar包。3、Dubbo(淘宝开源的基于TCP的RPC框架)基于Netty的高性能RPC框架,是阿里巴巴开源的,总体原理如下:

rpc框架都有哪些rmi dubbo

Dubbo分层

config(配置层 )

proxy(服务代理层)

registry( 注册中心层)

cluster( 路由层)

monitor( 监控层)

protocol( 远程调用层)

exchange( 信息交换层)

transport( 网络传输层)

serialize( 数据序列化层)

对外配置接口
以ServiceConfig, ReferenceConfig为中心,可以直接new配置类,也可以通过spring解析配置生成配置类
Javassist ProxyFactory
Jdk ProxyFactory
服务接口透明代理,生成服务的客户端Stub和服务器端Skeleton
以ServiceProxy为中心,扩展接口为ProxyFactory
选择

Zookeeper

Redis

Multicast

Simple

支持基于网络的集群方式,有广泛周边开源产品,建议使用dubbo-2.3.3以上版本(推荐使用)
依赖于Zookeeper的稳定性
支持基于客户端双写的集群方式,性能高
要求服务器时间同步,用于检查心跳过期脏数据
去中心化,不需要安装注册中心
依赖于网络拓普和路由,跨机房有风险
Dogfooding,注册中心本身也是一个标准的RPC服务
没有集群支持,可能单点故障
封装服务地址的注册与发现
以服务URL为中心,扩展接口为RegistryFactory, Registry, RegistryService
选择

Spring

Jetty

Log4j

自动加载META-INF/spring目录下的所有Spring配置
启动一个内嵌Jetty,用于汇报状态
大量访问页面时,会影响服务器的线程和内存
自动配置log4j的配置,在多进程启动时,自动给日志文件按进程分目录
用户不能控制log4j的配置,不灵活
条件路由

脚本路由

基于条件表达式的路由规则,功能简单易用
有些复杂多分支条件情况,规则很难描述
基于脚本引擎的路由规则,功能强大
没有运行沙箱,脚本能力过于强大,可能成为后门
Random

RoundRobin

LeastActive

ConsistentHash

随机,按权重设置随机概率(推荐使用)
在一个截面上碰撞的概率高,重试时,可能出现瞬间压力不均
轮循,按公约后的权重设置轮循比率
存在慢的机器累积请求问题,极端情况可能产生雪崩
最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差,使慢的机器收到更少请求
不支持权重,在容量规划时,不能通过权重把压力导向一台机器压测容量
一致性Hash,相同参数的请求总是发到同一提供者,当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动
压力分摊不均
Failover

Failfast

Failsafe

Failback

Forking

Broadcast

失败自动切换,当出现失败,重试其它服务器,通常用于读操作(推荐使用)
重试会带来更长延迟
快速失败,只发起一次调用,失败立即报错,通常用于非幂等性的写操作
如果有机器正在重启,可能会出现调用失败
失败安全,出现异常时,直接忽略,通常用于写入审计日志等操作
调用信息丢失
失败自动恢复,后台记录失败请求,定时重发,通常用于消息通知操作
不可靠,重启丢失
并行调用多个服务器,只要一个成功即返回,通常用于实时性要求较高的读操作
需要浪费更多服务资源
广播调用所有提供者,逐个调用,任意一台报错则报错,通常用于更新提供方本地状态
速度慢,任意一台报错则报错
封装多个提供者的路由及负载均衡,并桥接注册中心
以Invoker为中心,扩展接口为Cluster, Directory, Router, LoadBalance
Cluster选择

Router选择

路由规则

容器

RPC调用次数和调用时间监控
以Statistics为中心,扩展接口为MonitorFactory, Monitor, MonitorService
Dubbo协议

Rmi协议

Hessian协议

连接个数:单连接
连接方式:长连接
传输协议:TCP
传输方式:NIO异步传输
序列化:Hessian二进制序列化
适用范围:传入传出参数数据包较小(建议小于100K),消费者比提供者个数多,单一消费者无法压满提供者,尽量不要用dubbo协议传输大文件或超大字符串。
适用场景:常规远程服务方法调用
采用NIO复用单一长连接,并使用线程池并发处理请求,减少握手和加大并发效率,性能较好(推荐使用)
适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况
Dubbo缺省协议不适合传送大数据量的服务,比如传文件,传视频等,除非请求量很低
Dubbo协议缺省每服务每提供者每消费者使用单一长连接,如果数据量较大,可以使用多个连接
为防止被大量连接撑挂,可在服务提供方限制大接收连接数,以实现服务提供方自我保护
在大文件传输时,单一连接会成为瓶颈
总结

可与原生RMI互操作,基于TCP协议
偶尔会连接失败,需重建Stub
参数及返回值需实现Serializable接口
参数及返回值不能自定义实现List, Map, Number, Date, Calendar等接口,只能用JDK自带的实现,因为hessian会做特殊处理,自定义实现类中的属性值都会丢失
连接个数:多连接
连接方式:短连接
传输协议:HTTP
传输方式:同步传输
序列化:Hessian二进制序列化
适用范围:传入传出参数数据包较大,提供者比消费者个数多,提供者压力较大,可传文件
适用场景:页面传输,文件传输,或与原生hessian服务互操作
提供者用Dubbo的Hessian协议暴露服务,消费者直接用标准Hessian接口调用
或者提供方用标准Hessian暴露服务,消费方用Dubbo的Hessian协议调用
基于Hessian的远程调用协议
可与原生Hessian互操作,基于HTTP协议
需hessian.jar支持,http短连接的开销大
Hessian协议用于集成Hessian的服务,Hessian底层采用Http通讯,采用Servlet暴露服务,Dubbo缺省内嵌Jetty作为服务器实现
可以和原生Hessian服务互操作

总结

约束

封装RPC调用
以Invocation, Result为中心,扩展接口为Protocol, Invoker, Exporter
选择

封装请求响应模式,同步转异步
以Request, Response为中心,扩展接口为Exchanger, ExchangeChannel,ExchangeClient, ExchangeServer
Netty

Mina

Grizzly

性能较好(推荐使用)
一次请求派发两种事件,需屏蔽无用事件
老牌NIO框架,稳定
待发送消息队列派发不及时,大压力下,会出现FullGC
Sun的NIO框架,应用于GlassFish服务器中
线程池不可扩展,Filter不能拦截下一Filter
抽象mina和netty为统一接口
以Message为中心,扩展接口为Channel, Transporter, Client, Server, Codec
选择

Hessian

Dubbo

Json

Java

性能较好,多语言支持(推荐使用)
Hessian的各版本兼容性不好,可能和应用使用的Hessian冲突,Dubbo内嵌了hessian3.2.1的源码
通过不传送POJO的类元信息,在大量POJO传输时,性能较好
当参数对象增加字段时,需外部文件声明
纯文本,可跨语言解析,缺省采用FastJson解析
性能较差
Java原生支持
性能较差
可复用的一些工具
扩展接口为Serialization, ObjectInput, ObjectOutput, ThreadPool
选择

Business

RPC

Remoting

Service
Config
Proxy
Registry
Cluster
Monitor
Protocol
Exchange
Transport
Serialize
层次结构

层说明


如何评价 Swift 语言

Swift是Apple在WWDC2014所发布的一门编程语言,用来撰写OS X和iOS应用程序[1]。在设计Swift时.就有意和Objective-C共存,Objective-C是Apple操作系统在导入Swift前使用的编程语言
Swift是供iOS和OS X应用编程的新编程语言,基于C和Objective-C,而却没有C的一些兼容约束。Swift采用了安全的编程模式和添加现代的功能来使得编程更加简单、灵活和有趣。界面则基于广受人民群众爱戴的Cocoa和Cocoa Touch框架,展示了软件开发的新方向。
2010 年 7 月LLVM 编译器的原作者暨苹果开发者工具部门总监克里斯·拉特纳(Chris Lattner)开始着手 Swift 编程语言的工作,还有一个 dogfooding 团队大力参与其中。至2014年6月发表,Swift大约历经4年的开发期。苹果宣称Swift的特点是:快速、现代、安全、互动,且全面优于Objective-C语言。Xcode Playgrounds功能是Swift为苹果开发工具带来的最大创新,该功能提供强大的互动效果,能让Swift源代码在撰写过程中能实时显示出其运行结果。拉特纳本人强调,Playgrounds很大程度是受到布雷特·维克多(Bret Victor)理念的启发。
JavaEye的创始人Robbin发表意见:“对程序员来说,熟悉Swift语法也不过一天时间足够了。关键是要提供高级数据类型,简化Cocoa类库,否则用不用Swift都没区别。”


如何评价 Swift 语言

先说结论(针对Swift 2.2):Swift把几种主流语言的优势糅合得非常好,是我见过的最漂亮最现代化的语言。
“几种语言的优势”指的是:
Objective C的运行时动态支持,和基于编译期引用计数的内存管理模型,
Ruby灵活优雅的语法,
C++的严格编译期检查,C++11编译期类型推导,模版(之所以说模版template,而不是范型generic,是因为Swift的范型实现依靠编译器更多些,而不像Java/C#依赖于运行时支持),
Javascript和Ruby的closure。
糅合的结果就是,写Swift带给你的极致体验是无与伦比的。
你可以轻松地像Javascript一样用closure写函数式编程,实现callback, aync, 以及类似Promise的代码风格;而同时,你又无需忍受Javascript那样稀烂的类型系统(JS连函数参数的个数都不检查)。语法上,Swift closure几乎和Ruby一样漂亮;Javascript写closure很啰嗦,Objective C写block更难看(那个C函数指针风格的block声明我就没搞清楚过,有码农为此专门写了个blog: Fucking Blocks Syntax),C++写closure?... 眼花。
更舒服的是,Swift通过引入nullable的概念,支持在编译期对nil值进行检查。这一举解决了Objective C因为对nil值过于灵活和宽容导致的问题。而通过optional chaining, 原来的灵活性依然保留。
除此之外,Swift还支持与Objective C混编,完美支持iOS/Mac的SDK。所以在老项目中,过渡到Swift的成本是比较低的。个人推荐老项目转向Swift可以从testcase开始写。
题主说Swift是“基于脚本的编程语言”,这个说法不太妥当。Swift是一门非常严格的编译语言,它的编译期类型检查要比Objective C和Java都要严格,更别提那些真正的脚本语言了。当然,Swift可以在Xcode Playground里即时编辑即时显示结果——那是苹果的黑科技,并不意味着Swift是脚本语言。性能上,Swift不输Objective C。
初学者关心好不好学这个问题。在此也给出明确答案:不好学。Swift不是一门初学者入门语言。不要抱着写Swift可以快速上手的浮躁心态入门iOS开发。


上一篇:国语版你是我的眼睛

下一篇:没有了