Publishing REST-style Services

Demonstrates how to access services published via triple and dubbo protocols using standard rest requests.

The “rest protocol” discussed in this article is not a true protocol implementation, but rather a way to make the triple protocol support direct access via REST-style HTTP requests. We will demonstrate how to access Dubbo services using REST requests.

Note

Starting from Dubbo version 3.3, the REST protocol has been moved to the extensions library, with the triple protocol providing more comprehensive support for REST. The built-in protocol implementations now only include triple and dubbo.
Therefore, when we mention REST, we are referring to the REST access support capabilities of the triple protocol. For more details, see Triple REST User Manual

When discussing the triple protocol example, we mentioned that the triple protocol supports direct access in application/json format:

  1. curl \
  2. --header "Content-Type: application/json" \
  3. --data '["Dubbo"]' \
  4. http://localhost:50052/org.apache.dubbo.samples.api.GreetingsService/sayHi/

If you find the above http://localhost:50052/org.apache.dubbo.samples.api.GreetingsService/sayHi format of path request not user-friendly, you can customize HTTP request paths and methods through annotations. Currently, three annotation formats are supported: built-in, Spring Web, and JAX-RS. For the complete code of the following example, refer to dubbo-samples-triple-rest.

Download and Run the Example

  1. # Get the example code
  2. git clone --depth=1 https://github.com/apache/dubbo-samples.git
  3. cd dubbo-samples/2-advanced/dubbo-samples-triple-rest/dubbo-samples-triple-rest-basic
  4. # Run directly
  5. mvn spring-boot:run
  6. # Or package and run
  7. mvn clean package -DskipTests
  8. java -jar target/dubbo-samples-triple-rest-basic-1.0.0-SNAPSHOT.jar

Of course, you can also import the project directly with an IDE and execute org.apache.dubbo.rest.demo.BasicRestApplication#main to run it, and use breakpoints to debug and deepen your understanding of the principles.

Example Code

  1. // Service Interface
  2. package org.apache.dubbo.rest.demo;
  3. import org.apache.dubbo.remoting.http12.rest.Mapping;
  4. import org.apache.dubbo.remoting.http12.rest.Param;
  5. public interface DemoService {
  6. String hello(String name);
  7. @Mapping(path = "/hi", method = HttpMethods.POST)
  8. String hello(User user, @Param(value = "c", type = ParamType.Header) int count);
  9. }
  10. // Service Implementation
  11. @DubboService
  12. public class DemoServiceImpl implements DemoService {
  13. @Override
  14. public String hello(String name) {
  15. return "Hello " + name;
  16. }
  17. @Override
  18. public String hello(User user, int count) {
  19. return "Hello " + user.getTitle() + ". " + user.getName() + ", " + count;
  20. }
  21. }
  22. // Model
  23. @Data
  24. public class User {
  25. private String title;
  26. private String name;
  27. }

Testing the Basic Service

  1. curl -v "http://127.0.0.1:8081/org.apache.dubbo.rest.demo.DemoService/hello?name=world"
  2. # Output looks like
  3. #> GET /org.apache.dubbo.rest.demo.DemoService/hello?name=world HTTP/1.1
  4. #> Host: 127.0.0.1:8081
  5. #> User-Agent: curl/8.7.1
  6. #> Accept: */*
  7. #>
  8. #* Request completely sent off
  9. #< HTTP/1.1 200 OK
  10. #< content-type: application/json
  11. #< alt-svc: h2=":8081"
  12. #< content-length: 13
  13. #<
  14. #"Hello world"

Code Explanation:
You can see “Hello world” was outputted, and the double quotes indicate the default output content-type was application/json.
From this example, you can understand that Triple exports the service to /{serviceInterface}/{methodName} path by default and supports passing parameters through the URL.

Testing the Advanced Service

  1. curl -v -H "c: 3" -d 'name=Yang' "http://127.0.0.1:8081/org.apache.dubbo.rest.demo.DemoService/hi.txt?title=Mr"
  2. # Output looks like
  3. #> POST /org.apache.dubbo.rest.demo.DemoService/hi.txt?title=Mr HTTP/1.1
  4. #> Host: 127.0.0.1:8081
  5. #> User-Agent: curl/8.7.1
  6. #> Accept: */*
  7. #> c: 3
  8. #> Content-Length: 9
  9. #> Content-Type: application/x-www-form-urlencoded
  10. #>
  11. #* upload completely sent off: 9 bytes
  12. #< HTTP/1.1 200 OK
  13. #< content-type: text/plain
  14. #< alt-svc: h2=":8081"
  15. #< content-length: 17
  16. #<
  17. #Hello Mr. Yang, 3

Code Explanation:
The output “Hello Mr. Yang, 3” shows no double quotes because the output is requested as text/plain by specifying the suffix txt.
This example illustrates how to customize paths via the Mapping annotation and customize parameter sources via the Param annotation, supporting parameters passed through the post body or URL; for detailed instructions, see: Basic User Guide

