<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Apache Dubbo – 版本发布</title><link>https://cn.dubbo.apache.org/zh/blog/news/releases/</link><description>Recent content in 版本发布 on Apache Dubbo</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><atom:link href="https://cn.dubbo.apache.org/zh/blog/news/releases/index.xml" rel="self" type="application/rss+xml"/><item><title>Blog: 2.7.14 发版公告</title><link>https://cn.dubbo.apache.org/zh/blog/2021/09/20/2.7.14-%E5%8F%91%E7%89%88%E5%85%AC%E5%91%8A/</link><pubDate>Mon, 20 Sep 2021 00:00:00 +0000</pubDate><guid>https://cn.dubbo.apache.org/zh/blog/2021/09/20/2.7.14-%E5%8F%91%E7%89%88%E5%85%AC%E5%91%8A/</guid><description>
&lt;h2 id="变动项">变动项&lt;/h2>
&lt;ul>
&lt;li>为 ServiceDiscovery 增加动态配置中心的覆盖规则。（#8389）&lt;/li>
&lt;li>修复当 mock 参数中包含 &amp;lsquo;:&amp;rsquo; 或者 &amp;lsquo;=&amp;rsquo; 符号时无法正常使用的问题。（#8379）&lt;/li>
&lt;li>修复 zone 参数对 ZoneAwareClusterInvoker 配置无法生效的问题。（#8521）&lt;/li>
&lt;li>为序列化白名单检查增加开关，默认为 true。（#8537）&lt;/li>
&lt;li>修复当请求超时时序列化检查的空指针异常。（#8587）&lt;/li>
&lt;li>修复 NetUtils.ignoreNetworkInterface 无法处理网卡中包含 &amp;lsquo;(&amp;rsquo; 符号的问题。（#8629）&lt;/li>
&lt;li>统一获取本地地址的方式。（#8679）&lt;/li>
&lt;li>修复当重试参数为0，依旧会重试1次的问题。（#8743）&lt;/li>
&lt;li>当清除未使用的 invoker 时，立即关闭客户端。（#8756）&lt;/li>
&lt;li>修复 destroy 方法以及 doOverrideIfNecessary 中的异常。（#8683）&lt;/li>
&lt;li>DefaultFuture.closeChannel 根据日志级别选择是否打印请求的详细数据。（#8778）&lt;/li>
&lt;li>使用 MapUtils 替换 AttachmentsAdapter（#8772）&lt;/li>
&lt;/ul>
&lt;h2 id="maven依赖变化">Maven依赖变化&lt;/h2>
&lt;ul>
&lt;li>netty4: 4.1.51.Final -&amp;gt; 4.1.66.Final&lt;/li>
&lt;li>netty4_ssl: 2.0.39.Final -&amp;gt; 2.0.40.Final&lt;/li>
&lt;li>http_client: 4.5.3 -&amp;gt; 4.5.13&lt;/li>
&lt;li>jetty: 9.4.11.v20180605 -&amp;gt; 9.4.43.v20210629&lt;/li>
&lt;li>apollo_client: 1.1.1 -&amp;gt; 1.8.0&lt;/li>
&lt;li>tomcat_embed: 8.5.31-&amp;gt; 9.0.48&lt;/li>
&lt;li>commons_io: 2.6 -&amp;gt; 2.7&lt;/li>
&lt;li>curator: 5.0.0 -&amp;gt; 5.1.0&lt;/li>
&lt;li>hessian_lite: 3.2.8 -&amp;gt; 3.2.11&lt;/li>
&lt;/ul></description></item><item><title>Blog: 3.0.2.1 发版公告</title><link>https://cn.dubbo.apache.org/zh/blog/2021/08/23/3.0.2.1-%E5%8F%91%E7%89%88%E5%85%AC%E5%91%8A/</link><pubDate>Mon, 23 Aug 2021 00:00:00 +0000</pubDate><guid>https://cn.dubbo.apache.org/zh/blog/2021/08/23/3.0.2.1-%E5%8F%91%E7%89%88%E5%85%AC%E5%91%8A/</guid><description>
&lt;p>这是 3.0.2 的错误修正版本。
除了以下更改外，与版本 3.0.2 完全相同。&lt;/p>
&lt;h2 id="bug-修复">Bug 修复&lt;/h2>
&lt;ul>
&lt;li>修复 nacos group 在消费者端不生效的问题 (#8533)&lt;/li>
&lt;li>修复请求超时时序列化检查的 NPE (#8547)&lt;/li>
&lt;li>兼容使用 dubbo-all 时未导入 farbic-io 包的问题 (#8546)&lt;/li>
&lt;/ul></description></item><item><title>Blog: 3.0.2 发版公告</title><link>https://cn.dubbo.apache.org/zh/blog/2021/08/18/3.0.2-%E5%8F%91%E7%89%88%E5%85%AC%E5%91%8A/</link><pubDate>Wed, 18 Aug 2021 00:00:00 +0000</pubDate><guid>https://cn.dubbo.apache.org/zh/blog/2021/08/18/3.0.2-%E5%8F%91%E7%89%88%E5%85%AC%E5%91%8A/</guid><description>
&lt;h2 id="新特性">新特性&lt;/h2>
&lt;ul>
&lt;li>支持通过 @DubboService 注解暴露泛化服务&lt;/li>
&lt;li>元数据中心xml格式的配置支持 protocol 和 port 属性&lt;/li>
&lt;li>兼容 curator5 以上的版本&lt;/li>
&lt;li>点对点调用支持*通配符进行匹配, 一个提供者地址可对应多个接口&lt;/li>
&lt;li>为应用级别的服务发现增加动态配置去进行规则覆盖&lt;/li>
&lt;li>对提供者测的动态配置覆盖规则提供开关，可以使提供者无视动态配置，不重新暴露&lt;/li>
&lt;li>支持 native image&lt;/li>
&lt;li>提供取消执行 shutdown hook 的开关&lt;/li>
&lt;li>支持 Kubernetes Mesh 的服务治理规则&lt;/li>
&lt;li>Netty 连接支持 SSL 配置&lt;/li>
&lt;/ul>
&lt;h2 id="bug-修复">Bug 修复&lt;/h2>
&lt;ul>
&lt;li>DubboBootStrap start 重复调用后，动态配置被覆盖&lt;/li>
&lt;li>动态配置规则被删除后，依然生效&lt;/li>
&lt;li>triple 协议在暴露时会抛出空指针异常&lt;/li>
&lt;li>ConfigCenterConfig.setAddress 方法会覆盖掉 username 属性&lt;/li>
&lt;li>DefaultFuture.closeChannel 会销毁掉消费端测的线程池&lt;/li>
&lt;li>TripleClientHandler.writeRequest 抛出空指针异常&lt;/li>
&lt;li>解析3.0迁移规则异常时会抛出空指针异常&lt;/li>
&lt;li>Activated Extensions 的顺序性问题&lt;/li>
&lt;li>URLAddress.parse 方法在解析 ipv6 地址时存在问题&lt;/li>
&lt;li>用户自定义的参数在 properties 配置中不生效&lt;/li>
&lt;li>同时使用 API 模式和 Spring 模式配置时属性，Config Id 存在覆盖问题&lt;/li>
&lt;li>应用级别服务发现在启动时不生效&lt;/li>
&lt;li>Nacos 注册中心无法动态感知提供者的数量变化&lt;/li>
&lt;li>${dubbo.application} 在 xml 文件中无法被 spring 的 placeholder 规则给解析替换&lt;/li>
&lt;li>获取实例参数的顺序问题，先去获取了实例级别参数，再去获取接口级别参数&lt;/li>
&lt;li>当 DubboConfigBeanInitializer 不存在时，注册应用启动监听器会抛出异常&lt;/li>
&lt;li>Mock 时 参数中包含 &amp;lsquo;:&amp;rsquo; 或者 &amp;lsquo;=&amp;rsquo; 字符时，不生效&lt;/li>
&lt;li>删除 Mesh 规则时空指针异常&lt;/li>
&lt;/ul>
&lt;h2 id="优化">优化&lt;/h2>
&lt;ul>
&lt;li>抓住 RemovalTask 的异常，保证信号量能够释放&lt;/li>
&lt;li>通过 唯一 service name 检查 ReferenceConfig/ServiceConfig 是否重复&lt;/li>
&lt;li>优化生成随机数的性能&lt;/li>
&lt;li>如果用户使用接口级别去做服务发现，不发布应用与接口的映射数据到元数据中心&lt;/li>
&lt;li>使用 StringBuilder#append(Char) 提升性能&lt;/li>
&lt;li>保证 GRPC 编译的类文件中接口的顺序&lt;/li>
&lt;li>优化 reference bean 的占位符解析&lt;/li>
&lt;li>MergeableClusterInvoker 中使用 CompletableFuture#get(long, TimeUnit) 去提升性能&lt;/li>
&lt;li>内置服务 MetadataService 不延迟暴露&lt;/li>
&lt;li>优化 ConfigBean 和 Bootstrap 的启动逻辑&lt;/li>
&lt;li>优化 Config 检查是否重复的逻辑&lt;/li>
&lt;li>使用 Ring 数据结构去进行注册通知&lt;/li>
&lt;li>优化动态配置的初始化逻辑&lt;/li>
&lt;li>ConfigManager 使用 ConcurrentHashMap 去移除锁逻辑，提升 equals 和 toString 性能&lt;/li>
&lt;li>优化 MetadataInfo equals 方法 以及 Instance Listener&lt;/li>
&lt;li>优化异步 export/refer 逻辑&lt;/li>
&lt;li>使用 TreeSet 数据结构保证应用级别服务发现时应用名称的顺序一致&lt;/li>
&lt;li>RegistryNotifier 的第一个十次通知不延迟&lt;/li>
&lt;li>dubbo-compile 编译使用新的格式生成 stub&lt;/li>
&lt;li>Mesh 服务治理规则在动态配置中心的分组和其他规则分组统一，由 DEFAULT_GROUP 改成 dubbo&lt;/li>
&lt;li>使用 nacos 用作注册中心时，可以在注册中心地址中使用参数来改变在 nacos 中的分组&lt;/li>
&lt;li>计算 ServiceInfo 的 reversion 时，移除运行时参数，避免生成多个 reversion&lt;/li>
&lt;li>Nacos 注册中心抛出异常时，将异常封装称 RpcException 抛出&lt;/li>
&lt;li>禁止动态配置中心对一些权限参数进行动态修改&lt;/li>
&lt;li>优化 Config Bean 的初始化流程，并兼容 spring 3.x/4.1.x&lt;/li>
&lt;li>Bootstrap.start 方法可重入，暴露或引用新的服务&lt;/li>
&lt;li>将 org.apache.dubbo 包中的类默认添加到白名单中&lt;/li>
&lt;li>保证生成的 Config 的 Id 唯一，并检查 Config 是否之前存在&lt;/li>
&lt;li>Javaassist 兼容改变 override 声明字段&lt;/li>
&lt;li>重构解码时的检查逻辑，当找不到 path, version 对应的提供者是，抛出异常&lt;/li>
&lt;li>当 ApplicationModel 为 null 时，兼容 adaptive extensions&lt;/li>
&lt;/ul>
&lt;h2 id="代码质量提升">代码质量提升&lt;/h2>
&lt;p>感谢以下提高 Apache Dubbo 的稳定性的贡献。&lt;/p>
&lt;p>&lt;a href="https://github.com/apache/dubbo/pull/8111">#8111&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8147">#8147&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8164">#8164&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8177">#8177&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8180">#8180&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8161">#8161&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8183">#8183&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8205">#8205&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8215">#8215&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8173">#8173&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8219">#8219&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8228">#8228&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8232">#8232&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8230">#8230&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8236">#8236&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8260">#8260&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8262">#8262&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8252">#8252&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8246">#8246&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8208">#8208&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8278">#8278&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8267">#8267&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8277">#8277&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8291">#8291&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8296">#8296&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8302">#8302&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8175">#8175&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8319">#8319&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8309">#8309&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8336">#8336&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8332">#8332&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8328">#8328&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8355">#8355&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8396">#8396&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8401">#8401&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8395">#8395&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8415">#8415&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8406">#8406&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8411">#8411&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8418">#8418&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8439">#8439&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8404">#8404&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8443">#8443&lt;/a>&lt;/p>
&lt;h2 id="maven依赖变化">Maven依赖变化&lt;/h2>
&lt;ul>
&lt;li>移除依赖: org.eclipse.collections:eclipse-collections&lt;/li>
&lt;li>移除依赖: com.google.guava:guava&lt;/li>
&lt;li>jetty: 9.4.11.v20180605 -&amp;gt; 9.4.43.v20210629&lt;/li>
&lt;li>apollo client: 1.1.1 -&amp;gt; 1.8.0&lt;/li>
&lt;li>snakeyaml: 1.20 -&amp;gt; 1.29&lt;/li>
&lt;li>tomcat embed: 8.5.31 -&amp;gt; 8.5.69&lt;/li>
&lt;li>nacos client: 2.0.0 -&amp;gt; 2.0.2&lt;/li>
&lt;li>swagger: 1.5.19 -&amp;gt; 1.5.24&lt;/li>
&lt;li>hessian_lite: 3.2.8 -&amp;gt; 3.2.11&lt;/li>
&lt;/ul></description></item><item><title>Blog: 3.0.1 发版公告</title><link>https://cn.dubbo.apache.org/zh/blog/2021/07/02/3.0.1-%E5%8F%91%E7%89%88%E5%85%AC%E5%91%8A/</link><pubDate>Fri, 02 Jul 2021 00:00:00 +0000</pubDate><guid>https://cn.dubbo.apache.org/zh/blog/2021/07/02/3.0.1-%E5%8F%91%E7%89%88%E5%85%AC%E5%91%8A/</guid><description>
&lt;h2 id="优化">优化&lt;/h2>
&lt;ul>
&lt;li>重构服务自省映射关系，支持地址迁移时直接配置上游应用名&lt;/li>
&lt;li>为 Spring 扫描添加缓存&lt;/li>
&lt;li>优化配置覆盖逻辑&lt;/li>
&lt;li>支持 Servlet 环境下控制 Dubbo 生命周期&lt;/li>
&lt;li>添加 ServiceListener 用于监听 ServiceConfig&lt;/li>
&lt;li>优化方法回调参数设置&lt;/li>
&lt;/ul>
&lt;h2 id="bug-修复">Bug 修复&lt;/h2>
&lt;ul>
&lt;li>启用强制校验&lt;/li>
&lt;li>更正多注册中心情况下，一个注册中心启动时无地址就销毁的逻辑&lt;/li>
&lt;li>移除冗余的日志输出&lt;/li>
&lt;li>忽略无效的 MetadataReportConfig&lt;/li>
&lt;li>修复消费端启动时 NPE 的情况&lt;/li>
&lt;li>修复若干和低版本兼容问题&lt;/li>
&lt;li>修复若干应用级服务发现逻辑存在的问题&lt;/li>
&lt;li>优化地址迁移规则，支持应用级地址重订阅&lt;/li>
&lt;li>修复 MetadataInfo 存在 NPE 的情况&lt;/li>
&lt;li>修复应用级注册到注册中心的实例信息被错误覆盖的问题&lt;/li>
&lt;/ul>
&lt;h2 id="代码质量提升">代码质量提升&lt;/h2>
&lt;p>感谢以下提高 Apache Dubbo 的稳定性的贡献。&lt;/p>
&lt;p>&lt;a href="https://github.com/apache/dubbo/pull/8043">#8043&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8044">#8044&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8048">#8048&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8071">#8071&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8119">#8119&lt;/a>,
&lt;a href="https://github.com/apache/dubbo/pull/8132">#8132&lt;/a>&lt;/p></description></item><item><title>Blog: dubbo-go 1.5.0</title><link>https://cn.dubbo.apache.org/zh/blog/2021/01/14/dubbo-go-1.5.0/</link><pubDate>Thu, 14 Jan 2021 00:00:00 +0000</pubDate><guid>https://cn.dubbo.apache.org/zh/blog/2021/01/14/dubbo-go-1.5.0/</guid><description>
&lt;h2 id="引语">引语&lt;/h2>
&lt;p>计算机技术浪潮每 10 年都有一次技术颠覆，相关知识体系最迟每 5 年都会革新一次，大概每两年贬值一半，在应用服务通信框架领域亦然。凡是有长期生命的通信框架，大概有 5 年的成长期和 5 年的稳定成熟期。每个时代都有其匹配的应用通信框架，在 20 年前的 2G 时代，强跨语言跨平台而弱性能的 gRPC 是不会被采用的。&lt;/p>
&lt;p>每个通信框架，不同的人从不同角度看出不同的结论：初学者看重易用易学，性能测评者注重性能，应用架构师考虑其维护成本，老板则考虑则综合成本。一个应用通信框架的性能固然重要，其稳定性和进化能力更重要，得到有效维护的框架可在长时间单位内降低其综合成本：学习成本、维护成本、升级成本和更换成本。&lt;/p>
&lt;p>什么是 Dubbo-go？第一，它是 Dubbo 的 Go 语言版本，全面兼容 Dubbo 是其第一要义。第二，它是一个 Go 语言应用通信框架，会充分利用作为云原生时代第一语言&amp;mdash;Go 语言的优势，扩展 dubbo 的能力。&lt;/p>
&lt;p>2008 年诞生的 Dubbo 已有十多年历史，依靠阿里和其社区，历久弥新。2016 年发布的 Dubbo-go 也已进入第五个年头，如今全面兼容 Dubbo v2.7.x 的 Dubbo-go v1.5 终于发布了。&lt;/p>
&lt;p>回首过往，Dubbo-go 已经具备如下能力：&lt;/p>
&lt;ul>
&lt;li>互联互通：打通了 gRPC 和 Spring Cloud 生态；&lt;/li>
&lt;li>可观测性：基于 OpenTracing 和 Prometheus，使得其在 Logging、Tracing 和 Metrics 方面有了长足进步；&lt;/li>
&lt;li>云原生：Dubbo-go 实现了基于 Kubernetes API Server 为注册中心的通信能力，做到了升级成本最低。&lt;/li>
&lt;/ul>
&lt;p>毋庸讳言，相较于现有成绩，发展阶段的 Dubbo-go 对未来有更多的期待之处：&lt;/p>
&lt;ul>
&lt;li>易用性：Dubbo-go 的入门成本并不低，把很多感兴趣者挡在了门外。但好消息是，随着 Dubbo-go 在阿里内部的逐步推开，阿里中间件团队对其进行了进一步的封装，经生产环境检验后会开放给社区使用。&lt;/li>
&lt;li>云原生：目前的 Dubbo-go 的基于 kubernetes 的方案，从技术分层角度来看， Kubernetes API Server 终究是系统的运维态组件，不应该暴露给应用层，否则会造成 APIServer 自身通信压力过大，且系统整体风险很高：应用层使用不当，或者框架自身的流量方面的 bug，可能会把 APIServer 打垮，后果就是造成整体后端服务能力的瘫痪！所以应用层需要感知的是 kubernetes 提供给应用层的 Operator，不断进化的 Dubbo-go 计划在 v1.6 版本中发布 Dubbo-go Operator。&lt;/li>
&lt;/ul>
&lt;p>雄关漫道真如铁，而今迈步从头越。Dubbo-go 社区【钉钉群 23331795】与 Dubbo-go 同在。&lt;/p>
&lt;h2 id="应用维度注册模型">应用维度注册模型&lt;/h2>
&lt;p>经过一段时间的努力之后，我们终于完成了应用维度的服务注册与发现。和原本已有的接口维度的注册模型比起来，新的注册模型有两个突出特点：&lt;/p>
&lt;ol>
&lt;li>和主流的注册模型保持一致。目前的主流做法都是按照应用为基本单位来进行注册的，如Spring Cloud。在支持应用维度注册之后，对于接下来的云原生支持，奠定了基础；&lt;/li>
&lt;li>大幅度减轻对注册中心的压力。在该模型之下，从注册中心的视角看过去，集群规模只和实例数量成正比，而不是现有的和服务数量成正比；&lt;/li>
&lt;/ol>
&lt;p>当然，我们在设计的时候就考虑到了用户的迁移成本。要迁移到新的注册模型，只需要将现有使用的注册中心换成新的 &lt;code>ServiceDiscoveryRegistry&lt;/code> 就可以。&lt;/p>
&lt;p>&lt;code>ServiceDiscoveryRegistry&lt;/code> 是支持多种实现的。目前来说，我们支持：&lt;/p>
&lt;ol>
&lt;li>nacos;&lt;/li>
&lt;li>etcd;&lt;/li>
&lt;li>zookeeper;&lt;/li>
&lt;/ol>
&lt;p>我们提倡新上线的业务尽量使用 nacos 和 etcd 这种更可靠稳定的注册中心。&lt;/p>
&lt;h2 id="metadata-report-元数据中心">Metadata Report 元数据中心&lt;/h2>
&lt;p>v1.5 版本在支持应用维度注册模型时，有很重要的一个问题需要解决，即接口维度的元数据存储。服务维度的注册模型和应用维度的注册模型，本质的区别是往注册中心注册的数据维度的不一致。虽然我们在应用维度注册模型中，将接口维度的数据从注册中心中剔除了，但是在rpc的框架中，一个 consumer 要想真正找到想要调用的服务地址，就必须得到 provider 端开放的服务信息。这部分数据，在 v1.5 版本中，我们将它们存储到了元数据中心中。&lt;/p>
&lt;p>元数据中心，是一个接口定义。泛指一块存储区域，可以对接口级别的元数据进行存储、读取，provider 端调用存储，consumer 端调用读取。元数据中心中的数据需要保持准确性、实时性。&lt;/p>
&lt;p>目前元数据中心，有两个父类（Go 中没有继承，此处说的父子类，单纯指子类对父类的组合关系）实现，一个是 local 实现，一个是 remote 实现。local 实现是将 provider 的内存作为虚拟元数据中心，remote 实现是指依赖 ZooKeeper、etcd、nacos 等注册中心作为元数据中心。目前 remote 有 zookeeper、nacos、etcd 和 consul 的子类实现。即用户可以将元数据信息，通过以上的第三方注册中心进行数据存储和分发。&lt;/p>
&lt;h2 id="invocation-接口支持-attribute-属性">Invocation 接口支持 attribute 属性&lt;/h2>
&lt;p>invocation 结构中新增 attribute 属性支持，用于流程内部的属性存储。和 attachment 不同点在于，attachment会从 consumer 传递到 provider，但 attribute 属性不会。&lt;/p>
&lt;h2 id="k8s注册中心">k8s注册中心&lt;/h2>
&lt;p>在 v1.5 版本之前，k8s 注册中心的实现是通过直接使用 &lt;a href="https://github.com/kubernetes/client-go">k8s client&lt;/a> 中Pod对象的 List&amp;amp;&amp;amp;Watch 接口。在本次迭代中引入了 k8s informer。这样做的原因在于两点，首先一定的程度上来讲 dubbo-go 的 k8s 注册中心也是一个 k8s controller，使用 informer 的模式更加 k8s native。更重要的是社区计划后续向 CRD+Operator 的模式演进，informer 模式是对后续的演进的探索。除了这个铺垫之外，本次迭代还对跨 namespace 的服务发现做了支持。再有就是为了减少对 kube-apiserver List&amp;amp;&amp;amp;Watch 的压力，对 provider 和 consumer 的行为进行了区分，provider 不再进行 Watch 而仅对 kube-apiserver 进行写操作。&lt;/p>
&lt;h1 id="优化路由模型">优化路由模型&lt;/h1>
&lt;p>在 1.5 版本之前，Router 模型中属性是包含：优先级与路由属性，Router Chain 只包含路由属性。从中能识别出其实 Router Chain 也是一种特殊 Router。1.5 版本之后，使 Router 更抽象，分离出其优先级属性，新增 Priority Router、Chain 继承 Router 使其变为特殊的 Router，使关系上看起来更加清晰。如下图：&lt;/p>
&lt;p>&lt;img src="https://cn.dubbo.apache.org/imgs/blog/dubbo-go/1.5/router.png" alt="">&lt;/p>
&lt;h1 id="回顾与展望">回顾与展望&lt;/h1>
&lt;p>Dubbo-go 处于一个比较稳定成熟的状态。目前新版本正处于往云原生方向的尝试，应用服务维度注册是首先推出的功能，这是一个和之前模型完全不一样的新注册模型。该版本是我们朝云原生迈进新一步的关键版本。除此之外，包含在该版本也有一些之前提到的优化。&lt;/p>
&lt;p>下一个版本 v1.5.1，虽然仍是以兼容 Dubbo 2.7.x 为主要任务，但在分布式能力的增强上，也是我们关注的重点。&lt;/p>
&lt;p>在&lt;strong>分布式事务&lt;/strong>方面，有一个重要的基于 Seata 扩展实现。通过增加过滤器，在服务端接收 xid 并结合 seata-golang&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup> 达到支持分布式事务的目的。 从而使 Dubbo-go 在分布式场景下，让用户有更多的选择，能适应更多的个性化场景。&lt;/p>
&lt;p>与此同时，在&lt;strong>传输链路安全性&lt;/strong>上，TLS 安全传输链路是该版本重要功能之一。通过提供统一入口，未来能引入更多的与传输链路安全性相关的功能，适应用户不一样的使用场景。&lt;/p>
&lt;p>&lt;strong>注册中心模型&lt;/strong>上，支持多注册中心集群负载均衡。业务部署假设是双注册中心（图 1 ），从原来双注册中心中所有 Provider 一起选址。优化成选址时的多了一层注册中心集群间的负载均衡（图 2 ）。&lt;/p>
&lt;p>&lt;img src="https://cn.dubbo.apache.org/imgs/blog/dubbo-go/1.5/multi-registry.png" alt="">&lt;/p>
&lt;p>（图 1 ）&lt;/p>
&lt;p>&lt;img src="https://cn.dubbo.apache.org/imgs/blog/dubbo-go/1.5/loadbalance.png" alt="">&lt;/p>
&lt;p>（图 2 ）&lt;/p>
&lt;p>以前的 dubbo-go RPC 层直接复用了 getty 框架 的 RPC[&lt;sup id="fnref:2">&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref">2&lt;/a>&lt;/sup>(https://github.com/AlexStocks/getty/tree/feature/rpc)]，未能实现协议和应用通信地址的隔离。阿里中间件展图同学重构了 dubbo-go RPC 层，实现了连接复用：可以实现 consumer 与 provider 端的同一个 TCP 连接上进行多协议通信。相关 PR 业已合并，会在 dubbo-go v1.5.1 中发布。&lt;/p>
&lt;p>目前下一个版本正在紧锣密鼓的开发中，具体规划及任务清单&lt;sup id="fnref:3">&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref">3&lt;/a>&lt;/sup> ，都已经在 Github 上体现。&lt;/p>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>&lt;a href="https://github.com/seata-golang/seata-golang">https://github.com/seata-golang/seata-golang&lt;/a>&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:2">
&lt;p>&lt;a href="https://github.com/AlexStocks/getty/tree/feature/rpc">https://github.com/AlexStocks/getty/tree/feature/rpc&lt;/a>&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:3">
&lt;p>&lt;a href="https://github.com/apache/dubbo-go/projects/8">https://github.com/apache/dubbo-go/projects/8&lt;/a>&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description></item><item><title>Blog: dubbo-go 1.5.1</title><link>https://cn.dubbo.apache.org/zh/blog/2021/01/14/dubbo-go-1.5.1/</link><pubDate>Thu, 14 Jan 2021 00:00:00 +0000</pubDate><guid>https://cn.dubbo.apache.org/zh/blog/2021/01/14/dubbo-go-1.5.1/</guid><description>
&lt;p>近期我们发布了 dubbo-go v1.5.1，虽然是 v1.5 的一个子版本，但相比于 v1.5.0， 社区还是投入了很大人力添加了如下重大改进。&lt;/p>
&lt;h2 id="1-应用维度注册模型">1 应用维度注册模型&lt;/h2>
&lt;p>在新模型 release 后，我们发现 Provider 每个 URL 发布元数据都会注册 ServiceInstance，影响性能需要优化。&lt;/p>
&lt;p>我们的优化方案是：&lt;/p>
&lt;p>去除 ServiceDiscoveryRegistry 中注册 ServiceInstance 的代码，在 config_loader 中的loadProviderConfig 方法的最后注册 ServiceInstance&lt;/p>
&lt;p>具体步骤：&lt;/p>
&lt;ol>
&lt;li>获取所有注册的 Registry，过滤出 ServiceDiscoveryRegistry，拿取所有 ServiceDiscovery。&lt;/li>
&lt;li>创建 ServiceInstance。&lt;/li>
&lt;li>每个 ServiceDiscovery 注册 ServiceInstance。&lt;/li>
&lt;/ol>
&lt;p>保证 Provider 在注册成功之后，才暴露元数据信息。&lt;/p>
&lt;h2 id="2-支持基于-seata-的事务">2 支持基于 Seata 的事务&lt;/h2>
&lt;p>基于 Seata 扩展实现。通过增加过滤器，在服务端接收 xid 并结合 &lt;a href="https://github.com/seata-golang/seata-golang">seata-golang&lt;/a> 达到支持分布式事务的目的。 从而使 Dubbo-go 在分布式场景下，让用户有更多的选择，能适应更多的个性化场景。&lt;/p>
&lt;p>我们在 dubbo-samples 中给出了 &lt;a href="https://github.com/apache/dubbo-go-samples/tree/1.5/seata">事务测试用例&lt;/a> 。&lt;/p>
&lt;h2 id="3-多注册中心集群负载均衡">3 多注册中心集群负载均衡&lt;/h2>
&lt;p>对于多注册中心订阅的场景，选址时的多了一层注册中心集群间的负载均衡：&lt;/p>
&lt;p>在 Cluster Invoker 这一级，我们支持的选址策略有：&lt;/p>
&lt;ul>
&lt;li>指定优先级&lt;/li>
&lt;li>同 zone 优先&lt;/li>
&lt;li>权重轮询&lt;/li>
&lt;/ul>
&lt;h2 id="4-传输链路安全性">4 传输链路安全性&lt;/h2>
&lt;p>该版本在传输链路的安全性上做了尝试，对于内置的 Dubbo getty Server 提供了基于 TLS 的安全链路传输机制。&lt;/p>
&lt;p>为尽可能保证应用启动的灵活性，TLS Cert 的指定通过配置文件方式，具体请参见 Dubbo-go 配置读取规则与 TLS 示例：&lt;/p>
&lt;h2 id="5-路由功能增强">5 路由功能增强&lt;/h2>
&lt;p>本次路由功能重点支持了 动态标签路由 和 应用/服务级条件路由。&lt;/p>
&lt;h3 id="51-动态标签路由">5.1 动态标签路由&lt;/h3>
&lt;p>标签路由通过将某一个或多个服务的提供者划分到同一个分组，约束流量只在指定分组中流转，从而实现流量隔离的目的，可以作为蓝绿发布、灰度发布等场景的能力基础。&lt;/p>
&lt;p>标签主要是指对 Provider 端应用实例的分组，目前有两种方式可以完成实例分组，分别是&lt;code>动态规则打标&lt;/code>和&lt;code>静态规则打标&lt;/code>，其中动态规则相较于静态规则优先级更高，而当两种规则同时存在且出现冲突时，将以动态规则为准。&lt;/p>
&lt;h4 id="511-动态规则打标">5.1.1 动态规则打标&lt;/h4>
&lt;p>可随时在&lt;a href="https://cn.dubbo.apache.org/zh/docsv2.7/user/examples/routing-rule/">服务治理控制台&lt;/a>下发标签归组规则&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75"># governance-tagrouter-provider应用增加了两个标签分组tag1和tag2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75"># tag1包含一个实例 127.0.0.1:20880&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75"># tag2包含一个实例 127.0.0.1:20881&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>---
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">force&lt;/span>: &lt;span style="color:#cb4b16">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">runtime&lt;/span>: &lt;span style="color:#cb4b16">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">enabled&lt;/span>: &lt;span style="color:#cb4b16">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">key&lt;/span>: governance-tagrouter-provider
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">tags&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#268bd2">name&lt;/span>: tag1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">addresses&lt;/span>: [&lt;span style="color:#2aa198">&amp;#34;127.0.0.1:20880&amp;#34;&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#268bd2">name&lt;/span>: tag2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">addresses&lt;/span>: [&lt;span style="color:#2aa198">&amp;#34;127.0.0.1:20881&amp;#34;&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ...
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="512-静态规则打标">5.1.2 静态规则打标&lt;/h4>
&lt;p>可以在 server 配置文件的 tag 字段里设置&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">services&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#2aa198">&amp;#34;UserProvider&amp;#34;&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">registry&lt;/span>: &lt;span style="color:#2aa198">&amp;#34;hangzhouzk&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">protocol &lt;/span>: &lt;span style="color:#2aa198">&amp;#34;dubbo&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">interface &lt;/span>: &lt;span style="color:#2aa198">&amp;#34;com.ikurento.user.UserProvider&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">loadbalance&lt;/span>: &lt;span style="color:#2aa198">&amp;#34;random&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">warmup&lt;/span>: &lt;span style="color:#2aa198">&amp;#34;100&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">tag&lt;/span>: &lt;span style="color:#2aa198">&amp;#34;beijing&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">cluster&lt;/span>: &lt;span style="color:#2aa198">&amp;#34;failover&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">methods&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#268bd2">name&lt;/span>: &lt;span style="color:#2aa198">&amp;#34;GetUser&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">retries&lt;/span>: &lt;span style="color:#2aa198">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">loadbalance&lt;/span>: &lt;span style="color:#2aa198">&amp;#34;random&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>consumer 添加 tag 至 attachment 即可&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>ctx &lt;span style="color:#719e07">:=&lt;/span> context.&lt;span style="color:#268bd2">Background&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>attachment &lt;span style="color:#719e07">:=&lt;/span> &lt;span style="color:#b58900">make&lt;/span>(&lt;span style="color:#268bd2">map&lt;/span>[&lt;span style="color:#dc322f">string&lt;/span>]&lt;span style="color:#dc322f">string&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>attachment[&lt;span style="color:#2aa198">&amp;#34;dubbo.tag&amp;#34;&lt;/span>] = &lt;span style="color:#2aa198">&amp;#34;beijing&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ctx = context.&lt;span style="color:#268bd2">WithValue&lt;/span>(ctx, constant.AttachmentKey, attachment)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>err &lt;span style="color:#719e07">:=&lt;/span> userProvider.&lt;span style="color:#268bd2">GetUser&lt;/span>(ctx, []&lt;span style="color:#268bd2">interface&lt;/span>{}{&lt;span style="color:#2aa198">&amp;#34;A001&amp;#34;&lt;/span>}, user)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>请求标签的作用域为每一次 invocation，使用 attachment 来传递请求标签，注意保存在 attachment 中的值将会在一次完整的远程调用中持续传递，得益于这样的特性，我们只需要在起始调用时，通过一行代码的设置，达到标签的持续传递。&lt;/p>
&lt;h4 id="513-规则详解">5.1.3 规则详解&lt;/h4>
&lt;h5 id="格式">格式&lt;/h5>
&lt;ul>
&lt;li>&lt;code>Key&lt;/code>明确规则体作用到哪个应用。&lt;strong>必填&lt;/strong>。&lt;/li>
&lt;li>&lt;code>enabled=true&lt;/code> 当前路由规则是否生效，可不填，缺省生效。&lt;/li>
&lt;li>&lt;code>force=false&lt;/code> 当路由结果为空时，是否强制执行，如果不强制执行，路由结果为空的路由规则将自动失效，可不填，缺省为 &lt;code>false&lt;/code>。&lt;/li>
&lt;li>&lt;code>runtime=false&lt;/code> 是否在每次调用时执行路由规则，否则只在提供者地址列表变更时预先执行并缓存结果，调用时直接从缓存中获取路由结果。如果用了参数路由，必须设为 &lt;code>true&lt;/code>，需要注意设置会影响调用的性能，可不填，缺省为 &lt;code>false&lt;/code>。&lt;/li>
&lt;li>&lt;code>priority=1&lt;/code> 路由规则的优先级，用于排序，优先级越大越靠前执行，可不填，缺省为 &lt;code>0&lt;/code>。&lt;/li>
&lt;li>&lt;code>tags&lt;/code> 定义具体的标签分组内容，可定义任意n（n&amp;gt;=1）个标签并为每个标签指定实例列表。&lt;strong>必填&lt;/strong>&lt;/li>
&lt;li>
&lt;ul>
&lt;li>name， 标签名称&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>addresses， 当前标签包含的实例列表&lt;/li>
&lt;/ul>
&lt;h5 id="降级约定">降级约定&lt;/h5>
&lt;ol>
&lt;li>&lt;code>dubbo.tag=tag1&lt;/code> 时优先选择 标记了 &lt;code>tag=tag1&lt;/code> 的 provider。若集群中不存在与请求标记对应的服务，默认将降级请求 tag 为空的 provider；如果要改变这种默认行为，即找不到匹配 tag1 的 provider 返回异常，需设置&lt;code>dubbo.force.tag=true&lt;/code>。&lt;/li>
&lt;li>&lt;code>dubbo.tag&lt;/code> 未设置时，只会匹配 tag 为空的 provider。即使集群中存在可用的服务，若 tag 不匹配也就无法调用，这与约定 1 不同，携带标签的请求可以降级访问到无标签的服务，但不携带标签/携带其他种类标签的请求永远无法访问到其他标签的服务。&lt;/li>
&lt;/ol>
&lt;h3 id="52-应用服务级条件路由">5.2 应用/服务级条件路由&lt;/h3>
&lt;p>您可以在路由规则配置中配置多个条件路由及其粒度&lt;/p>
&lt;p>Sample:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75"># dubbo router yaml configure file&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">routerRules&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#268bd2">scope&lt;/span>: application
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">key&lt;/span>: BDTService
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">priority&lt;/span>: &lt;span style="color:#2aa198">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">enable&lt;/span>: &lt;span style="color:#cb4b16">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">force&lt;/span>: &lt;span style="color:#cb4b16">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">conditions &lt;/span>: [&lt;span style="color:#2aa198">&amp;#34;host = 192.168.199.208 =&amp;gt; host = 192.168.199.208 &amp;#34;&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#268bd2">scope&lt;/span>: service
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">key&lt;/span>: com.ikurento.user.UserProvider
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">priority&lt;/span>: &lt;span style="color:#2aa198">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">force&lt;/span>: &lt;span style="color:#cb4b16">true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">conditions &lt;/span>: [&lt;span style="color:#2aa198">&amp;#34;host = 192.168.199.208 =&amp;gt; host = 192.168.199.208 &amp;#34;&lt;/span>]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="521-规则详解">5.2.1 规则详解&lt;/h4>
&lt;h5 id="各字段含义">各字段含义&lt;/h5>
&lt;ul>
&lt;li>scope表示路由规则的作用粒度，scope的取值会决定key的取值。必填。&lt;/li>
&lt;li>
&lt;ul>
&lt;li>service 服务粒度&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>application 应用粒度&lt;/li>
&lt;li>Key明确规则体作用在哪个服务或应用。必填。&lt;/li>
&lt;li>
&lt;ul>
&lt;li>scope=service时，key取值为[{group}/]{service}[:{version}]的组合&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>scope=application时，key取值为application名称&lt;/li>
&lt;li>enabled=true 当前路由规则是否生效，可不填，缺省生效。&lt;/li>
&lt;li>force=false 当路由结果为空时，是否强制执行，如果不强制执行，路由结果为空的路由规则将自动失效，可不填，缺省为 false。&lt;/li>
&lt;li>runtime=false 是否在每次调用时执行路由规则，否则只在提供者地址列表变更时预先执行并缓存结果，调用时直接从缓存中获取路由结果。如果用了参数路由，必须设为 true，需要注意设置会影响调用的性能，可不填，缺省为 false。&lt;/li>
&lt;li>priority=1 路由规则的优先级，用于排序，优先级越大越靠前执行，可不填，缺省为 0。&lt;/li>
&lt;li>conditions 定义具体的路由规则内容。必填。&lt;/li>
&lt;/ul>
&lt;h2 id="6-回顾与展望">6 回顾与展望&lt;/h2>
&lt;p>Dubbo-go 处于一个比较稳定成熟的状态。目前新版本正处于往云原生方向的尝试，应用服务维度注册是首先推出的功能，这是一个和之前模型完全不一样的新注册模型。该版本是我们朝云原生迈进新一步的关键版本。除此之外，包含在该版本也有一些之前提到的优化。&lt;/p>
&lt;p>下一个版本 v1.5.2，本次的关注重点以通信模型改进为主，除此之外，与 2.7.x 的兼容性、易用性及质量保证也是本次关注的信息。&lt;/p>
&lt;p>在&lt;strong>服务发现&lt;/strong>，会支持更加多的方式，如：文件、Consul。 从而使 Dubbo-go 在服务发现场景下，让用户有更多的选择，能适应更多的个性化场景。&lt;/p>
&lt;p>另外 &lt;strong>易用性及质量保证&lt;/strong>，主要关注的是 samples 与自动化构建部分。可降低用户上手 Dubbo-go 的难度，提高代码质量。&lt;/p>
&lt;p>目前下一个版本正在紧锣密鼓的开发中，具体规划及任务清单&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup> ，都已经在 Github 上体现。&lt;/p>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>&lt;a href="https://github.com/apache/dubbo-go/projects/10">https://github.com/apache/dubbo-go/projects/10&lt;/a>&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description></item><item><title>Blog: dubbo-go-hessian2 v1.6.0</title><link>https://cn.dubbo.apache.org/zh/blog/2021/01/14/dubbo-go-hessian2-v1.6.0/</link><pubDate>Thu, 14 Jan 2021 00:00:00 +0000</pubDate><guid>https://cn.dubbo.apache.org/zh/blog/2021/01/14/dubbo-go-hessian2-v1.6.0/</guid><description>
&lt;h2 id="1-增加缓存优化">1. 增加缓存优化&lt;/h2>
&lt;p>dubbo-go-hessian2 在解析数据的数据大量使用到了 struct 的结构信息，这部分信息可以缓存起来反复利用，使得性能提升了一倍。优化过程记录可以详细阅读&lt;a href="https://mp.weixin.qq.com/s/ouVxldQAt0_4BET7srjJ6Q">《记一次对 dubbo-go-hessian2 的性能优化》&lt;/a>.&lt;/p>
&lt;p>对应 pr &lt;a href="https://github.com/apache/dubbo-go-hessian2/pull/179">#179&lt;/a>，作者 &lt;a href="https://github.com/micln">micln&lt;/a>。&lt;/p>
&lt;h2 id="2-string-解析性能优化">2. string 解析性能优化&lt;/h2>
&lt;p>由于 hessian （ dubbo 序列化协议，下称：hessian ）对 string 的定义是16 bit 的 unicode 的 UTF-8 表示形式，字符长度表示是16 bit 的字符数。这是仅针对 java 制定的规范，java 中一个字符是16 bit，对应到 UTF-16. hessian 库也是对每一个字符进行转码序列化。但 golang 里面字符是和 UTF-8 对应的，dubbo-go-hessian2 里面的 rune 是 32bit，和 unicode一一映射。对于 U+10000 ~ U+10FFFF 的字符，需按照 UTF16 的规范，将字符转换为 2 个字节的代理字符，再做转换，才能和 java 的序列化方式对应起来。&lt;/p>
&lt;p>原来不管是编码还是解析都是一个字符一个字符处理，特别是解析的时候，从流里面一个字节一个字节读取并组装成 rune，然后再转换为 string，这样效率特别低。我们的优化方案是，批次读取字节流到 buffer 中，对 buffer 进行解析转为 UTF-8 数组，并统计字符数量。其中需要对代理对字符将其转换为标准 UTF-8 子节数组。如果统计的字符数量不足，再进一步读取流种的数据进行解析。通过此方式提升一倍的解析效率。&lt;/p>
&lt;p>对应 pr &lt;a href="https://github.com/apache/dubbo-go-hessian2/pull/188">#188&lt;/a>，作者 &lt;a href="https://github.com/zonghaishang">zonghaishang&lt;/a>。&lt;/p>
&lt;h2 id="3-解析忽略不存在的字段">3. 解析忽略不存在的字段&lt;/h2>
&lt;p>hessian 库在解析数据的时候，对于一个 class 字段，如果不存在，则直接忽略掉。但 v1.6.0 版本之前 dubbo-go-hessian2 解析数据，如果遇到不存在的字段，会返回 error。从 v1.6.0 开始，与 hessian 一样，忽略不存在的字段。&lt;strong>因为这是一个特性的变更，所以升级的同学一定要注意了。&lt;/strong>&lt;/p>
&lt;p>对应 pr &lt;a href="https://github.com/apache/dubbo-go-hessian2/pull/201">#201&lt;/a>，作者 &lt;a href="https://github.com/micln">micln&lt;/a> &amp;amp; &lt;a href="https://github.com/fangyincheng">fangyincheng&lt;/a>。&lt;/p>
&lt;h2 id="4-解决浮点数精度丢失问题">4. 解决浮点数精度丢失问题&lt;/h2>
&lt;p>在对 float32 类型进行序列化时，我们一律强制转换为 float64 再进行序列化操作。由于浮点数的精度问题，在这个转换过程中可能出现小数点后出现多余的尾数，例如 (float32)99.8&amp;ndash;&amp;gt;(float64)99.80000305175781。&lt;/p>
&lt;p>1.6.0 版本对 float32 的序列化进行了优化：&lt;/p>
&lt;ul>
&lt;li>如果小数尾数小于 3 位，根据 hessian2 协议序列化为 double 32-bit 格式&lt;/li>
&lt;li>否则先转换为 string 类型，再转换为 float64 类型，这样做可以避免由于浮点数精度问题产生多余的尾数，最后对 float64 进行序列化。&lt;/li>
&lt;/ul>
&lt;p>虽然对 float32 类型进行了优化，但是依然建议使用浮点数的时候优先使用 float64 类型。&lt;/p>
&lt;p>对应 pr &lt;a href="https://github.com/apache/dubbo-go-hessian2/pull/196">#196&lt;/a>，作者 &lt;a href="https://github.com/willson-chen">willson-chen&lt;/a>。&lt;/p>
&lt;h2 id="5-解决-attachment-空值丢失问题">5. 解决 attachment 空值丢失问题&lt;/h2>
&lt;p>dubbo 请求中包含 attachment 信息，之前如果 attachment 里面含有如 &lt;code>&amp;quot;key1&amp;quot;:&amp;quot;&amp;quot;&lt;/code>，这种 value 为空的情况，解析出来的结果会直接丢失这个属性 key1 ，v1.6.0 修复了此问题，现在解析出来的 attachment 会正确解析出空 value 的属性。&lt;/p>
&lt;p>对应 pr &lt;a href="https://github.com/apache/dubbo-go-hessian2/pull/191">#191&lt;/a>，作者 &lt;a href="https://github.com/champly">champly&lt;/a>。&lt;/p>
&lt;h2 id="6-支持-继承-和忽略冗余字段">6. 支持 ‘继承’ 和忽略冗余字段&lt;/h2>
&lt;p>由于 go 没有继承的概念，所以在之前的版本，Java 父类的字段不被 dubbo-go-hessian2 所支持。新版本中，dubbo-go-hessian2 将Java来自父类的字段用匿名结构体对应，如：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">type&lt;/span> Dog &lt;span style="color:#268bd2">struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Animal
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Gender &lt;span style="color:#dc322f">string&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> DogName &lt;span style="color:#dc322f">string&lt;/span> &lt;span style="color:#2aa198">`hessian:&amp;#34;-&amp;#34;`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>同时，就像 json 编码中通过 immediately 可以在序列化中忽略该字段，同理，通过 hessian:&amp;quot;-&amp;quot; 用户也可以让冗余字段不参与 hessian 序列化。&lt;/p>
&lt;p>对应pr &lt;a href="https://github.com/apache/dubbo-go-hessian2/pull/154">#154&lt;/a>，作者 &lt;a href="https://github.com/micln">micln&lt;/a>&lt;/p></description></item><item><title>Blog: dubbo-go-hessian2 v1.7.0</title><link>https://cn.dubbo.apache.org/zh/blog/2021/01/14/dubbo-go-hessian2-v1.7.0/</link><pubDate>Thu, 14 Jan 2021 00:00:00 +0000</pubDate><guid>https://cn.dubbo.apache.org/zh/blog/2021/01/14/dubbo-go-hessian2-v1.7.0/</guid><description>
&lt;p>Dubbo-go-hessian2 v1.7.0已发布，详见 &lt;a href="https://github.com/apache/dubbo-go-hessian2/releases/tag/v1.7.0">https://github.com/apache/dubbo-go-hessian2/releases/tag/v1.7.0&lt;/a>， 以下对这次更新内容进行详细整理。&lt;/p>
&lt;p>另外v1.6.3 将 attachment 类型由 map[string]stiring 改为map[string]interface{} 导致版本不兼容问题，这部分已还原，后续的计划是将dubbo协议的request/response对象整体迁移到dubbogo项目中进行迭代修改， hessian2中将不再改动到request/response对象。&lt;/p>
&lt;h2 id="1-new-features">1. New Features&lt;/h2>
&lt;h3 id="11-add-getstacktrace-method-into-throwabler-and-its-implements-207httpsgithubcomapachedubbo-go-hessian2pull207">1.1 add GetStackTrace method into Throwabler and its implements. &lt;a href="https://github.com/apache/dubbo-go-hessian2/pull/207">#207&lt;/a>&lt;/h3>
&lt;p>go语言client请求java语言服务时，如果java语言抛出了异常，异常对应的堆栈信息是被保存在StackTraceElement中。&lt;/p>
&lt;p>这个异常信息在日志中最好能被打印出来，以方便客户端排查问题，所以在Throwabler和对应子类中增加了StackTraceElement的获取。&lt;/p>
&lt;p>注：其实还有一种更好的方法，所有的具体的异常类型都包含java_exception/exception.go的Throwable struct。这样只需要在Throwable中增加GetStackTrace方法就可以了。但是这种方式需要更多的测试验证，改动的逻辑相对会复杂一些。但是代码会更整洁。 这里先不用这种方法。&lt;/p>
&lt;h3 id="12-catch-user-defined-exceptions-208httpsgithubcomapachedubbo-go-hessian2pull208">1.2 catch user defined exceptions. &lt;a href="https://github.com/apache/dubbo-go-hessian2/pull/208">#208&lt;/a>&lt;/h3>
&lt;p>golang中增加一个java中Exception对象的序列化输出方法：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">func&lt;/span> &lt;span style="color:#268bd2">JavaException&lt;/span>() []&lt;span style="color:#dc322f">byte&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> e &lt;span style="color:#719e07">:=&lt;/span> hessian.&lt;span style="color:#268bd2">NewEncoder&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> exception &lt;span style="color:#719e07">:=&lt;/span> java_exception.&lt;span style="color:#268bd2">NewException&lt;/span>(&lt;span style="color:#2aa198">&amp;#34;java_exception&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> e.&lt;span style="color:#268bd2">Encode&lt;/span>(exception)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">return&lt;/span> e.&lt;span style="color:#268bd2">Buffer&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>在output/output.go 提供调用入口:添加如下函数初始化声明&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">func&lt;/span> &lt;span style="color:#268bd2">init&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> funcMap[&lt;span style="color:#2aa198">&amp;#34;JavaException&amp;#34;&lt;/span>] = testfuncs.JavaException
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>java代码中增加调用go方法序列化结果:&lt;/p>
&lt;p>&lt;strong>说明&lt;/strong>: Assert.assertEquals 不能直接比较Exception对象是否相等&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span> &lt;span style="color:#586e75">/**
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75"> * test java java.lang.Exception object and go java_exception Exception struct
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75"> */&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">@Test&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">public&lt;/span> &lt;span style="color:#dc322f">void&lt;/span> &lt;span style="color:#268bd2">testException&lt;/span>&lt;span style="color:#719e07">()&lt;/span> &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Exception exception &lt;span style="color:#719e07">=&lt;/span> &lt;span style="color:#719e07">new&lt;/span> Exception&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#2aa198">&amp;#34;java_exception&amp;#34;&lt;/span>&lt;span style="color:#719e07">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Object javaException &lt;span style="color:#719e07">=&lt;/span> GoTestUtil&lt;span style="color:#719e07">.&lt;/span>readGoObject&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#2aa198">&amp;#34;JavaException&amp;#34;&lt;/span>&lt;span style="color:#719e07">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">if&lt;/span> &lt;span style="color:#719e07">(&lt;/span>javaException &lt;span style="color:#719e07">instanceof&lt;/span> Exception&lt;span style="color:#719e07">)&lt;/span> &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Assert&lt;span style="color:#719e07">.&lt;/span>assertEquals&lt;span style="color:#719e07">(&lt;/span>exception&lt;span style="color:#719e07">.&lt;/span>getMessage&lt;span style="color:#719e07">(),&lt;/span> &lt;span style="color:#719e07">((&lt;/span>Exception&lt;span style="color:#719e07">)&lt;/span> javaException&lt;span style="color:#719e07">).&lt;/span>getMessage&lt;span style="color:#719e07">());&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="13-support-java8-time-object-212httpsgithubcomapachedubbo-go-hessian2pull212-221httpsgithubcomapachedubbo-go-hessian2pull221">1.3 support java8 time object. &lt;a href="https://github.com/apache/dubbo-go-hessian2/pull/212">#212&lt;/a>, &lt;a href="https://github.com/apache/dubbo-go-hessian2/pull/221">#221&lt;/a>&lt;/h3>
&lt;p>golang中增加一个java8对象的序列化输出方法：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">// test java8 java.time.Year
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">&lt;/span>&lt;span style="color:#268bd2">func&lt;/span> &lt;span style="color:#268bd2">Java8TimeYear&lt;/span>() []&lt;span style="color:#dc322f">byte&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> e &lt;span style="color:#719e07">:=&lt;/span> hessian.&lt;span style="color:#268bd2">NewEncoder&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> year &lt;span style="color:#719e07">:=&lt;/span> java8_time.Year{Year: &lt;span style="color:#2aa198">2020&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> e.&lt;span style="color:#268bd2">Encode&lt;/span>(year)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">return&lt;/span> e.&lt;span style="color:#268bd2">Buffer&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">// test java8 java.time.LocalDate
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">&lt;/span>&lt;span style="color:#268bd2">func&lt;/span> &lt;span style="color:#268bd2">Java8LocalDate&lt;/span>() []&lt;span style="color:#dc322f">byte&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> e &lt;span style="color:#719e07">:=&lt;/span> hessian.&lt;span style="color:#268bd2">NewEncoder&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> date &lt;span style="color:#719e07">:=&lt;/span> java8_time.LocalDate{Year: &lt;span style="color:#2aa198">2020&lt;/span>, Month: &lt;span style="color:#2aa198">9&lt;/span>, Day: &lt;span style="color:#2aa198">12&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> e.&lt;span style="color:#268bd2">Encode&lt;/span>(date)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">return&lt;/span> e.&lt;span style="color:#268bd2">Buffer&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>在output/output.go 提供调用入口:添加函数初始化声明&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">func&lt;/span> &lt;span style="color:#268bd2">init&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> funcMap[&lt;span style="color:#2aa198">&amp;#34;Java8TimeYear&amp;#34;&lt;/span>] = testfuncs.Java8TimeYear
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> funcMap[&lt;span style="color:#2aa198">&amp;#34;Java8LocalDate&amp;#34;&lt;/span>] = testfuncs.Java8LocalDate
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>java代码中增加调用go方法序列化结果:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">/**
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75"> * test java8 java.time.* object and go java8_time/* struct
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75"> */&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">@Test&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">public&lt;/span> &lt;span style="color:#dc322f">void&lt;/span> &lt;span style="color:#268bd2">testJava8Year&lt;/span>&lt;span style="color:#719e07">()&lt;/span> &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Year year &lt;span style="color:#719e07">=&lt;/span> Year&lt;span style="color:#719e07">.&lt;/span>of&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#2aa198">2020&lt;/span>&lt;span style="color:#719e07">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Assert&lt;span style="color:#719e07">.&lt;/span>assertEquals&lt;span style="color:#719e07">(&lt;/span>year
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">,&lt;/span> GoTestUtil&lt;span style="color:#719e07">.&lt;/span>readGoObject&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#2aa198">&amp;#34;Java8TimeYear&amp;#34;&lt;/span>&lt;span style="color:#719e07">));&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> LocalDate localDate &lt;span style="color:#719e07">=&lt;/span> LocalDate&lt;span style="color:#719e07">.&lt;/span>of&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#2aa198">2020&lt;/span>&lt;span style="color:#719e07">,&lt;/span> &lt;span style="color:#2aa198">9&lt;/span>&lt;span style="color:#719e07">,&lt;/span> &lt;span style="color:#2aa198">12&lt;/span>&lt;span style="color:#719e07">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Assert&lt;span style="color:#719e07">.&lt;/span>assertEquals&lt;span style="color:#719e07">(&lt;/span>localDate&lt;span style="color:#719e07">,&lt;/span> GoTestUtil&lt;span style="color:#719e07">.&lt;/span>readGoObject&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#2aa198">&amp;#34;Java8LocalDate&amp;#34;&lt;/span>&lt;span style="color:#719e07">));&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="14-support-test-golang-encoding-data-in-java-213httpsgithubcomapachedubbo-go-hessian2pull213">1.4 support test golang encoding data in java. &lt;a href="https://github.com/apache/dubbo-go-hessian2/pull/213">#213&lt;/a>&lt;/h3>
&lt;p>为了更好的测试验证hessian库，原来已经支持在golang中测试java的序列化数据，现在增加在java中测试golang的序列化数据，实现双向测试验证。&lt;/p>
&lt;p>golang中增加序列化输出方法:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">func&lt;/span> &lt;span style="color:#268bd2">HelloWorldString&lt;/span>() []&lt;span style="color:#dc322f">byte&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> e &lt;span style="color:#719e07">:=&lt;/span> hessian.&lt;span style="color:#268bd2">NewEncoder&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> e.&lt;span style="color:#268bd2">Encode&lt;/span>(&lt;span style="color:#2aa198">&amp;#34;hello world&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">return&lt;/span> e.&lt;span style="color:#268bd2">Buffer&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>将该方法注册到output/output.go中&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span> &lt;span style="color:#586e75">// add all output func here
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">&lt;/span> &lt;span style="color:#268bd2">func&lt;/span> &lt;span style="color:#268bd2">init&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> funcMap[&lt;span style="color:#2aa198">&amp;#34;HelloWorldString&amp;#34;&lt;/span>] = testfuncs.HelloWorldString
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>output/output.go 提供调用入口:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">func&lt;/span> &lt;span style="color:#268bd2">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> flag.&lt;span style="color:#268bd2">Parse&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">if&lt;/span> &lt;span style="color:#719e07">*&lt;/span>funcName &lt;span style="color:#719e07">==&lt;/span> &lt;span style="color:#2aa198">&amp;#34;&amp;#34;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> _, _ = fmt.&lt;span style="color:#268bd2">Fprintln&lt;/span>(os.Stderr, &lt;span style="color:#2aa198">&amp;#34;func name required&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> os.&lt;span style="color:#268bd2">Exit&lt;/span>(&lt;span style="color:#2aa198">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> f, exist &lt;span style="color:#719e07">:=&lt;/span> funcMap[&lt;span style="color:#719e07">*&lt;/span>funcName]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">if&lt;/span> !exist {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> _, _ = fmt.&lt;span style="color:#268bd2">Fprintln&lt;/span>(os.Stderr, &lt;span style="color:#2aa198">&amp;#34;func name not exist: &amp;#34;&lt;/span>, &lt;span style="color:#719e07">*&lt;/span>funcName)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> os.&lt;span style="color:#268bd2">Exit&lt;/span>(&lt;span style="color:#2aa198">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">defer&lt;/span> &lt;span style="color:#268bd2">func&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">if&lt;/span> err &lt;span style="color:#719e07">:=&lt;/span> &lt;span style="color:#b58900">recover&lt;/span>(); err &lt;span style="color:#719e07">!=&lt;/span> &lt;span style="color:#cb4b16">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> _, _ = fmt.&lt;span style="color:#268bd2">Fprintln&lt;/span>(os.Stderr, &lt;span style="color:#2aa198">&amp;#34;error: &amp;#34;&lt;/span>, err)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> os.&lt;span style="color:#268bd2">Exit&lt;/span>(&lt;span style="color:#2aa198">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">if&lt;/span> _, err &lt;span style="color:#719e07">:=&lt;/span> os.Stdout.&lt;span style="color:#268bd2">Write&lt;/span>(&lt;span style="color:#268bd2">f&lt;/span>()); err &lt;span style="color:#719e07">!=&lt;/span> &lt;span style="color:#cb4b16">nil&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> _, _ = fmt.&lt;span style="color:#268bd2">Fprintln&lt;/span>(os.Stderr, &lt;span style="color:#2aa198">&amp;#34;call error: &amp;#34;&lt;/span>, err)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> os.&lt;span style="color:#268bd2">Exit&lt;/span>(&lt;span style="color:#2aa198">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> os.&lt;span style="color:#268bd2">Exit&lt;/span>(&lt;span style="color:#2aa198">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>java代码中增加调用go方法序列化结果:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">public&lt;/span> &lt;span style="color:#268bd2">class&lt;/span> &lt;span style="color:#268bd2">GoTestUtil&lt;/span> &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">public&lt;/span> &lt;span style="color:#268bd2">static&lt;/span> Object &lt;span style="color:#268bd2">readGoObject&lt;/span>&lt;span style="color:#719e07">(&lt;/span>String func&lt;span style="color:#719e07">)&lt;/span> &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> System&lt;span style="color:#719e07">.&lt;/span>out&lt;span style="color:#719e07">.&lt;/span>println&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#2aa198">&amp;#34;read go data: &amp;#34;&lt;/span> &lt;span style="color:#719e07">+&lt;/span> func&lt;span style="color:#719e07">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">try&lt;/span> &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Process process &lt;span style="color:#719e07">=&lt;/span> Runtime&lt;span style="color:#719e07">.&lt;/span>getRuntime&lt;span style="color:#719e07">()&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">.&lt;/span>exec&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#2aa198">&amp;#34;go run output/output.go -func_name=&amp;#34;&lt;/span> &lt;span style="color:#719e07">+&lt;/span> func&lt;span style="color:#719e07">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#cb4b16">null&lt;/span>&lt;span style="color:#719e07">,&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">new&lt;/span> File&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#2aa198">&amp;#34;..&amp;#34;&lt;/span>&lt;span style="color:#719e07">));&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#dc322f">int&lt;/span> exitValue &lt;span style="color:#719e07">=&lt;/span> process&lt;span style="color:#719e07">.&lt;/span>waitFor&lt;span style="color:#719e07">();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">if&lt;/span> &lt;span style="color:#719e07">(&lt;/span>exitValue &lt;span style="color:#719e07">!=&lt;/span> &lt;span style="color:#2aa198">0&lt;/span>&lt;span style="color:#719e07">)&lt;/span> &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Assert&lt;span style="color:#719e07">.&lt;/span>fail&lt;span style="color:#719e07">(&lt;/span>readString&lt;span style="color:#719e07">(&lt;/span>process&lt;span style="color:#719e07">.&lt;/span>getErrorStream&lt;span style="color:#719e07">()));&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">return&lt;/span> &lt;span style="color:#cb4b16">null&lt;/span>&lt;span style="color:#719e07">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> InputStream is &lt;span style="color:#719e07">=&lt;/span> process&lt;span style="color:#719e07">.&lt;/span>getInputStream&lt;span style="color:#719e07">();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Hessian2Input input &lt;span style="color:#719e07">=&lt;/span> &lt;span style="color:#719e07">new&lt;/span> Hessian2Input&lt;span style="color:#719e07">(&lt;/span>is&lt;span style="color:#719e07">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">return&lt;/span> input&lt;span style="color:#719e07">.&lt;/span>readObject&lt;span style="color:#719e07">();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">}&lt;/span> &lt;span style="color:#719e07">catch&lt;/span> &lt;span style="color:#719e07">(&lt;/span>Exception e&lt;span style="color:#719e07">)&lt;/span> &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> e&lt;span style="color:#719e07">.&lt;/span>printStackTrace&lt;span style="color:#719e07">();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">return&lt;/span> &lt;span style="color:#cb4b16">null&lt;/span>&lt;span style="color:#719e07">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#268bd2">private&lt;/span> &lt;span style="color:#268bd2">static&lt;/span> String &lt;span style="color:#268bd2">readString&lt;/span>&lt;span style="color:#719e07">(&lt;/span>InputStream in&lt;span style="color:#719e07">)&lt;/span> &lt;span style="color:#268bd2">throws&lt;/span> IOException &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> StringBuilder out &lt;span style="color:#719e07">=&lt;/span> &lt;span style="color:#719e07">new&lt;/span> StringBuilder&lt;span style="color:#719e07">();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> InputStreamReader reader &lt;span style="color:#719e07">=&lt;/span> &lt;span style="color:#719e07">new&lt;/span> InputStreamReader&lt;span style="color:#719e07">(&lt;/span>in&lt;span style="color:#719e07">,&lt;/span> StandardCharsets&lt;span style="color:#719e07">.&lt;/span>UTF_8&lt;span style="color:#719e07">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#dc322f">char&lt;/span>&lt;span style="color:#719e07">[]&lt;/span> buffer &lt;span style="color:#719e07">=&lt;/span> &lt;span style="color:#719e07">new&lt;/span> &lt;span style="color:#dc322f">char&lt;/span>&lt;span style="color:#719e07">[&lt;/span>&lt;span style="color:#2aa198">4096&lt;/span>&lt;span style="color:#719e07">];&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#dc322f">int&lt;/span> bytesRead&lt;span style="color:#719e07">;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">while&lt;/span> &lt;span style="color:#719e07">((&lt;/span>bytesRead &lt;span style="color:#719e07">=&lt;/span> reader&lt;span style="color:#719e07">.&lt;/span>read&lt;span style="color:#719e07">(&lt;/span>buffer&lt;span style="color:#719e07">))&lt;/span> &lt;span style="color:#719e07">!=&lt;/span> &lt;span style="color:#719e07">-&lt;/span>&lt;span style="color:#2aa198">1&lt;/span>&lt;span style="color:#719e07">)&lt;/span> &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> out&lt;span style="color:#719e07">.&lt;/span>append&lt;span style="color:#719e07">(&lt;/span>buffer&lt;span style="color:#719e07">,&lt;/span> &lt;span style="color:#2aa198">0&lt;/span>&lt;span style="color:#719e07">,&lt;/span> bytesRead&lt;span style="color:#719e07">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">return&lt;/span> out&lt;span style="color:#719e07">.&lt;/span>toString&lt;span style="color:#719e07">();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>增加java测试代码:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">@Test&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">public&lt;/span> &lt;span style="color:#dc322f">void&lt;/span> &lt;span style="color:#268bd2">testHelloWordString&lt;/span>&lt;span style="color:#719e07">()&lt;/span> &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Assert&lt;span style="color:#719e07">.&lt;/span>assertEquals&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#2aa198">&amp;#34;hello world&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">,&lt;/span> GoTestUtil&lt;span style="color:#719e07">.&lt;/span>readGoObject&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#2aa198">&amp;#34;HelloWorldString&amp;#34;&lt;/span>&lt;span style="color:#719e07">));&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="15-support-javasqltime--javasqldate-219httpsgithubcomapachedubbo-go-hessian2pull219">1.5 support java.sql.Time &amp;amp; java.sql.Date. &lt;a href="https://github.com/apache/dubbo-go-hessian2/pull/219">#219&lt;/a>&lt;/h3>
&lt;p>增加了 java 类 java.sql.Time, java.sql.Date 支持，分别对应到hessian.Time 和 hessian.Date， 详见 &lt;a href="https://github.com/apache/dubbo-go-hessian2/pull/219/files">https://github.com/apache/dubbo-go-hessian2/pull/219/files&lt;/a>。&lt;/p>
&lt;h2 id="2-enhancement">2. Enhancement&lt;/h2>
&lt;h3 id="21-export-function-encnull-225httpsgithubcomapachedubbo-go-hessian2pull225">2.1 Export function EncNull. &lt;a href="https://github.com/apache/dubbo-go-hessian2/pull/225">#225&lt;/a>&lt;/h3>
&lt;p>开放 hessian.EncNull 方法，以便用户特定情况下使用。&lt;/p>
&lt;h2 id="3-bugfixes">3. Bugfixes&lt;/h2>
&lt;h3 id="31-fix-enum-encode-error-in-request-203httpsgithubcomapachedubbo-go-hessian2pull203">3.1 fix enum encode error in request. &lt;a href="https://github.com/apache/dubbo-go-hessian2/pull/203">#203&lt;/a>&lt;/h3>
&lt;p>原来在 dubbo request 对象中没有判断 enum 类型的情况，此pr增加了判断是不是POJOEnum类型。详见 &lt;a href="https://github.com/apache/dubbo-go-hessian2/pull/203/files">https://github.com/apache/dubbo-go-hessian2/pull/203/files&lt;/a>&lt;/p>
&lt;h3 id="32-fix-byte-field-decoding-issue-216httpsgithubcomapachedubbo-go-hessian2pull216">3.2 fix []byte field decoding issue. &lt;a href="https://github.com/apache/dubbo-go-hessian2/pull/216">#216&lt;/a>&lt;/h3>
&lt;p>v1.7.0 之前如果 struct中包含[]byte字段时无法反序列化, 报错“error list tag: 0x29”，主要原因是被当做list进行处理，对于这种情况应该按照binary数据进行处理即可。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">type&lt;/span> Circular &lt;span style="color:#268bd2">struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Num &lt;span style="color:#dc322f">int&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Previous &lt;span style="color:#719e07">*&lt;/span>Circular
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Next &lt;span style="color:#719e07">*&lt;/span>Circular
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ResponseDataBytes []&lt;span style="color:#dc322f">byte&lt;/span> &lt;span style="color:#586e75">// &amp;lt;----
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">func&lt;/span> (Circular) &lt;span style="color:#268bd2">JavaClassName&lt;/span>() &lt;span style="color:#dc322f">string&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">return&lt;/span> &lt;span style="color:#2aa198">&amp;#34;com.company.Circular&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="33-fix-decoding-error-for-map-in-map-229httpsgithubcomapachedubbo-go-hessian2pull229">3.3 fix decoding error for map in map. &lt;a href="https://github.com/apache/dubbo-go-hessian2/pull/229">#229&lt;/a>&lt;/h3>
&lt;p>v1.7.0 之前嵌套map无法正确解析，主要原因是对应的map对象被当做一个数据类型却未被自动加到类引用列表中，而嵌套map类信息是同一类型的引用，去类引用列表找，找不到就报错了。 解决这个问题的方法就是遇到map类对象，也将其加入到类引用列表中即可。 问题详细参考 &lt;a href="https://github.com/apache/dubbo-go-hessian2/issues/119">#119&lt;/a>.&lt;/p>
&lt;h3 id="34-fix-fields-name-mismatch-in-duration-class-234httpsgithubcomapachedubbo-go-hessian2pull234">3.4 fix fields name mismatch in Duration class. &lt;a href="https://github.com/apache/dubbo-go-hessian2/pull/234">#234&lt;/a>&lt;/h3>
&lt;p>这个 PR 解决了Duration对象中字段错误定义，原来是&amp;quot;second/nano&amp;quot;， 应该是&amp;quot;seconds/nanos&amp;quot;。&lt;/p>
&lt;p>同时改善了测试验证数据。之前使用0作为int字段的测试数据，这是不准确的，因为int类型默认值就是0.&lt;/p></description></item><item><title>Blog: dubbo-go 1.4.0</title><link>https://cn.dubbo.apache.org/zh/blog/2021/01/12/dubbo-go-1.4.0/</link><pubDate>Tue, 12 Jan 2021 00:00:00 +0000</pubDate><guid>https://cn.dubbo.apache.org/zh/blog/2021/01/12/dubbo-go-1.4.0/</guid><description>
&lt;p>得益于社区活跃的支持，2020 年 3 月 25 日 我们发布了一个让人兴奋的版本——dubbo-go v1.4.0。除了继续支持已有的 Dubbo 的一些特性外， dubbo-go 开始了一些自己的创新尝试。&lt;/p>
&lt;p>这个版本，最大的意义在于，做了一些支持云原生的准备工作。比如说，社区在探讨了很久的 k8s 落地之后，终于拿出来了使用 k8s 作为注册中心的解决方案。&lt;/p>
&lt;p>其次一个比较大的改进是&amp;ndash;我们在可观测性上也迈出了重要的一步。在这之前，dubbo-go只提供了日志这么一个单一手段，内部的信息比较不透明，这个版本将有很大的改善。&lt;/p>
&lt;p>最后一个令人心动的改进是，我们支持了 REST 协议。&lt;/p>
&lt;h2 id="1-k8s-注册中心">1. K8s 注册中心&lt;/h2>
&lt;p>dubbo-go 注册中心的本质为K/V型的数据存储。当前版本实现了以 Endpoint 为维度在 k8s API Server 进行服务注册和发现的方案【下文简称 Endpoint 方案】，架构图如下。&lt;/p>
&lt;p>&lt;img src="https://cn.dubbo.apache.org/imgs/blog/dubbo-go/1.4/k8s.png" alt="">&lt;/p>
&lt;p>Endpoint 方案，首先将每个 dubbo-go 进程自身服务信息序列化后，通过 Kubernetes 提供的 Patch 的接口写入在自身 Pod 对象的 Annotation 中。其次，通过 Kubernetes 的 Watch 接口观察集群中本 Namespace 内带有某些固定lable [见上图] Pod 的Annotation 信息的更新，处理服务健康检查、服务上下线等情况并实时更新本地缓存。整体流程仅使用 Kubernetes 原生 API 完成将 Kubernetes 作为注册中心的功能特性。&lt;/p>
&lt;p>这个方案非常简洁，不需要实现额外的第三方模块，也不需要对 Dubbo 业务作出改动，仅仅把 k8s 当做部署平台，依赖其容器管理能力，没有使用其 label selector 和 service 等服务治理特性。如果站在 k8s Operator 的角度来看，Operator 方案的优点即 Endpoint 方案的缺点，Endpoint 方案无法使用 k8s 的健康检查能力，亦没有使用 k8s service 的事件监听能力，每个 consumer 冗余监听一些不必要监听的事件，当 Endpoint 过多时会加大 API Server 的网络压力。&lt;/p>
&lt;p>目前 dubbo-go 社区其实已经有了 operator 版本注册中心的技术方案， 后续版本【计划版本是 v1.6】的 dubbo-go 会给出其实现。相比当前实现，operator 方案开发和线上维护成本当然上升很多。二者如同硬币的两面，社区会让两种方式会共存，以满足不同 level 的使用者。&lt;/p>
&lt;p>注意: 因 Pod 被调度而 IP 发生变化时，当前版本的 configuration 以及 router config 模块暂时无法动态更新。这有待于我们进一步解决。&lt;/p>
&lt;p>参考范例&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>.&lt;/p>
&lt;h2 id="2-tracing-和-metric">2. tracing 和 metric&lt;/h2>
&lt;p>可观测性是微服务重要的一环，也是我们1.4版本着力支持的部分。在1.4版本中，我们主要在 tracing 和 metric 两个方向提供了支持。&lt;/p>
&lt;p>为了支持 tracing 和 metric，关键的一点是支持context在整个调用过程中传递。为此我们解决了context跨端传递的问题。目前用户可以在接口中声明 context 并且设置值，dubbo-go 在底层完成 context 内容从 client 传递到 server 的任务。&lt;/p>
&lt;p>&lt;img src="https://cn.dubbo.apache.org/imgs/blog/dubbo-go/1.4/context.png" alt="">&lt;/p>
&lt;p>在 metric 方面，dubbo-go 开始支持 Prometheus 采集数据了。目前支持 Prometheus中 的 Histogram 和 Summary。用户也可以通过扩展 Reporter 接口来自定义数据采集。&lt;/p>
&lt;p>在 tracing 方面，目前 dubbo-go 的设计是采用 opentracing 作为统一的 API，在该 API 的基础上，通过在 client 和 server 之中传递 context，从而将整个链路串起来。用户可以采用任何支持 opentracing API 的监控框架来作为实现，例如 zipkin，jaeger 等。&lt;/p>
&lt;h2 id="3-rest协议支持">3. rest协议支持&lt;/h2>
&lt;p>Dubbo 生态的应用与其他生态的应用互联互通，一直是 dubbo-go 社区追求的目标。dubbo-go v1.3 版本已经实现了 dubbo-go 与 grpc 生态应用的互联互通，若想与其他生态如 Spring 生态互联互通，借助 rest 协议无疑是一个很好的技术手段。&lt;/p>
&lt;p>Rest 协议是一个很强大并且社区呼声很高的特性，它能够有效解决 open API，前端通信，异构系统通信等问题。比如，如果你的公司里面有一些陈年代码是通过 http 接口来提供服务的，那么使用我们的 rest 协议就可以无缝集成了。&lt;/p>
&lt;p>通过在 dubbo-go 中发布 RESTful 的接口的应用可以调用任意的 RESTful 的接口，也可以被任何客户端以 http 的形式调用，框架图如下：&lt;/p>
&lt;p>&lt;img src="https://cn.dubbo.apache.org/imgs/blog/dubbo-go/1.4/rest.png" alt="">&lt;/p>
&lt;p>在设计过程中，考虑到不同的公司内部使用的 web 框架并不相同，所以我们允许用户扩展自己 rest server （ web 框架在 dubbo-go的封装）的实现，当然，与 rest server 相关的，诸如 filter 等，都可以在自己的 rest server 实现内部扩展。&lt;/p>
&lt;h2 id="4-路由功能增强">4. 路由功能增强&lt;/h2>
&lt;p>路由规则在发起一次 RPC 调用前起到过滤目标服务器地址的作用，过滤后的地址列表，将作为消费端最终发起 RPC 调用的备选地址。v1.4 版本的 dubbo-go 实现了 Condition Router 和 Health Instance First Router，将在后面版本中陆续给出诸如 Tag Router 等剩余 Router 的实现。&lt;/p>
&lt;h3 id="41-条件路由">4.1 条件路由&lt;/h3>
&lt;p>条件路由，是 dubbo-go 中第一个支持的路由规则，允许用户通过配置文件及远端配置中心管理路由规则。&lt;/p>
&lt;p>与之相似的一个概念是 dubbo-go 里面的 group 概念，但是条件路由提供了更加细粒度的控制手段和更加丰富的表达语义。比较典型的使用场景是黑白名单设置，灰度以及测试等。&lt;/p>
&lt;p>参考范例&lt;sup id="fnref:2">&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref">2&lt;/a>&lt;/sup>。&lt;/p>
&lt;h3 id="42-健康实例优先路由">4.2 健康实例优先路由&lt;/h3>
&lt;p>在 RPC 调用中，我们希望尽可能地将请求命中到那些处理能力快、处于健康状态的实例，该路由的功能就是通过某种策略断定某个实例不健康，并将其排除在候选调用列表，优先调用那些健康的实例。这里的&amp;quot;健康&amp;quot;可以是我们自己定义的状态，默认实现即当错误比例到达某一个阈值时或者请求活跃数大于上限则认为其不健康，允许用户扩展健康检测策略。&lt;/p>
&lt;p>在我们服务治理里面，核心的问题其实就在于如何判断一个实例是否可用。无论是负载均衡、&lt;/p>
&lt;p>熔断还是限流，都是对这个问题的解答。所以，这个 feature 是一个很好的尝试。因为我们接下来计划提供的特性，基于规则的限流以及动态限流，都是要解决“如何断定一个实例是否可用”这么一个问题。&lt;/p>
&lt;p>所以欢迎大家使用这个特性，并向社区反馈各自设定的健康指标。这对我们接下来的工作会有很大的帮助。&lt;/p>
&lt;h2 id="5-hessian-协议增强">5. hessian 协议增强&lt;/h2>
&lt;p>相较于 dubbo 的 Java 语言以及其他多语言版本，dubbo-go 社区比较自豪的地方之一就是：无论底层网络引擎还是原生使用的 hessian2 协议，以及整体服务治理框架，都由 dubbo-go 社区从零开发并维护。v1.4 版本的 dubbo-go 对 hessian2 协议又带来了诸多新 feature。&lt;/p>
&lt;h3 id="51-支持-dubbo-协议的-attachments">5.1 支持 dubbo 协议的 attachments&lt;/h3>
&lt;p>在 dubbo-go中，attachments 机制用于传递业务参数之外的附加信息，是在客户端和服务端之间传递非业务参数信息的重要方式。&lt;/p>
&lt;p>hessian 编码协议将之编码在 body 内容的后面进行传输，dubbo-go-hessian2 之前并不支持读/写 attachments，在多个使用方【如蚂蚁金服】的要求下，dubbo-go-hessian2 以兼容已有的使用方式为前提，支持了 attachments 的读/写。&lt;/p>
&lt;p>Request 和 Response 的 struct 中定义了 attachments 的 map，当需要使用 attachments，需要由使用方构造这两种类型的参数或者返回对象。否则，将无法在hessian的传输流中获取和写入attachments。&lt;/p>
&lt;p>另外，利用 dubbo-go 调用链中传输 context 的功能，用户已经可以在服务方法中通过 context 添加 attachments了。&lt;/p>
&lt;h3 id="52-支持忽略非注册-pojo-的解析方式">5.2 支持忽略非注册 pojo 的解析方式&lt;/h3>
&lt;p>由于 hessian 编码协议与 Java 的类型高度耦合，在 golang 的实现中会相对比较麻烦，需要有指明的对应类型。dubbo-go-hessian2 的实现方式是：定义 POJO 接口，要求实现 JavaClassName 方法来供程序获取 Java 对应的类名。这导致了接收到包含未注册类的请求时，将会无法解析而报错，这个问题以前是无法解决的。&lt;/p>
&lt;p>但是，有一些使用场景如网关或者 service mesh 的 sidecar，需要在不关心 Java 类的具体定义的情况下，像 http读取 header 信息一样仅仅读取 dubbo 请求的附加信息，将 dubbo/dubbo-go 请求转发。通过该 feature，网关/sidecar 并不关注请求的具体内容，可以在解析请求的数据流时跳过无法解析的具体类型，直接读取 attachments 的内容。&lt;/p>
&lt;p>该实现通过在 Decoder 中添加的 skip 字段，对每一个 object 做出特殊处理。&lt;/p>
&lt;h3 id="53-支持-javamathbiginteger-和-javamathbigdecimal">5.3 支持 java.math.BigInteger 和 java.math.BigDecimal&lt;/h3>
&lt;p>在 Java 服务中，java.math.BigInteger 和 java.math.BigDecimal 是被频繁使用的数字类型，hessian 库将它们映射为 github.com/dubbogo/gost/math/big 下的对应类型。&lt;/p>
&lt;h3 id="54-支持-继承-和忽略冗余字段">5.4 支持 ‘继承’ 和忽略冗余字段&lt;/h3>
&lt;p>由于 go 没有继承的概念，所以在之前的版本，Java 父类的字段不被 dubbo-go-hessian2 所支持。新版本中，dubbo-go-hessian2 将Java来自父类的字段用匿名结构体对应，如：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">type&lt;/span> Dog &lt;span style="color:#268bd2">struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Animal
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Gender &lt;span style="color:#dc322f">string&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> DogName &lt;span style="color:#dc322f">string&lt;/span> &lt;span style="color:#2aa198">`hessian:&amp;#34;-&amp;#34;`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>同时，就像 json 编码中通过 &lt;code>immediately&lt;/code> 可以在序列化中忽略该字段，同理，通过 &lt;code>hessian:&amp;quot;-&amp;quot;&lt;/code> 用户也可以让冗余字段不参与 hessian 序列化。&lt;/p>
&lt;p>目前，上述四个特性已被某 Go 版本的 sidecar 集成到其商业版本中提供商业服务。&lt;/p>
&lt;h2 id="6-nacos-配置中心">6. Nacos 配置中心&lt;/h2>
&lt;p>配置中心是现代微服务架构里面的核心组件，现在 dubbo-go 提供了对配置中心的支持。&lt;/p>
&lt;p>&lt;img src="https://cn.dubbo.apache.org/imgs/blog/dubbo-go/1.4/config-center.png" alt="">&lt;/p>
&lt;p>Nacos 作为一个易于构建云原生应用的动态服务发现、配置管理和服务管理平台，在该版本终于作为配置中心而得到了支持。&lt;/p>
&lt;p>参考范例&lt;sup id="fnref:3">&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref">3&lt;/a>&lt;/sup>.&lt;/p>
&lt;h2 id="7-接口级签名认证">7. 接口级签名认证&lt;/h2>
&lt;p>Dubbo 鉴权认证是为了避免敏感接口被匿名用户调用而在 SDK 层面提供的额外保障。用户可以在接口级别进行定义是否允许匿名调用，并对调用方进行验签操作，对于验签不通过的消费端，禁止调用。&lt;/p>
&lt;p>&lt;img src="https://cn.dubbo.apache.org/imgs/blog/dubbo-go/1.4/acl.png" alt="">&lt;/p>
&lt;p>如上图，总体实现基于 AK/SK 机制，应用通过 HTTPS 通信，启动时向鉴权服务拉取，定期更新。且允许用户自定义获取 AK/SK 的源，在 RPC 层面保障安全性。&lt;/p>
&lt;h2 id="8-回顾与展望">8. 回顾与展望&lt;/h2>
&lt;p>目前 dubbo-go 已经到了一个比较稳定成熟的状态。在接下来的版本里面，我们将集中精力在云原生上。下一个版本，我们将首先实现应用维度的服务注册，这是一个和现有注册模型完全不同的新的注册模型。也是我们朝着云原生努力的一个关键版本。&lt;/p>
&lt;p>在可观测性上，我们计划在整个 dubbo-go 的框架内，引入更多的埋点，收集更加多的内部状态。这需要实际生产环境用户的使用反馈，从而知道该如何埋点，收集何种数据。&lt;/p>
&lt;p>在限流和熔断上，可以进一步扩展。当下的限流算法，是一种静态的算法&amp;ndash;限流参数并没有实时根据当前服务器的状态来推断是否应该限流，它可能仅仅是用户的经验值。其缺点在于，用户难以把握应该如何配置，例如 TPS 究竟应该设置在多大。所以计划引入一种基于规则的限流和熔断。这种基于规则的限流和熔断，将允许用户设置一些系统状态的状态，如 CPU 使用率，磁盘 IO，网络 IO 等。当系统状态符合用户规则时，将触发熔断。&lt;/p>
&lt;p>目前这些规划的 任务清单&lt;sup id="fnref:4">&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref">4&lt;/a>&lt;/sup>，都已经放入在 dubbo-go 项目的 issue 里面，欢迎感兴趣的朋友认领参与开发。dubbo-go 社区在 &lt;strong>钉钉群 23331795&lt;/strong> 欢迎你的加入。&lt;/p>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>&lt;a href="https://github.com/apache/dubbo-go-samples/tree/1.5/registry/kubernetes">https://github.com/apache/dubbo-go-samples/tree/1.5/registry/kubernetes&lt;/a>&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:2">
&lt;p>&lt;a href="https://github.com/dubbogo/dubbo-samples/tree/master/golang/router/condition">https://github.com/dubbogo/dubbo-samples/tree/master/golang/router/condition&lt;/a>&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:3">
&lt;p>&lt;a href="https://github.com/dubbogo/dubbo-samples/tree/master/golang/configcenter/nacos">https://github.com/dubbogo/dubbo-samples/tree/master/golang/configcenter/nacos&lt;/a>&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:4">
&lt;p>&lt;a href="https://github.com/apache/dubbo-go/milestone/1">https://github.com/apache/dubbo-go/milestone/1&lt;/a>&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description></item><item><title>Blog: 2.7.5 功能解析</title><link>https://cn.dubbo.apache.org/zh/blog/2020/05/18/2.7.5-%E5%8A%9F%E8%83%BD%E8%A7%A3%E6%9E%90/</link><pubDate>Mon, 18 May 2020 00:00:00 +0000</pubDate><guid>https://cn.dubbo.apache.org/zh/blog/2020/05/18/2.7.5-%E5%8A%9F%E8%83%BD%E8%A7%A3%E6%9E%90/</guid><description>
&lt;p>近日，备受瞩目的 Dubbo 2.7.5 版本正式发布，在 2.7.5 版本中，Dubbo 引入了很多新的特性、对现有的很多功能做了增强、同时在性能上也有了非常大的提升，这个版本无论对 Dubbo 社区亦或是开发者来说，都将是一个里程碑式的版本。&lt;/p>
&lt;ul>
&lt;li>应用粒度服务注册【beta】&lt;/li>
&lt;li>HTTP/2 (gRPC) 协议支持&lt;/li>
&lt;li>Protobuf 支持&lt;/li>
&lt;li>性能优化，调用链路性能提升 30%&lt;/li>
&lt;li>支持 TLS 安全传输链路&lt;/li>
&lt;li>优化的消费端线程模型&lt;/li>
&lt;li>新增更适应多集群部署场景的负载均衡策略&lt;/li>
&lt;li>全新的应用开发 API （兼容老版本应用）【beta】&lt;/li>
&lt;li>其他一些功能增强与 bugfix&lt;/li>
&lt;/ul>
&lt;p>首先，从服务发现上，新版本突破以往基于接口粒度的模型，引入了全新的基于应用粒度的服务发现机制 - 服务自省，虽然该机制当前仍处于 beta 阶段，但对于 Dubbo 向整个微服务云原生体系靠齐，都打下了非常好的基础；得益于紧凑的协议设计和代码实现上的优化，Dubbo 一直以来都具有较好的性能表现，在 2.7.5 版本中，性能上有了进一步的提升，根据来自官方维护团队的压测，新版本在调用链路上性能提升达到 30%；云原生微服务时代，多语言需求变得越来越普遍，协议的通用性和穿透性对于构建打通前后端的整套微服务体系也变得非常关键，Dubbo 通过实现 gRPC 协议实现了对 HTTP/2 协议的支持，同时增加了与 Protobuf 的结合。&lt;/p>
&lt;h2 id="1--应用粒度服务注册beta">1. 应用粒度服务注册【beta】&lt;/h2>
&lt;p>从 Java 实现版本的角度来说，Dubbo 是一个面向接口代理的服务开发框架，服务定义、服务发布以及服务引用都是基于接口，服务治理层面包括服务发现、各种规则定义也都是基于接口定义的，基于接口可以说是 Dubbo 的一大优势，比如向开发者屏蔽了远程调用细节、治理粒度更精细等。但基于接口的服务定义同时也存在一些问题，如服务，与业界通用的微服务体系等。&lt;/p>
&lt;p>&lt;img src="https://cn.dubbo.apache.org/imgs/blog/servicediscovery-old.png" alt="servicediscovery-old.png">&lt;/p>
&lt;p>针对以上问题，2.7.5 版本引入了一种新的服务定义/治理机制：&lt;strong>服务自省&lt;/strong>，简单来说这是一种基于应用粒度的服务治理方案。一个实例只向注册中心注册一条记录，彻底解决服务推送性能瓶颈，同时由于这样的模型与主流微服务体系如 SpringCloud、K8S 等天然是对等的，因此为 Dubbo 解决和此类异构体系间的互联互通清除了障碍。有兴趣进一步了解 Dubbo 服务自省机制如何解决异构微服务体系互联互通问题的，可具体参考我们之前的文章解析《Dubbo 如何成为联通异构微服务体系的最佳服务开发框架》。&lt;/p>
&lt;p>以下是服务自省机制的基本工作原理图。&lt;/p>
&lt;p>&lt;img src="https://cn.dubbo.apache.org/imgs/blog/servicediscovery-new.png" alt="servicediscovery-new.png">&lt;/p>
&lt;p>要了解更多关于服务自省工作原理的细节，请参与官方文档及后续文章。&lt;/p>
&lt;p>服务自省与当前已有的机制之间可以说是互补的关系，Dubbo 框架会继续保持接口粒度的服务治理的优势，实现接口和应用两个粒度互为补充的局面，兼顾性能、灵活性和通用性，力争使 Dubbo 成为微服务开发的最佳框架。&lt;/p>
&lt;h2 id="2-http2-grpc-协议支持">2. HTTP/2 (gRPC) 协议支持&lt;/h2>
&lt;p>Dubbo RPC 协议是构建在 TCP 之上，这有很多优势也有一些缺点，缺点比如通用性、协议穿透性不强，对多语言实现不够友好等。HTTP/2 由于其标准 HTTP 协议的属性，无疑将具有更好的通用性，现在或将来在各层网络设备上肯定都会得到很好的支持，gRPC 之所以选在 HTTP/2 作为传输层载体很大程度上也是因为这个因素。当前 gRPC 在云原生、Mesh 等体系下的认可度和采用度逐步提升，俨然有成为 RPC 协议传输标准的趋势，Dubbo 和 gRPC 在协议层面是对等竞争的，但是在框架实现上却各有侧重，Dubbo 无疑有更丰富的服务开发和治理体验 。&lt;/p>
&lt;p>Dubbo 支持 gRPC 协议带来的直观好处有：&lt;/p>
&lt;ul>
&lt;li>正式支持基于 HTTP/2 的远程通信，在协议通用性和穿透性上进一步提升。&lt;/li>
&lt;li>支持跨进程的 Stream 流式通信，支持 Reactive 风格的 RPC 编程。&lt;/li>
&lt;li>解决了 gRPC 框架难以直接用于微服务开发的问题，将其纳入 Dubbo 的服务治理体系。&lt;/li>
&lt;li>为联通组织内部已有的 gRPC 或多语言体系提供支持。&lt;/li>
&lt;/ul>
&lt;p>2.7.5 版本开始，gRPC (HTTP/2) 成为 Dubbo 协议体系中的一等公民，对于有需求的开发者完全可以在 Dubbo 开发的微服务体系中启用 gRPC 协议，而不必束缚在 Dubbo 协议自身上，关于这点我们在《Dubbo 如何成为联通异构微服务体系的最佳服务开发框架》一文中也有类似的观点表述。&lt;/p>
&lt;p>关于 Dubbo 中如何开发 grpc (HTTP/2) 服务的细节，请参考文章《Dubbo 在跨语言与协议穿透性等方面的探索》，关于如何开启 TLS 和使用 Reactive RPC 编程，请参见示例。另外，Dubbo 的 go 版本目前同样也提供了对 gRPC 协议对等的支持，具体请关注 dubbogo 社区的发版计划。&lt;/p>
&lt;h2 id="3-protobuf-支持">3. Protobuf 支持&lt;/h2>
&lt;p>支持 Protobuf 更多的是从解决 Dubbo 跨语言易用性的角度考虑的。&lt;/p>
&lt;p>跨语言的服务开发涉及到多个方面，从服务定义、RPC 协议到序列化协议都要做到语言中立，同时还针对每种语言有对应的 SDK 实现。虽然得益于社区的贡献，现在 Dubbo 在多语言 SDK 实现上逐步有了起色，已经提供了包括 Java, Go, PHP, C#, Python, NodeJs, C 等版本的客户端或全量实现版本，但在以上提到的跨语言友好性方面，以上三点还是有很多可改进之处。&lt;/p>
&lt;p>协议上 2.7.5 版本支持了 gRPC，而关于服务定义与序列化，Protobuf 则提供了很好的解决方案。&lt;/p>
&lt;ul>
&lt;li>服务定义。当前 Dubbo 的服务定义和具体的编程语言绑定，没有提供一种语言中立的服务描述格式，比如 Java 就是定义 Interface 接口，到了其他语言又得重新以另外的格式定义一遍。因此 Dubbo 通过支持 Protobuf 实现了语言中立的服务定义。&lt;/li>
&lt;li>序列化。Dubbo 当前支持的序列化包括 Json、Hessian2、Kryo、FST、Java 等，而这其中支持跨语言的只有 Json、Hessian2，通用的 Json 有固有的性能问题，而 Hessian2 无论在效率还是多语言 SDK 方面都有所欠缺。为此，Dubbo 通过支持 Protobuf 序列化来提供更高效、易用的跨语言序列化方案。&lt;/li>
&lt;/ul>
&lt;p>日后，不论我们使用什么语言版本来开发 Dubbo 服务，都可以直接使用 IDL 定义如下服务，具体请参见示例&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>syntax = &lt;span style="color:#2aa198">&amp;#34;proto3&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>option java_multiple_files = &lt;span style="color:#cb4b16">true&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>option java_package = &lt;span style="color:#2aa198">&amp;#34;org.apache.dubbo.demo&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>option java_outer_classname = &lt;span style="color:#2aa198">&amp;#34;DemoServiceProto&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>option objc_class_prefix = &lt;span style="color:#2aa198">&amp;#34;DEMOSRV&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#719e07">package&lt;/span> demoservice;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">// The demo service definition.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">&lt;/span>service DemoService {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> rpc &lt;span style="color:#268bd2">SayHello&lt;/span> (HelloRequest) &lt;span style="color:#268bd2">returns&lt;/span> (HelloReply) {}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">// The request message containing the user&amp;#39;s name.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">&lt;/span>message HelloRequest {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#dc322f">string&lt;/span> name = &lt;span style="color:#2aa198">1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">// The response message containing the greetings
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">&lt;/span>message HelloReply {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#dc322f">string&lt;/span> message = &lt;span style="color:#2aa198">1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="4-性能优化">4. 性能优化&lt;/h2>
&lt;h3 id="41-调用链路优化">4.1 调用链路优化&lt;/h3>
&lt;p>2.7.5 版本对整个调用链路做了全面的优化，根据压测结果显示，总体 QPS 性能提升将近 30%，同时也减少了调用过程中的内存分配开销。其中一个值得提及的设计点是 2.7.5 引入了 Servicerepository 的概念，在服务注册阶段提前生成 ServiceDescriptor 和 MethodDescriptor，以减少 RPC 调用阶段计算 Service 元信息带来的资源消耗。&lt;/p>
&lt;h3 id="42-消费端线程池模型优化">4.2 消费端线程池模型优化&lt;/h3>
&lt;p>对 2.7.5 版本之前的 Dubbo 应用，尤其是一些消费端应用，当面临需要消费大量服务且并发数比较大的大流量场景时（典型如网关类场景），经常会出现消费端线程数分配过多的问题，具体问题讨论可参见以下 issue ：&lt;/p>
&lt;p>&lt;a href="https://github.com/apache/dubbo/issues/2013">https://github.com/apache/dubbo/issues/2013&lt;/a>&lt;/p>
&lt;p>改进后的消费端线程池模型，通过复用业务端被阻塞的线程，很好的解决了这个问题。&lt;/p>
&lt;p>&lt;strong>老的线程池模型&lt;/strong>&lt;/p>
&lt;p>&lt;img src="https://cn.dubbo.apache.org/imgs/blog/consumer-threadpool0.png" alt="消费端线程池.png">&lt;/p>
&lt;p>我们重点关注 Consumer 部分：&lt;/p>
&lt;ol>
&lt;li>业务线程发出请求，拿到一个 Future 实例。&lt;/li>
&lt;li>业务线程紧接着调用 future.get 阻塞等待业务结果返回。&lt;/li>
&lt;li>当业务数据返回后，交由独立的 Consumer 端线程池进行反序列化等处理，并调用 future.set 将反序列化后的业务结果置回。&lt;/li>
&lt;li>业务线程拿到结果直接返回&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>2.7.5 版本引入的线程池模型&lt;/strong>&lt;/p>
&lt;p>&lt;img src="https://cn.dubbo.apache.org/imgs/blog/consumer-threadpool1.png" alt="消费端线程池新.png">&lt;/p>
&lt;ol>
&lt;li>业务线程发出请求，拿到一个 Future 实例。&lt;/li>
&lt;li>在调用 future.get() 之前，先调用 ThreadlessExecutor.wait()，wait 会使业务线程在一个阻塞队列上等待，直到队列中被加入元素。&lt;/li>
&lt;li>当业务数据返回后，生成一个 Runnable Task 并放入 ThreadlessExecutor 队列&lt;/li>
&lt;li>业务线程将 Task 取出并在本线程中执行：反序列化业务数据并 set 到 Future。&lt;/li>
&lt;li>业务线程拿到结果直接返回&lt;/li>
&lt;/ol>
&lt;p>这样，相比于老的线程池模型，由业务线程自己负责监测并解析返回结果，免去了额外的消费端线程池开销。&lt;/p>
&lt;p>关于性能优化，在接下来的版本中将会持续推进，主要从以下两个方面入手：&lt;/p>
&lt;ol>
&lt;li>RPC 调用链路。目前能看到的点包括：进一步减少执行链路的内存分配、在保证协议兼容性的前提下提高协议传输效率、提高 Filter、Router 等计算效率。&lt;/li>
&lt;li>服务治理链路。进一步减少地址推送、服务治理规则推送等造成的内存、cpu 资源消耗。&lt;/li>
&lt;/ol>
&lt;h2 id="5-tls-安全传输链路">5. TLS 安全传输链路&lt;/h2>
&lt;p>2.7.5 版本在传输链路的安全性上做了很多工作，对于内置的 Dubbo Netty Server 和新引入的 gRPC 协议都提供了基于 TLS 的安全链路传输机制。&lt;/p>
&lt;p>TLS 的配置都有统一的入口，如下所示：&lt;/p>
&lt;p>&lt;strong>Provider 端&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>SslConfig sslConfig &lt;span style="color:#719e07">=&lt;/span> &lt;span style="color:#719e07">new&lt;/span> SslConfig&lt;span style="color:#719e07">();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sslConfig&lt;span style="color:#719e07">.&lt;/span>setServerKeyCertChainPath&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#2aa198">&amp;#34;path to cert&amp;#34;&lt;/span>&lt;span style="color:#719e07">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sslConfig&lt;span style="color:#719e07">.&lt;/span>setServerPrivateKeyPath&lt;span style="color:#719e07">(&lt;/span>args&lt;span style="color:#719e07">[&lt;/span>&lt;span style="color:#2aa198">1&lt;/span>&lt;span style="color:#719e07">]);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">// 如果开启双向 cert 认证
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">&lt;/span>&lt;span style="color:#719e07">if&lt;/span> &lt;span style="color:#719e07">(&lt;/span>mutualTls&lt;span style="color:#719e07">)&lt;/span> &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sslConfig&lt;span style="color:#719e07">.&lt;/span>setServerTrustCertCollectionPath&lt;span style="color:#719e07">(&lt;/span>args&lt;span style="color:#719e07">[&lt;/span>&lt;span style="color:#2aa198">2&lt;/span>&lt;span style="color:#719e07">]);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ProtocolConfig protocolConfig &lt;span style="color:#719e07">=&lt;/span> &lt;span style="color:#719e07">new&lt;/span> ProtocolConfig&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#2aa198">&amp;#34;dubbo/grpc&amp;#34;&lt;/span>&lt;span style="color:#719e07">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>protocolConfig&lt;span style="color:#719e07">.&lt;/span>setSslEnabled&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#cb4b16">true&lt;/span>&lt;span style="color:#719e07">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Consumer 端&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#719e07">if&lt;/span> &lt;span style="color:#719e07">(!&lt;/span>mutualTls&lt;span style="color:#719e07">)&lt;/span> &lt;span style="color:#719e07">{}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sslConfig&lt;span style="color:#719e07">.&lt;/span>setClientTrustCertCollectionPath&lt;span style="color:#719e07">(&lt;/span>args&lt;span style="color:#719e07">[&lt;/span>&lt;span style="color:#2aa198">0&lt;/span>&lt;span style="color:#719e07">]);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#719e07">}&lt;/span> &lt;span style="color:#719e07">else&lt;/span> &lt;span style="color:#719e07">{&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sslConfig&lt;span style="color:#719e07">.&lt;/span>setClientTrustCertCollectionPath&lt;span style="color:#719e07">(&lt;/span>args&lt;span style="color:#719e07">[&lt;/span>&lt;span style="color:#2aa198">0&lt;/span>&lt;span style="color:#719e07">]);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sslConfig&lt;span style="color:#719e07">.&lt;/span>setClientKeyCertChainPath&lt;span style="color:#719e07">(&lt;/span>args&lt;span style="color:#719e07">[&lt;/span>&lt;span style="color:#2aa198">1&lt;/span>&lt;span style="color:#719e07">]);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sslConfig&lt;span style="color:#719e07">.&lt;/span>setClientPrivateKeyPath&lt;span style="color:#719e07">(&lt;/span>args&lt;span style="color:#719e07">[&lt;/span>&lt;span style="color:#2aa198">2&lt;/span>&lt;span style="color:#719e07">]);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#719e07">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>为尽可能保证应用启动的灵活性，TLS Cert 的指定还能通过 -D 参数或环境变量等方式来在启动阶段根据部署环境动态指定，具体请参见 Dubbo 配置读取规则与 TLS 示例&lt;/p>
&lt;p>Dubbo 配置读取规则：/zh/docs/user/configuration/configuration-load-process.html&lt;/p>
&lt;p>TLS 示例：https://github.com/apache/dubbo-samples/tree/master/dubbo-samples-ssl&lt;/p>
&lt;blockquote>
&lt;p>如果要使用的是 gRPC 协议，在开启 TLS 时会使用到协议协商机制，因此必须使用支持 ALPN 机制的 Provider，推荐使用的是 netty-tcnative，具体可参见 gRPC Java 社区的总结： &lt;a href="https://github.com/grpc/grpc-java/blob/master/SECURITY.md">https://github.com/grpc/grpc-java/blob/master/SECURITY.md&lt;/a>&lt;/p>
&lt;/blockquote>
&lt;p>在服务调用的安全性上，Dubbo 在后续的版本中会持续投入，其中服务发现/调用的鉴权机制预计在接下来的版本中就会和大家见面。&lt;/p>
&lt;h2 id="6-bootstrap-apibeta">6. Bootstrap API【beta】&lt;/h2>
&lt;p>在上面讲《服务自省》时，我们提到了 Dubbo 面向接口的设计，面向接口编程、面向接口做服务发现和服务治理。在引入应用粒度服务发现的同时，2.7.5 版本对编程入口也做了优化，在兼容老版本 API 的同时，新增了新的面向应用的编程接口 - DubboBootstrap。&lt;/p>
&lt;p>以面向 Dubbo API 编程为例，以前我们要这么写：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>ServiceConfig&lt;span style="color:#719e07">&amp;lt;&lt;/span>GreetingsService&lt;span style="color:#719e07">&amp;gt;&lt;/span> service1 &lt;span style="color:#719e07">=&lt;/span> &lt;span style="color:#719e07">new&lt;/span> ServiceConfig&lt;span style="color:#719e07">&amp;lt;&amp;gt;();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>service1&lt;span style="color:#719e07">.&lt;/span>setApplication&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#719e07">new&lt;/span> ApplicationConfig&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#2aa198">&amp;#34;first-dubbo-provider&amp;#34;&lt;/span>&lt;span style="color:#719e07">));&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>service1&lt;span style="color:#719e07">.&lt;/span>setRegistry&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#719e07">new&lt;/span> RegistryConfig&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#2aa198">&amp;#34;zookeeper://&amp;#34;&lt;/span> &lt;span style="color:#719e07">+&lt;/span> zookeeperHost &lt;span style="color:#719e07">+&lt;/span> &lt;span style="color:#2aa198">&amp;#34;:2181&amp;#34;&lt;/span>&lt;span style="color:#719e07">));&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>service1&lt;span style="color:#719e07">.&lt;/span>export&lt;span style="color:#719e07">();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ServiceConfig&lt;span style="color:#719e07">&amp;lt;&lt;/span>GreetingsService&lt;span style="color:#719e07">&amp;gt;&lt;/span> service2 &lt;span style="color:#719e07">=&lt;/span> &lt;span style="color:#719e07">new&lt;/span> ServiceConfig&lt;span style="color:#719e07">&amp;lt;&amp;gt;();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>service2&lt;span style="color:#719e07">.&lt;/span>setApplication&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#719e07">new&lt;/span> ApplicationConfig&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#2aa198">&amp;#34;first-dubbo-provider&amp;#34;&lt;/span>&lt;span style="color:#719e07">));&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>service2&lt;span style="color:#719e07">.&lt;/span>setRegistry&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#719e07">new&lt;/span> RegistryConfig&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#2aa198">&amp;#34;zookeeper://&amp;#34;&lt;/span> &lt;span style="color:#719e07">+&lt;/span> zookeeperHost &lt;span style="color:#719e07">+&lt;/span> &lt;span style="color:#2aa198">&amp;#34;:2181&amp;#34;&lt;/span>&lt;span style="color:#719e07">));&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>service2&lt;span style="color:#719e07">.&lt;/span>export&lt;span style="color:#719e07">();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#719e07">......&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>ApplicationConfig、RegistryConfig、ProtocolConfig 等全局性的配置要在每个服务上去配置；并且从 Dubbo 框架的角度，由于缺少一个统一的 Server 入口，一些实例级别的配置如 ShutdownHook、ApplicationListener、应用级服务治理组件等都缺少一个加载驱动点。&lt;/p>
&lt;p>在引入 DubboBootstrap 后，新的编程模型变得更简单，并且也为解决了缺少实例级启动入口的问题&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-java" data-lang="java">&lt;span style="display:flex;">&lt;span>ProtocolConfig protocolConfig &lt;span style="color:#719e07">=&lt;/span> &lt;span style="color:#719e07">new&lt;/span> ProtocolConfig&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#2aa198">&amp;#34;grpc&amp;#34;&lt;/span>&lt;span style="color:#719e07">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>protocolConfig&lt;span style="color:#719e07">.&lt;/span>setSslEnabled&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#cb4b16">true&lt;/span>&lt;span style="color:#719e07">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>SslConfig sslConfig &lt;span style="color:#719e07">=&lt;/span> &lt;span style="color:#719e07">new&lt;/span> SslConfig&lt;span style="color:#719e07">();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sslConfig&lt;span style="color:#719e07">.&lt;/span>setXxxCert&lt;span style="color:#719e07">(...);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>DubboBootstrap bootstrap &lt;span style="color:#719e07">=&lt;/span> DubboBootstrap&lt;span style="color:#719e07">.&lt;/span>getInstance&lt;span style="color:#719e07">();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>bootstrap&lt;span style="color:#719e07">.&lt;/span>application&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#719e07">new&lt;/span> ApplicationConfig&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#2aa198">&amp;#34;ssl-provider&amp;#34;&lt;/span>&lt;span style="color:#719e07">))&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">.&lt;/span>registry&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#719e07">new&lt;/span> RegistryConfig&lt;span style="color:#719e07">(&lt;/span>&lt;span style="color:#2aa198">&amp;#34;zookeeper://127.0.0.1:2181&amp;#34;&lt;/span>&lt;span style="color:#719e07">))&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">.&lt;/span>protocol&lt;span style="color:#719e07">(&lt;/span>protocolConfig&lt;span style="color:#719e07">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#719e07">.&lt;/span>ssl&lt;span style="color:#719e07">(&lt;/span>sslConfig&lt;span style="color:#719e07">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ServiceConfig&lt;span style="color:#719e07">&amp;lt;&lt;/span>GreetingsService&lt;span style="color:#719e07">&amp;gt;&lt;/span> service1 &lt;span style="color:#719e07">=&lt;/span> &lt;span style="color:#719e07">new&lt;/span> ServiceConfig&lt;span style="color:#719e07">&amp;lt;&amp;gt;();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ServiceConfig&lt;span style="color:#719e07">&amp;lt;&lt;/span>GreetingsService&lt;span style="color:#719e07">&amp;gt;&lt;/span> service2 &lt;span style="color:#719e07">=&lt;/span> &lt;span style="color:#719e07">new&lt;/span> ServiceConfig&lt;span style="color:#719e07">&amp;lt;&amp;gt;();&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>bootstrap&lt;span style="color:#719e07">.&lt;/span>service&lt;span style="color:#719e07">(&lt;/span>service1&lt;span style="color:#719e07">).&lt;/span>service&lt;span style="color:#719e07">(&lt;/span>service2&lt;span style="color:#719e07">);&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>bootstrap&lt;span style="color:#719e07">.&lt;/span>start&lt;span style="color:#719e07">();&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="7-多注册中心集群负载均衡">7. 多注册中心集群负载均衡&lt;/h2>
&lt;p>对于多注册中心订阅的场景，选址时的多了一层注册中心集群间的负载均衡：&lt;/p>
&lt;p>&lt;img src="https://cn.dubbo.apache.org/imgs/blog/cluster-lb.png" alt="cluster-lb.png">&lt;/p>
&lt;p>在 Cluster Invoker 这一级，我们支持的选址策略有（2.7.5+ 版本，具体使用请参见文档）：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>指定优先级&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-xml" data-lang="xml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">&amp;lt;!-- 来自 preferred=“true” 注册中心的地址将被优先选择，只有该中心无可用地址时才 Fallback 到其他注册中心 --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">&amp;lt;dubbo:registry&lt;/span> address=&lt;span style="color:#2aa198">&amp;#34;zookeeper://${zookeeper.address1}&amp;#34;&lt;/span> preferred=&lt;span style="color:#2aa198">&amp;#34;true&amp;#34;&lt;/span> &lt;span style="color:#268bd2">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>同 zone 优先&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-xml" data-lang="xml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">&amp;lt;!-- 选址时会和流量中的 zone key 做匹配，流量会优先派发到相同 zone 的地址 --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">&amp;lt;dubbo:registry&lt;/span> address=&lt;span style="color:#2aa198">&amp;#34;zookeeper://${zookeeper.address1}&amp;#34;&lt;/span> zone=&lt;span style="color:#2aa198">&amp;#34;beijing&amp;#34;&lt;/span> &lt;span style="color:#268bd2">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>权重轮询&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-xml" data-lang="xml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#586e75">&amp;lt;!-- 来自北京和上海集群的地址，将以 10:1 的比例来分配流量 --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">&amp;lt;dubbo:registry&lt;/span> id=&lt;span style="color:#2aa198">&amp;#34;beijing&amp;#34;&lt;/span> address=&lt;span style="color:#2aa198">&amp;#34;zookeeper://${zookeeper.address1}&amp;#34;&lt;/span> weight=&lt;span style="color:#2aa198">”100“&lt;/span> &lt;span style="color:#268bd2">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#268bd2">&amp;lt;dubbo:registry&lt;/span> id=&lt;span style="color:#2aa198">&amp;#34;shanghai&amp;#34;&lt;/span> address=&lt;span style="color:#2aa198">&amp;#34;zookeeper://${zookeeper.address2}&amp;#34;&lt;/span> weight=&lt;span style="color:#2aa198">”10“&lt;/span> &lt;span style="color:#268bd2">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>默认，stick to 任意可用&lt;/p>
&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>关于多注册中心订阅模型，Dubbo 同时也提供了 Multi-Registry 合并的解决思路，欢迎参与到以下 PR 的讨论中: &lt;a href="https://github.com/apache/dubbo/issues/5399">https://github.com/apache/dubbo/issues/5399&lt;/a>&lt;/p>
&lt;/blockquote>
&lt;h2 id="8-其他功能增强">8. 其他功能增强&lt;/h2>
&lt;ul>
&lt;li>
&lt;p>新增地址变更事件通知接口，方便业务侧感知地址变化&lt;/p>
&lt;/li>
&lt;li>
&lt;p>新增外围配置加载入口，方便开发者在启动阶段定制服务启动参数&lt;/p>
&lt;/li>
&lt;li>
&lt;p>config 模块重构&lt;/p>
&lt;/li>
&lt;li>
&lt;p>parameters 扩展配置增强&lt;/p>
&lt;/li>
&lt;li>
&lt;p>其他一些 Bugfix&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>从 Dubbo 框架自身的角度来说，2.7.5 版本也做了很多的重构与优化（比如说 config 模块的重构），这些改动对于使用者来说并无感知的，但是从优化整个 Dubbo 代码内部结构的角度来说，这些改动对后续的功能开发与新机制的引入是一个很好的铺垫。&lt;/p>
&lt;h2 id="9-总结与展望">9. 总结与展望&lt;/h2>
&lt;p>在后续的版本中，Dubbo 会持续快速的优化与迭代，主要从以下几个方面发力：&lt;/p>
&lt;ul>
&lt;li>继续探索服务自省成为 Dubbo 主推的服务治理模型。&lt;/li>
&lt;li>对于企业用户关心的微服务解决方案场景，会持续推进框架的演进，包括当前正在开发的配置、服务鉴权机制、熔断等功能。后续还会尝试联合社区推动周边配套设施如网关、治理平台 Admin 等的建设，非常期待社区能踊跃参与到此部分的建设中。&lt;/li>
&lt;li>性能优化上。主要从两个方面着手，一是调用链路的持续优化，同时继续探索新的更通用的 RPC 协议；另一方面是在服务治理推送机制上的优化，以进一步提高 Dubbo 在大规模服务地址推送场景下的表现。&lt;/li>
&lt;li>云原生方向。接下来的版本将重点探索，1. 如何更好的支持 Dubbo 在 Kubernetes 上的部署和服务治理；2. 对于混合部署的场景，如传统 VM 和 K8S 体系混合部署、SDK Dubbo 与 Mesh 混合部署的场景，如何提供更好的支持以实现混部场景的长期共存或迁移。&lt;/li>
&lt;/ul></description></item><item><title>Blog: 过往版本</title><link>https://cn.dubbo.apache.org/zh/blog/2020/05/18/%E8%BF%87%E5%BE%80%E7%89%88%E6%9C%AC/</link><pubDate>Mon, 18 May 2020 00:00:00 +0000</pubDate><guid>https://cn.dubbo.apache.org/zh/blog/2020/05/18/%E8%BF%87%E5%BE%80%E7%89%88%E6%9C%AC/</guid><description>
&lt;h2 id="验证">验证&lt;/h2>
&lt;p>可以按照这里的&lt;a href="https://www.apache.org/info/verification">步骤&lt;/a>, 利用&lt;a href="https://downloads.apache.org/dubbo/KEYS">KEYS&lt;/a>文件来验证下载。&lt;/p>
&lt;h2 id="apache-dubbo">Apache Dubbo&lt;/h2>
&lt;p>请点击了解各&lt;a href="https://cn.dubbo.apache.org/zh/docsv2.7/user/versions/">版本详情和升级注意事项&lt;/a>&lt;/p>
&lt;blockquote>
&lt;p>GitHub: &lt;a href="https://github.com/apache/dubbo">https://github.com/apache/dubbo&lt;/a> &lt;br>
发布说明: &lt;a href="https://github.com/apache/dubbo/releases">https://github.com/apache/dubbo/releases&lt;/a>&lt;/p>
&lt;/blockquote>
&lt;h3 id="320-beta1-2022-11-08">3.2.0-beta.1 (2022-11-08)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://www.apache.org/dyn/closer.lua/dubbo/3.2.0-beta.1/apache-dubbo-3.2.0-beta.1-src.zip">source&lt;/a> |
&lt;a href="https://www.apache.org/dyn/closer.lua/dubbo/3.2.0-beta.1/apache-dubbo-3.2.0-beta.1-src.zip.asc">asc&lt;/a> |
&lt;a href="https://www.apache.org/dyn/closer.lua/dubbo/3.2.0-beta.1/apache-dubbo-3.2.0-beta.1-src.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="312-2022-11-08">3.1.2 (2022-11-08)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://www.apache.org/dyn/closer.lua/dubbo/3.1.2/apache-dubbo-3.1.2-src.zip">source&lt;/a> |
&lt;a href="https://www.apache.org/dyn/closer.lua/dubbo/3.1.2/apache-dubbo-3.1.2-src.zip.asc">asc&lt;/a> |
&lt;a href="https://www.apache.org/dyn/closer.lua/dubbo/3.1.2/apache-dubbo-3.1.2-src.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="2716-2022-07-06">2.7.16 (2022-07-06)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://www.apache.org/dyn/closer.lua/dubbo/2.7.16/apache-dubbo-2.7.16-src.zip">source&lt;/a> |
&lt;a href="https://www.apache.org/dyn/closer.lua/dubbo/2.7.16/apache-dubbo-2.7.16-src.zip.asc">asc&lt;/a> |
&lt;a href="https://www.apache.org/dyn/closer.lua/dubbo/2.7.16/apache-dubbo-2.7.16-src.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="309-2022-06-23">3.0.9 (2022-06-23)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://www.apache.org/dyn/closer.lua/dubbo/3.0.9/apache-dubbo-3.0.9-src.zip">source&lt;/a> |
&lt;a href="https://www.apache.org/dyn/closer.lua/dubbo/3.0.9/apache-dubbo-3.0.9-src.zip.asc">asc&lt;/a> |
&lt;a href="https://www.apache.org/dyn/closer.lua/dubbo/3.0.9/apache-dubbo-3.0.9-src.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="308-2022-05-11">3.0.8 (2022-05-11)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/dubbo/3.0.8/apache-dubbo-3.0.8-src.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/3.0.8/apache-dubbo-3.0.8-src.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/3.0.8/apache-dubbo-3.0.8-src.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="307-2022-04-01">3.0.7 (2022-04-01)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/dubbo/3.0.7/apache-dubbo-3.0.7-src.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/3.0.7/apache-dubbo-3.0.7-src.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/3.0.7/apache-dubbo-3.0.7-src.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="306-2022-02-28">3.0.6 (2022-02-28)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/dubbo/3.0.6/apache-dubbo-3.0.6-src.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/3.0.6/apache-dubbo-3.0.6-src.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/3.0.6/apache-dubbo-3.0.6-src.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="305-2021-12-30">3.0.5 (2021-12-30)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/dubbo/3.0.5/apache-dubbo-3.0.5-src.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/3.0.5/apache-dubbo-3.0.5-src.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/3.0.5/apache-dubbo-3.0.5-src.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="2715-2021-12-29">2.7.15 (2021-12-29)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/dubbo/2.7.15/apache-dubbo-2.7.15-src.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/2.7.15/apache-dubbo-2.7.15-src.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/2.7.15/apache-dubbo-2.7.15-src.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="2612-2021-12-29">2.6.12 (2021-12-29)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://www.apache.org/dyn/closer.lua/dubbo/2.6.12/apache-dubbo-2.6.12-src.zip">source&lt;/a> |
&lt;a href="https://www.apache.org/dyn/closer.lua/dubbo/2.6.12/apache-dubbo-v-src.zip.asc">asc&lt;/a> |
&lt;a href="https://www.apache.org/dyn/closer.lua/dubbo/2.6.12/apache-dubbo-2.6.12-src.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="304-2021-10-24">3.0.4 (2021-10-24)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/dubbo/3.0.4/apache-dubbo-3.0.4-src.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/3.0.4/apache-dubbo-3.0.4-src.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/3.0.4/apache-dubbo-3.0.4-src.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="303-2021-09-27">3.0.3 (2021-09-27)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/dubbo/3.0.3/apache-dubbo-3.0.3-src.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/3.0.3/apache-dubbo-3.0.3-src.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/3.0.3/apache-dubbo-3.0.3-src.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="2714-2021-09-20">2.7.14 (2021-09-20)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/dubbo/2.7.14/apache-dubbo-2.7.14-src.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/2.7.14/apache-dubbo-2.7.14-src.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/2.7.14/apache-dubbo-2.7.14-src.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="2611-2021-09-18">2.6.11 (2021-09-18)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://www.apache.org/dyn/closer.cgi?path=dubbo/2.6.11/apache-dubbo-2.6.11-source-release.zip">source&lt;/a> |
&lt;a href="https://www.apache.org/dyn/closer.cgi?path=dubbo/2.6.11/apache-dubbo-2.6.11-source-release.zip.asc">asc&lt;/a> |
&lt;a href="https://www.apache.org/dyn/closer.cgi?path=dubbo/2.6.11/apache-dubbo-2.6.11-source-release.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="3021-2021-08-23">3.0.2.1 (2021-08-23)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/dubbo/3.0.2.1/apache-dubbo-3.0.2.1-src.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/3.0.2.1/apache-dubbo-3.0.2.1-src.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/3.0.2.1/apache-dubbo-3.0.2.1-src.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="302-2021-08-16">3.0.2 (2021-08-16)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/dubbo/3.0.2/apache-dubbo-3.0.2-src.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/3.0.2/apache-dubbo-3.0.2-src.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/3.0.2/apache-dubbo-3.0.2-src.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="2713-2021-08-05">2.7.13 (2021-08-05)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/dubbo/2.7.13/apache-dubbo-2.7.13-src.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/2.7.13/apache-dubbo-2.7.13-src.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/2.7.13/apache-dubbo-2.7.13-src.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="301-2021-07-02">3.0.1 (2021-07-02)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/dubbo/3.0.1/apache-dubbo-3.0.1-src.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/3.0.1/apache-dubbo-3.0.1-src.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/3.0.1/apache-dubbo-3.0.1-src.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="300-2021-06-16">3.0.0 (2021-06-16)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/dubbo/3.0.0/apache-dubbo-3.0.0-src.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/3.0.0/apache-dubbo-3.0.0-src.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/3.0.0/apache-dubbo-3.0.0-src.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="2712-2021-06-11">2.7.12 (2021-06-11)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/dubbo/2.7.12/apache-dubbo-2.7.12-src.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/2.7.12/apache-dubbo-2.7.12-src.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/2.7.12/apache-dubbo-2.7.12-src.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="2711-2021-05-12">2.7.11 (2021-05-12)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/dubbo/2.7.11/apache-dubbo-2.7.11-src.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/2.7.11/apache-dubbo-2.7.11-src.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/2.7.11/apache-dubbo-2.7.11-src.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="2710-2021-04-08">2.7.10 (2021-04-08)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/dubbo/2.7.10/apache-dubbo-2.7.10-src.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/2.7.10/apache-dubbo-2.7.10-src.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/2.7.10/apache-dubbo-2.7.10-src.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="279-2020-02-23">2.7.9 (2020-02-23)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/dubbo/2.7.9/apache-dubbo-2.7.9-src.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/2.7.9/apache-dubbo-2.7.9-src.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/2.7.9/apache-dubbo-2.7.9-src.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="278-2020-07-28">2.7.8 (2020-07-28)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/dubbo/2.7.8/apache-dubbo-2.7.8-source-release.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/2.7.8/apache-dubbo-2.7.8-source-release.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/2.7.8/apache-dubbo-2.7.8-source-release.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="277-2020-05-18">2.7.7 (2020-05-18)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/dubbo/2.7.7/apache-dubbo-2.7.7-src.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/2.7.7/apache-dubbo-2.7.7-src.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/2.7.7/apache-dubbo-2.7.7-src.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="275-2019-12-29">2.7.5 (2019-12-29)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/dubbo/2.7.5/apache-dubbo-2.7.5-src.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/2.7.5/apache-dubbo-2.7.5-src.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/2.7.5/apache-dubbo-2.7.5-src.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="2741-2019-10-27">2.7.4.1 (2019-10-27)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/dubbo/2.7.4.1/apache-dubbo-2.7.4.1-src.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/2.7.4.1/apache-dubbo-2.7.4.1-src.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/2.7.4.1/apache-dubbo-2.7.4.1-src.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="274-2019-10-19">2.7.4 (2019-10-19)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/dubbo/2.7.4/apache-dubbo-2.7.4-src.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/2.7.4/apache-dubbo-2.7.4-src.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/2.7.4/apache-dubbo-2.7.4-src.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="273-2019-07-19">2.7.3 (2019-07-19)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/dubbo/2.7.3/apache-dubbo-2.7.3-src.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/2.7.3/apache-dubbo-2.7.3-src.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/2.7.3/apache-dubbo-2.7.3-src.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="272-2019-06-06">2.7.2 (2019-06-06)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/dubbo/2.7.2/apache-dubbo-2.7.2-src.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/2.7.2/apache-dubbo-2.7.2-src.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/dubbo/2.7.2/apache-dubbo-2.7.2-src.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="271-2019-03-26">2.7.1 (2019-03-26)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.7.1/apache-dubbo-incubating-2.7.1-src.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.7.1/apache-dubbo-incubating-2.7.1-src.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.7.1/apache-dubbo-incubating-2.7.1-src.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.7.1/apache-dubbo-incubating-2.7.1-bin.zip">binary&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.7.1/apache-dubbo-incubating-2.7.1-bin.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.7.1/apache-dubbo-incubating-2.7.1-bin.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="270-2019-01-29">2.7.0 (2019-01-29)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.7.0/apache-dubbo-incubating-2.7.0-source-release.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.7.0/apache-dubbo-incubating-2.7.0-source-release.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.7.0/apache-dubbo-incubating-2.7.0-source-release.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.7.0/apache-dubbo-incubating-2.7.0-bin-release.zip">binary&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.7.0/apache-dubbo-incubating-2.7.0-bin-release.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.7.0/apache-dubbo-incubating-2.7.0-bin-release.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="267-2019-07-15">2.6.7 (2019-07-15)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://www.apache.org/dyn/closer.lua/dubbo/2.6.7/apache-dubbo-2.6.7-source-release.zip">source&lt;/a> |
&lt;a href="https://www.apache.org/dyn/closer.lua/dubbo/2.6.7/apache-dubbo-2.6.7-source-release.zip.asc">asc&lt;/a> |
&lt;a href="https://www.apache.org/dyn/closer.lua/dubbo/2.6.7/apache-dubbo-2.6.7-source-release.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.apache.org/dyn/closer.lua/dubbo/2.6.7/apache-dubbo-2.6.7-bin-release.zip">binary&lt;/a> |
&lt;a href="https://www.apache.org/dyn/closer.lua/dubbo/2.6.7/apache-dubbo-2.6.7-bin-release.zip.asc">asc&lt;/a> |
&lt;a href="https://www.apache.org/dyn/closer.lua/dubbo/2.6.7/apache-dubbo-2.6.7-bin-release.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="266-2019-03-07">2.6.6 (2019-03-07)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://www.apache.org/dyn/closer.lua/incubator/dubbo/2.6.6/apache-dubbo-incubating-2.6.6-source-release.zip">source&lt;/a> |
&lt;a href="https://www.apache.org/dyn/closer.lua/incubator/dubbo/2.6.6/apache-dubbo-incubating-2.6.6-source-release.zip.asc">asc&lt;/a> |
&lt;a href="https://www.apache.org/dyn/closer.lua/incubator/dubbo/2.6.6/apache-dubbo-incubating-2.6.6-source-release.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.apache.org/dyn/closer.lua/incubator/dubbo/2.6.6/apache-dubbo-incubating-2.6.6-bin-release.zip">binary&lt;/a> |
&lt;a href="https://www.apache.org/dyn/closer.lua/incubator/dubbo/2.6.6/apache-dubbo-incubating-2.6.6-bin-release.zip.asc">asc&lt;/a> |
&lt;a href="https://www.apache.org/dyn/closer.lua/incubator/dubbo/2.6.6/apache-dubbo-incubating-2.6.6-bin-release.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="265-2018-11-23">2.6.5 (2018-11-23)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.6.5/apache-dubbo-incubating-2.6.5-source-release.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.6.5/apache-dubbo-incubating-2.6.5-source-release.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.6.5/apache-dubbo-incubating-2.6.5-source-release.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.6.5/apache-dubbo-incubating-2.6.5-bin-release.zip">binary&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.6.5/apache-dubbo-incubating-2.6.5-bin-release.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.6.5/apache-dubbo-incubating-2.6.5-bin-release.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="264-2018-10-08">2.6.4 (2018-10-08)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.6.4/apache-dubbo-incubating-2.6.4-source-release.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.6.4/apache-dubbo-incubating-2.6.4-source-release.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.6.4/apache-dubbo-incubating-2.6.4-source-release.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.6.4/apache-dubbo-incubating-2.6.4-bin-release.zip">binary&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.6.4/apache-dubbo-incubating-2.6.4-bin-release.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.6.4/apache-dubbo-incubating-2.6.4-bin-release.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="263-2018-09-11">2.6.3 (2018-09-11)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.6.3/apache-dubbo-incubating-2.6.3-source-release.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.6.3/apache-dubbo-incubating-2.6.3-source-release.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.6.3/apache-dubbo-incubating-2.6.3-source-release.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.6.3/apache-dubbo-incubating-2.6.3-bin-release.zip">binary&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.6.3/apache-dubbo-incubating-2.6.3-bin-release.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.6.3/apache-dubbo-incubating-2.6.3-bin-release.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="262-2018-06-07">2.6.2 (2018-06-07)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.6.2/dubbo-incubating-2.6.2-source-release.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.6.2/dubbo-incubating-2.6.2-source-release.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.6.2/dubbo-incubating-2.6.2-source-release.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.6.2/dubbo-incubating-2.6.2-bin-release.zip">binary&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.6.2/dubbo-incubating-2.6.2-bin-release.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/2.6.2/dubbo-incubating-2.6.2-bin-release.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="dubbo-spring-boot-starter">Dubbo Spring Boot Starter&lt;/h2>
&lt;blockquote>
&lt;p>GitHub: &lt;a href="https://github.com/apache/incubator-dubbo-spring-boot-project">https://github.com/apache/incubator-dubbo-spring-boot-project&lt;/a> &lt;br>
发布说明：https://github.com/apache/incubator-dubbo-spring-boot-project/releases&lt;/p>
&lt;/blockquote>
&lt;h3 id="271-2019-04-09">2.7.1 (2019-04-09)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://www.apache.org/dyn/closer.lua/incubator/dubbo/spring-boot-project/2.7.1/apache-dubbo-spring-boot-project-incubating-2.7.1-source-release.zip">source&lt;/a> |
&lt;a href="https://www.apache.org/dyn/closer.lua/incubator/dubbo/spring-boot-project/2.7.1/apache-dubbo-spring-boot-project-incubating-2.7.1-source-release.zip.asc">asc&lt;/a> |
&lt;a href="https://www.apache.org/dyn/closer.lua/incubator/dubbo/spring-boot-project/2.7.1/apache-dubbo-spring-boot-project-incubating-2.7.1-source-release.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.apache.org/dyn/closer.lua/incubator/dubbo/spring-boot-project/2.7.1/apache-dubbo-spring-boot-project-incubating-2.7.1-bin-release.zip">binary&lt;/a> |
&lt;a href="https://www.apache.org/dyn/closer.lua/incubator/dubbo/spring-boot-project/2.7.1/apache-dubbo-spring-boot-project-incubating-2.7.1-bin-release.zip.asc">asc&lt;/a> |
&lt;a href="https://www.apache.org/dyn/closer.lua/incubator/dubbo/spring-boot-project/2.7.1/apache-dubbo-spring-boot-project-incubating-2.7.1-bin-release.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="270-2019-02-14">2.7.0 (2019-02-14)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/incubator/dubbo/spring-boot-project/2.7.0/apache-dubbo-spring-boot-project-incubating-2.7.0-source-release.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/spring-boot-project/2.7.0/apache-dubbo-spring-boot-project-incubating-2.7.0-source-release.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/spring-boot-project/2.7.0/apache-dubbo-spring-boot-project-incubating-2.7.0-source-release.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://archive.apache.org/dist/incubator/dubbo/spring-boot-project/2.7.0/apache-dubbo-spring-boot-project-incubating-2.7.0-bin-release.zip">binary&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/spring-boot-project/2.7.0/apache-dubbo-spring-boot-project-incubating-2.7.0-bin-release.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/spring-boot-project/2.7.0/apache-dubbo-spring-boot-project-incubating-2.7.0-bin-release.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="021-2019-01-27">0.2.1 (2019-01-27)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/incubator/dubbo/spring-boot-project/0.2.1/apache-dubbo-spring-boot-project-incubating-0.2.1-source-release.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/spring-boot-project/0.2.1/apache-dubbo-spring-boot-project-incubating-0.2.1-source-release.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/spring-boot-project/0.2.1/apache-dubbo-spring-boot-project-incubating-0.2.1-source-release.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://archive.apache.org/dist/incubator/dubbo/spring-boot-project/0.2.1/apache-dubbo-spring-boot-project-incubating-0.2.1-bin-release.zip">binary&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/spring-boot-project/0.2.1/apache-dubbo-spring-boot-project-incubating-0.2.1-bin-release.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/spring-boot-project/0.2.1/apache-dubbo-spring-boot-project-incubating-0.2.1-bin-release.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="012-2019-01-27">0.1.2 (2019-01-27)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/incubator/dubbo/spring-boot-project/0.1.2/apache-dubbo-spring-boot-project-incubating-0.1.2-source-release.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/spring-boot-project/0.1.2/apache-dubbo-spring-boot-project-incubating-0.1.2-source-release.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/spring-boot-project/0.1.2/apache-dubbo-spring-boot-project-incubating-0.1.2-source-release.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://archive.apache.org/dist/incubator/dubbo/spring-boot-project/0.1.2/apache-dubbo-spring-boot-project-incubating-0.1.2-bin-release.zip">binary&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/spring-boot-project/0.1.2/apache-dubbo-spring-boot-project-incubating-0.1.2-bin-release.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/spring-boot-project/0.1.2/apache-dubbo-spring-boot-project-incubating-0.1.2-bin-release.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="dubbo-admin">Dubbo Admin&lt;/h2>
&lt;blockquote>
&lt;p>GitHub: &lt;a href="https://github.com/apache/incubator-dubbo-admin">https://github.com/apache/incubator-dubbo-admin&lt;/a> &lt;br>
发布说明：https://github.com/apache/incubator-dubbo-admin/releases&lt;/p>
&lt;/blockquote>
&lt;h3 id="01-2019-02-15">0.1 (2019-02-15)&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="https://archive.apache.org/dist/incubator/dubbo/dubbo-ops/0.1/apache-dubbo-ops-incubating-0.1-source-release.zip">source&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/dubbo-ops/0.1/apache-dubbo-ops-incubating-0.1-source-release.zip.asc">asc&lt;/a> |
&lt;a href="https://archive.apache.org/dist/incubator/dubbo/dubbo-ops/0.1/apache-dubbo-ops-incubating-0.1-source-release.zip.sha512">sha512&lt;/a>&lt;/li>
&lt;/ul></description></item></channel></rss>