0 to prepare

  1. Install registries: Dubbo-registry-simple, which comes with Zookeeper and Dubbox.
  2. Install DubboKeeper monitoring: https://github.com/dubboclub/dubbokeeper;

The above two preparation, is not the focus of this article, do not do a detailed introduction, installation is relatively simple, consult the relevant information to install learning.

1 the service side

1.2 Interface Definition

  1. Create Maven module: mSA-demo-api

  2. Msa-demo-api: Configures pom.xml

    <! -- Dubbox dependency -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>dubbo</artifactId>
        <version>2.8.4</version>
    </dependency>
    <! -- END -->
    
    <! If you want to use Lombok -->
    <dependency>
         <groupId>org.projectlombok</groupId>
         <artifactId>lombok</artifactId>
    </dependency>
    <! -- END -->
    
    <! -- If you want to use reST-style remote call -->
    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-jaxrs</artifactId>
        <version>3.0.7. The Final</version>
    </dependency>
    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-client</artifactId>
        <version>3.0.7. The Final</version>
    </dependency>
    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
        <version>1.0.0.ga</version>
    </dependency>
    <! -- END -->
    
    <! If you want to use JSON serialization -->
    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-jackson-provider</artifactId>
        <version>3.0.7. The Final</version>
    </dependency>
    <! -- END -->
    
    <! If you want to use XML serialization -->
    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-jaxb-provider</artifactId>
        <version>3.0.7. The Final</version>
    </dependency>
    <! -- END -->
    
    <! Netty Server -->
    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-netty</artifactId>
        <version>3.0.7. The Final</version>
    </dependency>
    <! -- END -->
    
    <! Sun HTTP Server -->
    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-jdk-http</artifactId>
        <version>3.0.7. The Final</version>
    </dependency>
    <! -- END -->
    
    <! Tomcat Server -->
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-core</artifactId>
        <version>8.0.11</version>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-logging-juli</artifactId>
        <version>8.0.11</version>
    </dependency>
    <! -- END -->
    
    <! Kyro serialization -->
    <dependency>
        <groupId>com.esotericsoftware.kryo</groupId>
        <artifactId>kryo</artifactId>
        <version>2.24.0</version>
    </dependency>
    <dependency>
        <groupId>de.javakaffee</groupId>
        <artifactId>kryo-serializers</artifactId>
        <version>0.26</version>
    </dependency>
    <! -- END -->
    
    <! -- If you want to use FST serialization -->
    <dependency>
        <groupId>de.ruedigermoeller</groupId>
        <artifactId>fst</artifactId>
        <version>1.55</version>
    </dependency>
    <! -- END -->
    
    <! If you want to serialize with Jackson -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.3.3</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.3.3</version>
    </dependency>
    <! -- END -->
    Copy the code

    Starting from Dubbox-2.8.4, all dependency libraries will be used in the same way as dubbo: if you want to use REST, Kyro, FST, Jackson, etc., you need to manually add dependencies.

  3. Define the interface: userService.java

    / * * *@author TaoBangren
     * @version 1.0
     * @since2017/5/17 9:26 am */
    public interface UserService {
        User getUser(Long id);
        Long registerUser(User user);
    }
    Copy the code
  4. Define the REST interface: AnotherUserRestService. Java

    package com.alibaba.dubbo.demo.user.facade;
    import com.alibaba.dubbo.demo.user.User;
    import com.alibaba.dubbo.rpc.protocol.rest.support.ContentType;
    import javax.validation.constraints.Min;
    import javax.ws.rs.*;
    import javax.ws.rs.core.MediaType;
    / * * *@author TaoBangren
     * @version 1.0
     * @since2017/5/17 9:26 am */
    // Developing REST services in Dubbo is mostly configured using JAX-RS annotations,
    // In the above examples, we put the annotation in the implementation class of the service. But the truth is, I
    // We can also put annotations on the service's interface. The two approaches are completely equivalent.
    //
    // In general, we recommend putting annotations in the service implementation class, so that annotations and
    // Java implementation code location is closer, easier to develop and maintain. And more importantly, we tend to
    // To avoid contamination of the interface, keep the interface pure and wide applicability.
    // However, as described later, if we want to access the service using a consumer developed directly by Dubbo, the annotation must be placed on the interface.
    // If both the interface and the implementation class add annotations, the annotation configuration of the implementation class takes effect, and the annotations on the interface are ignored.
    @Path("u")
    @Consumes({MediaType.APPLICATION_JSON, MediaType.TEXT_XML})
    @Produces({ContentType.APPLICATION_JSON_UTF_8, ContentType.TEXT_XML_UTF_8})
    public interface AnotherUserRestService {
    
          @GET
          @Path("{id : \\d+}")
          // In the case of a REST service that supports multiple data formats simultaneously, according to the JAX-RS standard,
          // MIME headers (content-type and Accept) are used to specify which format of data you want to use.
          // @Produces({ContentType.APPLICATION_JSON_UTF_8, ContentType.TEXT_XML_UTF_8})
          In Dubbo, however, we also automatically support the current industry-common way of specifying a URL suffix (.json and.xml)
          // The desired data format. For example, after add the annotation, direct access to http://localhost:8888/users/1001.json
          / / it means using the json format, direct access to the http://localhost:8888/users/1002.xml said in XML format,
          // Much simpler and more intuitive than using HTTP headers. REST apis for Twitter, Twitter, and so on take this approach.
          // If you don't add HTTP headers or suffixing, Dubbo's REST will prioritize the data format that is first listed in the annotation definition above.
          // Note: To support XML data, the annotation can be either MediaType.TEXT_XML or MediaType.APPLICATION_XML,
          // But TEXT_XML is more commonly used, and if you want to specify the data format using the above URL suffix, only TEXT_XML will work.
          User getUser(@PathParam("id") @Min(1L) Long id);
    
          @POST
          @Path("register")
          RegistrationResult registerUser(User user);
    }
    Copy the code
  5. Define entities: user.java

    package com.alibaba.dubbo.demo.user;
    import lombok.Data;
    import org.codehaus.jackson.annotate.JsonProperty;
    import javax.validation.constraints.Min;
    import javax.validation.constraints.NotNull;
    import javax.validation.constraints.Size;
    import javax.xml.bind.annotation.XmlAccessType;
    import javax.xml.bind.annotation.XmlAccessorType;
    import javax.xml.bind.annotation.XmlElement;
    import javax.xml.bind.annotation.XmlRootElement;
    import java.io.Serializable;
    / * * *@author TaoBangren
     * @version 1.0
     * @since2017/5/17 9:26 am */
    // Since JAX-RS implementations generally use the standard JAXB (Java API for XML Binding) to serialize and deserialize XML format data,
    // So we need to add a class-level JAXB annotation(@xmlRootelement) for each object to be transferred with XML, otherwise serialization will fail.
    @Data
    @XmlRootElement
    @XmlAccessorType(XmlAccessType.FIELD)
    public class User implements Serializable {
    
          @NotNull
          @Min(1L)
          private Long id;
    
          // The underlying implementation of REST automatically serializes/deserializes between service objects and JSON/XML data formats.
          // However, in some scenarios, if the automatic conversion is not enough, you can customize it.
          // The REST implementation of Dubbo uses JAXB for XML serialization, Jackson for JSON serialization,
          // So you can customize the mapping by adding JAXB or Jackson annotations to the object.
          @JsonProperty("username")
          @XmlElement(name = "username")
          @NotNull
          @Size(min = 6, max = 50)
          private String name;
    }
    Copy the code
  6. Define the REST response result entity: RegistrationResult.java

    package com.alibaba.dubbo.demo.user.facade;
    import lombok.Data;
    import javax.xml.bind.annotation.XmlRootElement;
    import java.io.Serializable;
    / * * *@author TaoBangren
     * @version 1.0
     * @since2017/5/17 9:26 am */
    // In addition, if the return value in the service method is Java primitive type (such as int, long, float, double, etc.),
    // It's better to add a wrapper object to them because JAXB can't serialize primitive types directly. This not only solves the problem of XML serialization,
    // And make the returned data conform to XML and JSON specifications.
    // This wrapper Object actually makes use of the so-called Data Transfer Object (DTO) pattern, which also allows for more useful customization of the Data being transferred.
    @Data
    @XmlRootElement
    public class RegistrationResult implements Serializable {
          private Long id;
    }
    Copy the code

