提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录一、Dubbo的功能二、Rpc比Http的优势三、Netty的优势四、Spi
1、Spi的优点
一、Dubbo的功能
拆分服务、屏蔽底层细节,解耦;减少Jar包大小服务治理(负载均衡、注册与发现、访问量统计、服务监控、灰度发布)
二、Rpc比Http的优势
| Rpc | Http | 所以 | |
|---|---|---|---|
| 序列化方式 | 针对二进制协议(如Hessian)做序列化与反序列化 | 基于文本,比如json | 编码后的二进制数据小了,存储空间的硬件成本小了,传输带宽小了,系统的吞吐量变大 |
| 传输协议 | 基于TCP|IP协议,分别是传输层和网络层 | 额外多了应用层、表示层、会话层 | 少了这三层 |
| 连接方式 | 长连接 | 大多都是短连接 | 减少了因为连接损耗的时间 |
三、Netty的优势
jdk nio类库与api繁杂,api使用简单,开发门槛低预置了很多编码功能,支持多种主流协议可以通过Channelhandler对通信框架进行灵活的扩展综合性能最优、已经修复了jdk已知的所有bug 四、Spi 1、Spi的优点
1 支持缓存,实例缓存在cacheInstances中,通过map获取
// key:extensionName,value:Instance private final ConcurrentMap> cachedInstances = new ConcurrentHashMap >(); public T getExtension(String name) { if (name == null || name.length() == 0) throw new IllegalArgumentException("Extension name == null"); if ("true".equals(name)) { return getDefaultExtension(); } // 这里查缓存里的instance Holder
2 Dubbo的SPI上有默认值
private String cachedDefaultName;
// synchronized in getExtensionClasses
private Map> loadExtensionClasses() {
final SPI defaultAnnotation = type.getAnnotation(SPI.class);
if (defaultAnnotation != null) {
String value = defaultAnnotation.value();
if ((value = value.trim()).length() > 0) {
String[] names = NAME_SEPARATOR.split(value);
if (names.length > 1) {
throw new IllegalStateException("more than 1 default extension name on extension " + type.getName()
+ ": " + Arrays.toString(names));
}
// 这里赋值,后面用于动态生成适配器里的代码
if (names.length == 1) cachedDefaultName = names[0];
}
}
Map> extensionClasses = new HashMap>();
loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY);
loadDirectory(extensionClasses, DUBBO_DIRECTORY);
loadDirectory(extensionClasses, SERVICES_DIRECTORY);
return extensionClasses;
}
3.支持AOP与IOC
private Set> cachedWrapperClasses; private void loadClass(Map > extensionClasses, java.net.URL resourceURL, Class> clazz, String name) throws NoSuchMethodException { ..... else if (isWrapperClass(clazz)) { // 1.1 刘峻峰 如果是包装类,会在这里先cache,当getExtension的时候,会把get到的实例再包装一层 Set > wrappers = cachedWrapperClasses; if (wrappers == null) { cachedWrapperClasses = new ConcurrentHashSet >(); wrappers = cachedWrapperClasses; } wrappers.add(clazz); } ..... } private T createExtension(String name) { ... if (wrapperClasses != null && !wrapperClasses.isEmpty()) { for (Class> wrapperClass : wrapperClasses) { // 1.2 刘峻峰 调用包装类的有参构造方法,把这些类再包装起来 instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance)); } } ... }