Observing Logs

You can open debug logs to understand the startup and response request process of REST.

  1. logging:
  2. level:
  3. "org.apache.dubbo.rpc.protocol.tri": debug
  4. "org.apache.dubbo.remoting": debug

Once enabled, you can observe the Rest mapping registration and request-response process.

  1. # Register mapping
  2. DEBUG o.a.d.r.p.t.TripleProtocol : [DUBBO] Register triple grpc mapping: 'org.apache.dubbo.rest.demo.DemoService' -> invoker[tri://192.168.2.216:8081/org.apache.dubbo.rest.demo.DemoService]
  3. INFO .r.p.t.r.m.DefaultRequestMappingRegistry : [DUBBO] BasicRequestMappingResolver resolving rest mappings for ServiceMeta{interface=org.apache.dubbo.rest.demo.DemoService, service=DemoServiceImpl@2a8f6e6} at url [tri://192.168.2.216:8081/org.apache.dubbo.rest.demo.DemoService]
  4. DEBUG .r.p.t.r.m.DefaultRequestMappingRegistry : [DUBBO] Register rest mapping: '/org.apache.dubbo.rest.demo.DemoService/hi' -> mapping=RequestMapping{name='DemoServiceImpl#hello', path=PathCondition{paths=[org.apache.dubbo.rest.demo.DemoService/hi]}, methods=MethodsCondition{methods=[POST]}}, method=MethodMeta{method=org.apache.dubbo.rest.demo.DemoService.hello(User, int), service=DemoServiceImpl@2a8f6e6}
  5. DEBUG .r.p.t.r.m.DefaultRequestMappingRegistry : [DUBBO] Register rest mapping: '/org.apache.dubbo.rest.demo.DemoService/hello' -> mapping=RequestMapping{name='DemoServiceImpl#hello~S', path=PathCondition{paths=[org.apache.dubbo.rest.demo.DemoService/hello]}}, method=MethodMeta{method=org.apache.dubbo.rest.demo.DemoService.hello(String), service=DemoServiceImpl@2a8f6e6}
  6. INFO .r.p.t.r.m.DefaultRequestMappingRegistry : [DUBBO] Registered 2 REST mappings for service [DemoServiceImpl@44627686] at url [tri://192.168.2.216:8081/org.apache.dubbo.rest.demo.DemoService] in 11ms
  7. # Request Response
  8. DEBUG .a.d.r.p.t.r.m.RestRequestHandlerMapping : [DUBBO] Received http request: DefaultHttpRequest{method='POST', uri='/org.apache.dubbo.rest.demo.DemoService/hi.txt?title=Mr', contentType='application/x-www-form-urlencoded'}
  9. DEBUG .r.p.t.r.m.DefaultRequestMappingRegistry : [DUBBO] Matched rest mapping=RequestMapping{name='DemoServiceImpl#hello', path=PathCondition{paths=[/org.apache.dubbo.rest.demo.DemoService/hi]}, methods=MethodsCondition{methods=[POST]}}, method=MethodMeta{method=org.apache.dubbo.rest.demo.DemoService.hello(User, int), service=DemoServiceImpl@2a8f6e6}
  10. DEBUG .a.d.r.p.t.r.m.RestRequestHandlerMapping : [DUBBO] Content-type negotiate result: request='application/x-www-form-urlencoded', response='text/plain'
  11. DEBUG .d.r.h.AbstractServerHttpChannelObserver : [DUBBO] Http response body is: '"Hello Mr. Yang, 3"'
  12. DEBUG .d.r.h.AbstractServerHttpChannelObserver : [DUBBO] Http response headers sent: {:status=[200], content-type=[text/plain], alt-svc=[h2=":8081"], content-length=[17]}

Practical Application Scenarios

Next, let’s look at what real problems can be solved with triple protocol supporting REST format access.

Spring Cloud Interoperation

First, the initial scenario is to enable interoperability between the Dubbo system and HTTP microservice systems.

Imagine you are in charge of a business line, and you have a microservice cluster developed based on Dubbo, where services communicate using the triple binary protocol. There is another important business within the company running on a microservice cluster developed based on Spring Cloud, where the services communicate using HTTP+JSON. Now you want to enable communication between these two businesses; how can services interact? The triple protocol supporting REST format access can solve this problem, allowing the Dubbo microservice cluster to communicate internally using the triple binary protocol while externally using the REST request format provided by triple.

Gateway Traffic Access

Another very valuable scenario for supporting REST format access is that it facilitates gateway traffic access. Accessing binary-format RPC protocols has always been a challenge. Previously, Dubbo provided generic calls to solve this problem; gateways could implement HTTP -> Dubbo protocol conversion to access backend microservice clusters.

Now, with support for REST format, decentralized access can be achieved without any gateway protocol conversion. For more details, see HTTP Gateway Traffic Access.

Feedback

Was this page helpful?

Yes No

Last modified September 30, 2024: Update & Translate Overview Docs (#3040) (d37ebceaea7)