By Youwei Chen, Momo R&D Engineer and Apache Dubbo PMC
When developing microservices, traditional RPC services often form the underlying layer, with browsers, mobile terminals, external servers, testing environments, curl, and more comprising the upper layer. We might assemble our RPC layer, known as BFF, through an external server like Tomcat. Alternatively, if we don't have BFF, our RPC would serve as an external service. However, since browsers need access, we require a gateway such as APISIX or ShenYu, which are HTTP gateways.
The above figure shows our process, but it presents certain challenges.
For lightweight services, a forwarding layer alone would suffice. However, whether we use a gateway or a web server for forwarding can be troublesome.
Additionally, most RPC services are binary-based and cannot be easily tested locally. To address this, our company might develop a backend or intermediate proxy for testing. Nevertheless, testing locally remains unfeasible unless the proxy is deployed in a testing environment at least.
Overall, these two issues result in lower user-friendliness and higher development costs due to non-business-related repetitive tasks.
Based on the above two problems, let's introduce the Triple protocol.
To address the aforementioned challenges, let's introduce the Triple protocol. First, let's discuss the previous generation protocol and the reasons for its release. As we know, Dubbo is based on the Dubbo protocol, which relies on TCP and comprises a single packet. However, due to its packet design, the gateway cannot perform special rule judgments, filtering, and other operations. Although it's not impossible, decompressing the packet completely to perform necessary operations and then reassembling it would sacrifice performance, which is generally unacceptable.
Hence, we contemplated separating the original data from the actual packet. With HTTP readily available and gRPC being a mainstream industry protocol, our goal was to make HTTP compatible with gRPC. Currently, gRPC uses an Interface Definition Language (IDL), but IDL poses challenges, particularly on the Java side, where writing interfaces and defining packages can be cumbersome. The Go programming language side handles this better, as developers are more accustomed to this development model.
To address these issues, we developed the Triple protocol. Firstly, it is compatible with gRPC, allowing for complete interoperability. Secondly, it is compatible with our own methods of defining interfaces. While some performance is sacrificed, ease of use is improved. Moreover, RPC is generally not the bottleneck of business applications, as most bottlenecks reside in the database (DB) layer.
However, another issue remains. Despite compatibility with gRPC, which is based on TCP, our system cannot be accepted if the frontend or other third-party systems only support HTTP.
Based on this, we plan to introduce a new Triple protocol. In order to achieve this, we have referred to protocols such as gRPC, gRPC Web, and general HTTP. These protocols provide support for browser access, streaming, and can run on both HTTP/1 and HTTP/2 protocols. While HTTP/3 is not widely promoted at the moment, it will be supported in the future.
The final implementation of the design is entirely based on HTTP and is user-friendly, developer-friendly, and easy to debug. It can be accessed through a simple browser or through curl, especially for unary RPC. Additionally, it is fully compatible with gRPC, so businesses using HTTP do not need to worry about compatibility or signing protocols. To ensure stability, we will only use popular network libraries in the industry, such as Java's native and Go's basic net packages.
Both the Triple and gRPC protocols are based on HTTP, but gRPC is based on HTTP/2 while Triple is based on both HTTP/1 and HTTP/2.
While we are compatible with gRPC, we have also added some additional features for ease of use. For example, we support the request format of Application/Json and cURL access. In the previous version of the protocol, we had a secondary serialization process to support traditional interface definitions. We now use a special content type to determine the structure of our body, eliminating the need for secondary serialization. This feature can also be extended to implement or expand on all the functions of HTTP in the Triple protocol.
After adopting the Triple protocol, our development process has changed. If there is no need for assembly or an outer proxy, the access process can be simplified to external request browsers, the server of the other party, curl, or direct testing on the server. There are no compatibility issues when communicating with other gRPCs, and a layer of complexity is removed, which greatly benefits most users who do not require this particular scenario.
Initially, the Triple protocol was compatible with gRPC and based solely on HTTP/2. As HTTP/2 has streaming capabilities, it naturally supports streaming. However, the new version of the protocol also supports streaming in HTTP/1, but due to the limitations of HTTP/1, it can only support server streaming. Its implementation relies on the server push feature of HTTP/1.
There is no need to discuss client streaming and bidirectional streaming. However, it is worth noting that bidirectional streaming is not available on the Java side in terms of coding, but it is possible to implement it.
The Triple protocol supports two definition methods: IDL definition and direct definition. Direct definition allows for synchronization, asynchronization, and handwriting. It also allows for more extreme cases, such as using IDL to generate protobuf classes without defining the service. In this case, it is sufficient to use the generated request and response classes. The Triple protocol will automatically determine whether the interface uses protobuf for transmission or not.
The server is responsible for implementing its services. In the example above, I directly used the API assembly method. In actual business scenarios, annotations or XML may be used.
Since we support the standard HTTP protocol, testing becomes simplified in theory. Additionally, because we support gRPC, we can use gRPC curl to call our services. However, it is important to note that the reflection service needs to be enabled manually as it is not enabled by default. With the reflection service, we can obtain the source data of the interface and convert it into protobuf format through Json. Alternatively, we can directly call it using Application/Json. It is also worth mentioning that Streaming can be used under HTTP/1.
Furthermore, because we support HTTP, theoretically all third-party HTTP clients can be called. Additionally, after registering, you can use Dubbo's Admin to perform testing.
There is no essential difference between the two call sides: POJO and IDL.
Now that we have the Triple protocol, it is important to have a framework to support it. Service governance is a fundamental aspect of microservices. Therefore, service governance is an essential part of microservices.
Triple is just one of the protocols in Dubbo. Of course, you can also use the original Dubbo protocol or other protocols for compatibility. Additionally, multiple protocols can be enabled on the same port as needed.
Dubbo also provides implementations in multiple languages for Triple. Currently, it can be implemented in Rust, Go, Java, JS, node, and Python. This eliminates the need for users to implement it according to the specifications of the experimental protocol. However, if there are customization requirements, such as internal frameworks, they can be implemented according to the specifications.
Dubbo integrates well with service frameworks. In theory, customers do not need to worry about service definition, service governance, service registration, and discovery during the development process, especially on the Java side. It is ready to use out-of-the-box.
Dubbo provides a rich ecosystem, including third-party ecosystems like Nacos and Zookeeper. Therefore, there is no need for innovation, just the introduction of corresponding packages.
The provided example showcases how the Triple protocol can be used for service registration. You can select Nacos, Zookeeper, or Kubernetes, and on the left side, there is a Client and a Server that can be called in this way.
Let's look at the implementation in admin. It's worth mentioning that our admin has also been refactored in the new version, and it is implemented in Go. Look forward to it.
We often encounter the need for canary releases or traffic routing. We can send a tag governance rule from the admin and tag some instances. Then, the traffic carrying those tags will be passed through from the entry point, achieving traffic routing for the entire link.
Cloud-Native Devops Best Practices(1): Continuous Integration (CI) + OpenKruise Image Pre-download
503 posts | 48 followers
FollowAlibaba Clouder - December 22, 2020
Alibaba Cloud Native Community - September 12, 2023
Alibaba Clouder - September 21, 2017
Alibaba Clouder - October 20, 2020
Aliware - May 24, 2021
Alibaba Clouder - May 17, 2021
503 posts | 48 followers
FollowA public Internet gateway for flexible usage of network resources and access to VPC.
Learn MoreMSE provides a fully managed registration and configuration center, and gateway and microservices governance capabilities.
Learn MoreExplore Web Hosting solutions that can power your personal website or empower your online business.
Learn MoreMulti-source metrics are aggregated to monitor the status of your business and services in real time.
Learn MoreMore Posts by Alibaba Cloud Native Community