1.3 Service Implementation

  1. Create a Maven module: msa-demo-provider

  2. Msa-demo-provider: configures POM.xml

    <! -- Module depends on START -->
    <dependency>
         <groupId>com.alibaba</groupId>
         <artifactId>msa-demo-api</artifactId>
         <version>1.0 the SNAPSHOT</version>
    </dependency>
    <! -- Module depends on END -->
    Copy the code
  3. Implement the UserService interface: UserServicePl.java

    package com.alibaba.dubbo.demo.user;
    import lombok.extern.slf4j.Slf4j;
    import java.util.concurrent.atomic.AtomicLong;
    / * * *@author TaoBangren
     * @version 1.0
     * @since2017/5/17 9:26 am */
    @Slf4j
    public class UserServiceImpl implements UserService {
          private final AtomicLong idGen = new AtomicLong();
          public User getUser(Long id) {
              User user = new User();
              user.setId(id);
              user.setName("username" + id);
              return user;
          }
      
          public Long registerUser(User user) {
              // System.out.println("Username is " + user.getName());
              returnidGen.incrementAndGet(); }}Copy the code
  4. Realize the REST interface AnotherUserRestService: AnotherUserRestServiceImpl. Java

    package com.alibaba.dubbo.demo.user.facade;
    import com.alibaba.dubbo.demo.user.User;
    import com.alibaba.dubbo.demo.user.UserService;
    import com.alibaba.dubbo.rpc.RpcContext;
    import lombok.extern.slf4j.Slf4j;
    / * * *@author TaoBangren
     * @version 1.0
     * @since2017/5/17 9:26 am */
    @Slf4j
    public class AnotherUserRestServiceImpl implements AnotherUserRestService {
    
          private UserService userService;
    
          public void setUserService(UserService userService) {
              this.userService = userService;
          }
    
          public User getUser(Long id) {
              System.out.println("Client name is " + RpcContext.getContext().getAttachment("clientName"));
              System.out.println("Client impl is " + RpcContext.getContext().getAttachment("clientImpl"));
              return userService.getUser(id);
          }
    
          public RegistrationResult registerUser(User user) {
              Long id = userService.registerUser(user);
              RegistrationResult registrationResult = new RegistrationResult();
              registrationResult.setId(id);
              returnregistrationResult; }}Copy the code
  5. Dubbox integrates with Spring: msa-demo-provider.xml

     <?xml version="1.0" encoding="UTF-8"? >
     <beans xmlns="http://www.springframework.org/schema/beans"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
         xsi:schemaLocation="Http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
    
         <! -- Current application configuration -->
         <dubbo:application name="msa-demo-provider" owner="tbr" organization="tbr"/>
         <dubbo:monitor address="x.x.x.x:20884"/>
    
         <! -- Multiple registries configuration, vertical indicates that multiple registries are connected at the same time, and multiple cluster addresses in the same registry are separated by commas -->
         <dubbo:registry protocol="zookeeper" address="x.x.x.x:2181,x.x.x.x:2181,x.x.x.x:2181"/>
         <dubbo:protocol name="dubbo" port="20880" serialization="kryo"/>
    
         <! -- 1. Embedded Jetty is used as rest Server, and if the server attribute is not configured, rest protocol is also used by default jetty. Jetty is a very mature Java Servlet container and has been well integrated with Dubbo (currently only Jetty and tomcat, TJWS and Dubbo monitoring system are seamlessly integrated among the five embedded servers), so, If your Dubbo system is a standalone process, you can simply default to Jetty. <dubbo:protocol name="rest" server="jetty"/> 2. The configuration uses embedded Tomcat to do rest Server. REST performs much better on embedded Tomcat than jetty (see benchmarks below), and tomcat is recommended for scenarios where high performance is required. <dubbo:protocol name="rest" server="tomcat"/> 3. The embedded NetTY is used as the REST Server. <dubbo:protocol name="rest" server="netty"/> 4. The configuration selects embedded TJWS or Sun HTTP Server as rest Server. Both server implementations are very lightweight, making them easy to use for quick startup in integration testing and, of course, in low-load production environments. Note: TJWS has been deprecated because it does not work well with the Servlet 3.1 API. <dubbo:protocol name="rest" server="tjws"/> <dubbo:protocol name="rest" server="sunhttp"/> 5. <dubbo:protocol name="rest" server="servlet"/> 6. By setting up the Server as a servlet, Dubbo uses the servlet container of the external application server as the REST Server. Also, add the following configuration to the web. XML of the Dubbo system:  <web-app> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/classes/META-INF/spring/dubbo-demo-provider.xml</param-value> </context-param> <listener> <listener-class>com.alibaba.dubbo.remoting.http.servlet.BootstrapListener</listener-class> </listener> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>com.alibaba.dubbo.remoting.http.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app> that is, dubbo's BootstrapListener and DispatherServlet must be added to web.xml, To complete the integration of Dubbo's REST functionality with external servlet containers. You can still stick with embedded Server in this scenario, but the servlet container of the external application server is often more powerful than embedded Server (especially if you are deploying to the more robust and scalable WebLogic, WebSphere, etc.). In addition, it is also convenient for unified management and monitoring on application servers. If dubbo REST is deployed to external Tomcat and server="servlet" is configured to enable external Tomcat as the underlying implementation of REST Server, it is best to add the following configuration to Tomcat:  <Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol" connectionTimeout="20000" redirectPort="8443" minSpareThreads="20" enableLookups="false" maxThreads="100" maxKeepAliveRequests="-1" KeepAliveTimeout ="60000"/> maxKeepAliveRequests="-1". This configuration ensures that Tomcat always enables HTTP long connections to improve REST call performance. Note, however, that always enabling long connections is not necessarily the best practice if the REST consumer is not constantly invoking REST services. In addition, always enable long connection is generally not suitable for ordinary WebApps, and is more suitable for rPC-like scenarios. Therefore, for high performance, dubbo REST and normal Web applications should not be mixed in Tomcat and should be deployed in a separate instance. 7. Note: If you load Spring ContextLoaderListener with spring ContextLoaderListener, you must ensure that the BootstrapListener configuration is before ContextLoaderListener, otherwise dubbo initialization will fail. -->
     
         <! -- 1. Set a basic relative path that is applicable to all REST services. Context Path is commonly used in Java Web applications. <dubbo: Protocol Name ="rest" port="8888" KeepAlive ="true" server="netty" IOThreads ="5" threads="100" contextpath="services"/> 2. <dubbo:protocol name=" REST "threads="500"/> Note: The current thread pool Settings only take effect if server="netty" or server="jetty" or server="tomcat". In addition, if server="servlet", this thread pool setting is also invalid because the external application server is enabled as rest server, which is not controlled by Dubbo. <dubbo:protocol name="rest" IOThreads ="5" threads="100"/> 3. Note: If you are using an external application server for rest Server, configure: <dubbo:protocol name="rest" port="8888" contextPath ="services" server="servlet"/> This parameter must be consistent with the port of the external application server and the context path of the DispatcherServlet (that is, the WebApp Path plus the Servlet URL pattern). < Dubbo :protocol name="rest" keepalive="false"/> This configuration currently takes effect only for server="netty" and server="tomcat". 5. Set the maximum number of HTTP connections that can be received by the server provider to prevent the REST server from being overwhelmed by too many connections as a basic self-protection mechanism. <dubbo:protocol name=" REST "ACCEPTS ="500" server="tomcat/> Note: this configuration currently only works for server="tomcat". 6. If the consumer of the REST service is also a Dubbo system, you can set the maximum timeout period for the consumer to call the REST service and the maximum number of HTTP connections that each consumer can open, as other Dubbo RPC mechanisms do. <dubbo:service interface=" XXX "ref=" XXX" protocol="rest" timeout="2000" connections="10"/> <dubbo: Reference ID =" XXX "interface=" XXX" timeout="2000" connections="10"/> However, it is generally recommended to configure this configuration on the service provider. According to the official dubbo document, "Configure as many attributes on the Consumer side of the Provider as possible to make the Provider implementer think about the characteristics and quality of service of the Provider from the beginning." Note: If Dubbo's REST service is published for use by non-Dubbo clients, the configuration here on <dubbo:service/> is completely invalid because such clients are not controlled by Dubbo. 7. Dubbo's REST supports GZIP compression of request and response data to reduce network transfer time and bandwidth footprint, but this approach also increases CPU overhead. -->
    
         <! Use tomcat server 2. Use REST to expose services on port 8888 3. Dubbo REST also supports JAX-RS Filter and Interceptor to facilitate customized interception of REST request and response processes. Filter is used to access and set HTTP request and response parameters, URIs, and so on. For example, the Cachecontrolfilter. Java Interceptor is used to access and modify the input and output byte streams. For example, manually add GZIP compression. Such as: GZIPWriterInterceptor. Java 4. In standard JAX-RS applications, we typically add @Provider annotations to filters and interceptors, and jax-RS Runtime automatically finds and enables them. In Dubbo, we register filters and interceptors.5 by adding XML configuration. Here, we can add all three types of Filter, Interceptor, and DynamicFuture objects to the Extension attribute, separated by commas. (DynamicFuture is another interface that allows you to enable filters and interceptors more dynamically. Google it if you're interested.) 6. Of course, Dubbo also supports the Filter concept, but the filters and Interceptor we are discussing here are closer to the bottom of the protocol implementation, allowing for more low-level customization than dubbo's filters. Note: The XML attribute here is called extension, not interceptor or filter, because in addition to interceptor and filter, we will add more extension types in the future. 7. If the REST consumer is also a Dubbo system (see discussion below), you can similarly configure the Interceptor and Filter for the consumer. However, in JAX-RS, the Filter on the consumer side and the Filter on the provider side are two different interfaces. For example, in the previous example, the server side is ContainerResponseFilter interface, while the consumer side is ClientResponseFilter. 8. Dubbo REST also supports THE JAX-RS standard ExceptionMapper. Can be used to customize the HTTP response that should be returned after a particular exception occurs. 9. Dubbo REST supports the output of header fields and body messages in all HTTP requests and responses. LoggingFilter -->
         <dubbo:protocol name="rest" port="8888" threads="500" contextpath="services" server="tomcat" accepts="500"
                     extension="com.alibaba.dubbo.demo.extension.TraceInterceptor, com.alibaba.dubbo.demo.extension.TraceFilter, com.alibaba.dubbo.demo.extension.ClientTraceFilter, com.alibaba.dubbo.demo.extension.DynamicTraceBinding, com.alibaba.dubbo.demo.extension.CustomExceptionMapper, com.alibaba.dubbo.rpc.protocol.rest.support.LoggingFilter"/>
    
         <! -- use the external tomcat or other server with the servlet approach; the port and contextpath must be exactly the same as those in external server <dubbo:protocol name="rest" port="8888" contextpath="services" server="servlet"/> -->
     
         <dubbo:protocol name="http" port="8889"/>
         <dubbo:protocol name="hessian" port="8890"/>
         <dubbo:protocol name="webservice" port="8892"/>
      
         <! Declare the service interface to be exposed -->
         <dubbo:service interface="com.alibaba.dubbo.demo.user.UserService" ref="userService" protocol="dubbo" group="xmlConfig"/>
     
         <! -- 1. In order to be consistent with other Dubbo remote call protocols, annotation validation in REST must be placed on the service's interface. Putting annotations on the interface has at least one advantage: dubbo clients can share information about the interface. Dubbo does not even need to make a remote call, input validation can be done locally. Then turn on validation in the XML configuration in dubbo's standard way:  <dubbo:service interface=xxx.UserService" ref="userService" protocol="rest" validation="true"/> 2. In many of Dubbo's other remote invocation protocols, rpcExceptions are thrown directly to the client if input validation fails, whereas in REST, the client is often a non-Dubbo or even a non-Java system, making it difficult to throw Java exceptions directly. For now, therefore, we return validation errors in XML format:  <violationReport> <constraintViolations> <path>getUserArgument0</path> <message>User ID must be greater than 1</message> <value>0</value> </constraintViolations> </violationReport> If you feel that the default validation error return format does not meet your requirements, as described in the section above, Adding custom ExceptionMapper from the custom error return format. Note that this ExceptionMapper must catch Dubbo's RpcException with a generic declaration in order to successfully override dubbo Rest's default exception-handling policy. In order to simplify the operation, in fact, the simplest way here is to directly inherit Dubbo REST RpcExceptionMapper, and override the processing of the check exception method.
         <dubbo:service interface="com.alibaba.dubbo.demo.user.facade.AnotherUserRestService" ref="anotherUserRestService" protocol="rest" timeout="2000" connections="100" validation="true"/>
      
         <bean id="userService" class="com.alibaba.dubbo.demo.user.UserServiceImpl"/>
     
         <bean id="anotherUserRestService" class="com.alibaba.dubbo.demo.user.facade.AnotherUserRestServiceImpl">
             <property name="userService" ref="userService"/>
         </bean>
     
         <! Spring MVC also supports annotation configuration, which looks very, very similar to JAX-RS. Personally, I think Spring MVC is more suitable for Restful services for Web applications, such as AJAX calls, HTML output and so on, and page jump flows in applications. Spring MVC can handle both normal Web page requests and REST requests at the same time. But in general this restful service is implemented in the presentation layer or web layer or something like that. Jax-rs is better suited for pure service-oriented applications, which are what traditional Java EE calls mid-tier services, such as publishing traditional EJBs as restful services. In Spring applications, spring beans that act as Services are directly published as restful services. Generally the restful service is at the business, application or facade level. MVC hierarchies and concepts are often of little value in such applications as servitization. Of course, some implementations of JAX-RS, such as Jersey, also attempt to provide MVC support that is better suited to web applications mentioned above, but probably not as good as Spring MVC. In dubbo applications, where I think many people prefer to publish a native Spring Service bean (or manager or whatever) as a remote service directly and transparently, jax-RS is more natural and straightforward without the additional introduction of MVC concepts. Of course, leave aside the question of whether it's a best practice to publish remote services transparently, whether you should add a facade or not. Of course, I know that in the case of Dubbo does not support REST, many friends adopt the architecture of Spring MVC restful call Dubbo (Spring) Service to publish restful services. This approach is fine by me, except that without modifying Spring MVC and deeply integrating it with Dubbo, restful services can't be like other remote call protocols in Dubbo such as WebServices, Dubbo RPC, Hessian, etc. Enjoy advanced service governance features such as: Register in dubbo's service registry, monitor the number of calls, TPS, response time and so on through dubbo monitoring center, control it through Dubbo unified configuration such as thread pool size, maximum number of connections, etc., through Dubbo unified service flow control, permission control, frequency control. In addition, Spring MVC is only responsible for the server side. On the consumer side, spring restTemplate is usually used. If the restTemplate is not integrated with Dubbo, there is the possibility of automatic or manual intervention to degrade the service like the Dubbo service client. If both the server and consumer are dubbo systems, the rest interaction through Spring, if Spring REST does not deeply integrate Dubbo, dubbo unified routing and other functions cannot be used. Of course, I personally don't think these things have to be either/or. I heard that Rod Johnson, the founder of Spring, likes to say, "The customer is always right." In fact, instead of discussing which way is better, it's better to support both ways. So there was a plan to support Spring Rest annoation in the documentation, but I didn't know how feasible it would be. 1. Can overloaded methods in JAX-RS map to the same URL address? http://stackoverflow.com/questions/17196766/can-resteasy-choose-method-based-on-query-params 2. Can the POST method in JAX-RS accept multiple parameters? http://stackoverflow.com/questions/5553218/jax-rs-post-multiple-objects Note: the above remarks, all from: https://dangdangdotcom.github.io/dubbox/rest.html - >
    </beans>
    Copy the code
  6. Configuration dubbo. The properties

    #dubbo.container=log4j,spring
    #dubbo.application.name=demo-provider
    #dubbo.application.owner=
    # dubbo. Registry. Address = multicast: / / 224.5.6.7:1234
    # dubbo. Registry. Address = zookeeper: / / 127.0.0.1:2181
    # dubbo. Registry. Address = redis: / / 127.0.0.1:6379
    # dubbo. Registry. Address = dubbo: / / 127.0.0.1:9090
    #dubbo.monitor.protocol=registry
    #dubbo.protocol.name=dubbo
    #dubbo.protocol.port=20880
    #dubbo.service.loadbalance=roundrobin
    #dubbo.log4j.file=logs/msa-demo-provider.log
    #dubbo.log4j.level=INFO
    #dubbo.log4j.subdirectory=20880
    dubbo.application.logger=slf4j
    dubbo.spring.config=classpath*:msa-*.xml
    Copy the code

1.4 Starting the Service

Define the service startup class

package com.alibaba.dubbo.demo.provider;
/ * * *@author TaoBangren
  * @version 1.0
  * @since2017/5/17 9:26 am */
public class DemoProvider {
      public static void main(String[] args) { com.alibaba.dubbo.container.Main.main(args); }}Copy the code

Run the main method to start mSA-Demo-provider. If the following logs are displayed, the mSA-Demo-provider is started successfully:

To viewDubboKeeperMonitor the market, mSA-Demo-Provider released the service successfully, you can see the two interfaces we released:

2. The client

  1. Create Maven module: msa-demo-client

  2. Msa-demo-client: configures pom.xml

    <! -- Module depends on START -->
    <dependency>
         <groupId>com.alibaba</groupId>
         <artifactId>msa-demo-api</artifactId>
         <version>1.0 the SNAPSHOT</version>
    </dependency>
    <! -- Module depends on END -->
    Copy the code
  3. Dubbox and Spring integration configuration: mSA-Demo-client.xml

    <?xml version="1.0" encoding="UTF-8"? >
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
        xsi:schemaLocation="Http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
    
       <! -- Current application configuration -->
       <! --<dubbo:application name="msa-demo-client" owner="shark" organization="shark"/>-->
    
       <! -- Multiple registries configuration, vertical indicates that multiple registries are connected at the same time, and multiple cluster addresses in the same registry are separated by commas -->
       <! --<dubbo:registry protocol="zookeeper" address="x.x.x.x:2181,x.x.x.x:2181,x.x.x.x:2181"/>-->
       <! --<dubbo:monitor address="x.x.x.x:20884"/>-->
     
       <dubbo:reference id="userService" interface="com.alibaba.dubbo.demo.user.UserService" group="xmlConfig"/>
       <dubbo:reference id="anotherUserRestService" interface="com.alibaba.dubbo.demo.user.facade.AnotherUserRestService"/>
    
       <! -- directly connect to provider to simulate the access to non-dubbo rest services <dubbo:reference id="anotherUserRestService" interface="com.alibaba.dubbo.demo.user.facade.AnotherUserRestService" url="rest://localhost:8888/services/"/> -->
    </beans>
    Copy the code

3. The consumer end

3.1 Implementation of the consumer side

  1. Create Maven module: mSA-demo-consumer

  2. Msa-demo-consumer: Configure POM.xml

    <! -- Module depends on START -->
    <dependency>
          <groupId>com.jeasy</groupId>
          <artifactId>msa-demo-client</artifactId>
          <version>1.0 the SNAPSHOT</version>
    </dependency>
    <! -- Module depends on END -->
    Copy the code
  3. Create a consumer-side test class: DemoAction.java

    package com.alibaba.dubbo.demo;
    import com.alibaba.dubbo.rpc.RpcContext;
    import com.alibaba.dubbo.demo.user.User;
    import com.alibaba.dubbo.demo.user.UserService;
    import com.alibaba.dubbo.demo.user.facade.AnotherUserRestService;
    / * * *@author TaoBangren
     * @version 1.0
     * @since2017/5/17 9:26 am */
    public class DemoAction {
    
          private UserService userService;
    
          private AnotherUserRestService anotherUserRestService;
    
          public void setUserService(final UserService userService) {
              this.userService = userService;
          }
    
          public void setAnotherUserRestService(final AnotherUserRestService anotherUserRestService) {
              this.anotherUserRestService = anotherUserRestService;
          }
    
          public void start(a) throws Exception {
              User user = new User();
              user.setId(1L);
              user.setName("larrypage");
    
              System.out.println("SUCCESS: registered user with id by rest" + anotherUserRestService.registerUser(user).getId());
              System.out.println("SUCCESS: registered user with id " + userService.registerUser(user));
     
              RpcContext.getContext().setAttachment("clientName"."demo");
              RpcContext.getContext().setAttachment("clientImpl"."dubbox rest");
              System.out.println("SUCCESS: got user by rest" + anotherUserRestService.getUser(1L));
              System.out.println("SUCCESS: got user " + userService.getUser(1L)); }}Copy the code
  4. Dubbox integration configuration with Spring: mSA-demo-consumer.xml

    <?xml version="1.0" encoding="UTF-8"? >
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
        xsi:schemaLocation="Http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
    
       <! -- Current application configuration -->
       <dubbo:application name="msa-demo-consumer" owner="tbr" organization="tbr"/>
    
       <! -- Multiple registries configuration, vertical indicates that multiple registries are connected at the same time, and multiple cluster addresses in the same registry are separated by commas -->
       <dubbo:registry protocol="zookeeper" address="x.x.x.x:2181,x.x.x.x:2181,x.x.x.x:2181"/>
       <dubbo:monitor address="x.x.x.x:20884"/>
    
       <bean class="com.alibaba.dubbo.demo.DemoAction" init-method="start">
           <property name="userService" ref="userService"/>
           <property name="anotherUserRestService" ref="anotherUserRestService"/>
       </bean>
    </beans>
    Copy the code
  5. Configuration dubbo. The properties

    #dubbo.container=log4j,spring
    #dubbo.application.name=demo-consumer
    #dubbo.application.owner=
    # dubbo. Registry. Address = multicast: / / 224.5.6.7:1234
    # dubbo. Registry. Address = zookeeper: / / 127.0.0.1:2181
    # dubbo. Registry. Address = redis: / / 127.0.0.1:6379
    # dubbo. Registry. Address = dubbo: / / 127.0.0.1:9090
    #dubbo.monitor.protocol=registry
    #dubbo.log4j.file=logs/msa-demo-consumer.log
    #dubbo.log4j.level=INFO
    dubbo.application.logger=slf4j
    dubbo.spring.config=classpath*:msa-*.xml
    Copy the code

3.2 Consumer side test

Define the consumption startup class:

package com.jeasy;
/ * * *@author TaoBangren
 * @version 1.0
 * @since2017/5/17 9:26 am */
public class DemoConsumer {
      public static void main(String[] args) { com.alibaba.dubbo.container.Main.main(args); }}Copy the code

Run the main method to start mSA-demo-consumer. If the following log output is displayed, mSA-demo-consumer is started successfully:

At the same time, the server will output the service invocation log information, and the invocation is successful, as follows:

4. Standard use

The module describe Whether must
msa-xxx-api Define interfaces & entities Must be
msa-xxx-provider Depend on API module, realize service interface, provide service Must be
msa-xxx-client Rely on API modules, Spring configuration files & test cases for use by third parties calling services Must be
msa-xxx-consumer The client module is required. You are advised to retain the client module to avoid the close coupling between the client module and the application optional

5. Recommended reading

5.1 Dubbox Resources

  1. Source code address: github.com/dangdangdot…
  2. Development in Dubbo REST style remote invocation: dangdangdotcom. Making. IO/dubbox/REST…
  3. Using efficient Java serialization: in Dubbo dangdangdotcom. Making. IO/dubbox/begawan…
  4. Using configuration dubbox JavaConfig way: dangdangdotcom. Making. IO/dubbox/Java…
  5. Dubbo Jackson serialization instructions: dangdangdotcom. Making. IO/dubbox/jack…
  6. Demo: dangdangdotcom. Making. IO/dubbox/Demo…
  7. Dangdang open-source Dubbox, expanding Dubbo service framework supports REST style remote invocation: www.infoq.com/cn/news/201…
  8. Dubbox Wiki: github.com/dangdangdot…

5.2 Dubbo Related Resources

  1. Source code address: github.com/alibaba/dub…
  2. Dubbo Wiki: github.com/alibaba/dub…
  3. http://dubbo.io/