Example of getting started with dubbo hello world
1. Demand
In an e-commerce system, order services need to call user services to get all addresses of a user;
We now need to create two service modules to test:
Modular |
function |
Order Service web Module |
Create an order, etc. |
User service Module |
Query user address, etc. |
Test expected results: Order service web module in server A, user service module in server B, A can call B's function remotely.
2. Engineering Structure
According to dubbo Best Practices for Servicing
a. Subcontracting
It is recommended that service interfaces, service models, service exceptions, and so on, be included in the API package, since service models and exceptions are also part of the API and conform to the subcontracting principle: Reuse Publication Equivalence Principle (REP), Common Reuse Principle (CRP).
If necessary, you can also consider placing a reference configuration for spring in the API package so that it can be used simply by referencing the configuration during the spring loading process. The configuration recommendations are placed in the package directory of the module to avoid conflicts, such as com/alibaba/china/xxx/dubbo-reference.xml.
b. Granularity
Service interfaces are as granular as possible, and each service method should represent a function, not a step of a function, or you will face distributed transaction issues, which Dubbo does not currently provide.Service interfaces recommend dividing into business scenarios and abstracting similar business to prevent the number of interfaces from exploding.
It is not recommended to use general interfaces that are too abstract, such as Map query, which do not have explicit semantics and will be inconvenient for later maintenance.
2. Creating Projects
1. Create project, module
This demo takes the form of project and multi-module, project called dubbo, module gmall-interface, order-service-consumer, user-service-provider, respectively, as shown in the figure:
a, parent project
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.ty</groupId> <artifactId>dubbo</artifactId> <packaging>pom</packaging> <version>1.0-SNAPSHOT</version> <modules> <module>gmall-interface</module> <module>order-service-consumer</module> <module>user-service-providor</module> </modules> <!--If you do not specify that an error may be reported,@Override is not allowed when implementing interface method--> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
b. gmall-interface
The structure is as follows:
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>dubbo</artifactId> <groupId>com.ty</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>gmall-interface</artifactId> </project>
UserAddress
package com.ty.bean; import java.io.Serializable; /** * User Address * @author lfy * */ public class UserAddress implements Serializable { private Integer id; private String userAddress; //User Address private String userId; //user id private String consignee; //Consignee private String phoneNum; //Phone number private String isDefault; //Is this the default address Y-yes N-no public UserAddress() { super(); // TODO Auto-generated constructor stub } public UserAddress(Integer id, String userAddress, String userId, String consignee, String phoneNum, String isDefault) { super(); this.id = id; this.userAddress = userAddress; this.userId = userId; this.consignee = consignee; this.phoneNum = phoneNum; this.isDefault = isDefault; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUserAddress() { return userAddress; } public void setUserAddress(String userAddress) { this.userAddress = userAddress; } public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public String getConsignee() { return consignee; } public void setConsignee(String consignee) { this.consignee = consignee; } public String getPhoneNum() { return phoneNum; } public void setPhoneNum(String phoneNum) { this.phoneNum = phoneNum; } public String getIsDefault() { return isDefault; } public void setIsDefault(String isDefault) { this.isDefault = isDefault; } }
OrderService
package com.ty.service; import com.ty.bean.UserAddress; import java.util.List; public interface OrderService { /** * Initialize Order * @param userId */ public List<UserAddress> initOrder(String userId); }
UserService
package com.ty.service; import com.ty.bean.UserAddress; import java.util.List; /** * User Services * @author lfy * */ public interface UserService { /** * Return all shipping addresses by user id * @param userId * @return */ public List<UserAddress> getUserAddressList(String userId); }
c,user-service-providor
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>dubbo</artifactId> <groupId>com.ty</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>user-service-providor</artifactId> <dependencies> <dependency> <groupId>com.ty</groupId> <artifactId>gmall-interface</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!-- Introduce dubbo --> <!-- https://mvnrepository.com/artifact/com.alibaba/dubbo --> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.6.2</version> </dependency> <!-- The registry uses zookeeper,Introducing operations zookeeper Client --> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>2.12.0</version> </dependency> </dependencies> </project>
UserServiceImpl
package com.ty.service.impl; import com.ty.bean.UserAddress; import com.ty.service.UserService; import java.util.Arrays; import java.util.List; public class UserServiceImpl implements UserService { @Override public List<UserAddress> getUserAddressList(String userId) { System.out.println("UserServiceImpl.....old..."); // TODO Auto-generated method stub UserAddress address1 = new UserAddress(1, "3rd Floor of Hongfu Science Park Complex Building, Changping District, Beijing", "1", "Miss Li", "010-56253825", "Y"); UserAddress address2 = new UserAddress(2, "Silicon Valley Building, West of Baoan District, Shenzhen B Block 3 (Shenzhen Branch)", "1", "Mr. Wang", "010-56253825", "N"); /*try { Thread.sleep(4000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); }*/ return Arrays.asList(address1,address2); } }
UserServiceImpl2
package com.ty.service.impl; import com.ty.bean.UserAddress; import com.ty.service.UserService; import java.util.Arrays; import java.util.List; public class UserServiceImpl2 implements UserService { @Override public List<UserAddress> getUserAddressList(String userId) { System.out.println("UserServiceImpl.....new..."); // TODO Auto-generated method stub UserAddress address1 = new UserAddress(1, "3rd Floor of Hongfu Science Park Complex Building, Changping District, Beijing", "1", "Miss Li", "010-56253825", "Y"); UserAddress address2 = new UserAddress(2, "Silicon Valley Building, West of Baoan District, Shenzhen B Block 3 (Shenzhen Branch)", "1", "Mr. Wang", "010-56253825", "N"); return Arrays.asList(address1,address2); } }
UserServiceStub
package com.ty.service.impl; import com.ty.bean.UserAddress; import com.ty.service.UserService; import org.springframework.util.StringUtils; import java.util.List; public class UserServiceStub implements UserService { private final UserService userService; /** * The proxy object passed in is userService Remote * @param userService */ public UserServiceStub(UserService userService) { super(); this.userService = userService; } @Override public List<UserAddress> getUserAddressList(String userId) { // TODO Auto-generated method stub System.out.println("UserServiceStub....."); if(!StringUtils.isEmpty(userId)) { return userService.getUserAddressList(userId); } return null; } }
MainApplication
package com.ty; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.io.IOException; public class MainApplication { public static void main(String[] args) throws IOException { ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("provider.xml"); ioc.start(); System.in.read(); } }
providor.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.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <!-- 1,Specify the current service/Name of the application (same service name, do not have the same name as other services) --> <dubbo:application name="user-service-provider"></dubbo:application> <!-- 2,Specify the location of the registry --> <!-- <dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry> --> <dubbo:registry protocol="zookeeper" address="127.0.0.1:2181"></dubbo:registry> <!-- 3,Specify communication rules (communication protocols?Communication Port) --> <dubbo:protocol name="dubbo" port="20882"></dubbo:protocol> <!-- 4,Exposure Services ref: Real implementation objects pointing to services --> <dubbo:service interface="com.ty.service.UserService" ref="userServiceImpl01" timeout="1000" version="1.0.0"> <dubbo:method name="getUserAddressList" timeout="1000"></dubbo:method> </dubbo:service> <!--Uniform Provider Rules --> <dubbo:provider timeout="1000"></dubbo:provider> <!-- Implementation of services --> <bean id="userServiceImpl01" class="com.ty.service.impl.UserServiceImpl"></bean> <dubbo:service interface="com.ty.service.UserService" ref="userServiceImpl02" timeout="1000" version="2.0.0"> <dubbo:method name="getUserAddressList" timeout="1000"></dubbo:method> </dubbo:service> <bean id="userServiceImpl02" class="com.ty.service.impl.UserServiceImpl2"></bean> <!-- Connect Monitoring Center --> <dubbo:monitor protocol="registry"></dubbo:monitor> </beans>
d,order-service-consumer
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>dubbo</artifactId> <groupId>com.ty</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>order-service-consumer</artifactId> <dependencies> <dependency> <groupId>com.ty</groupId> <artifactId>gmall-interface</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!-- Introduce dubbo --> <!-- https://mvnrepository.com/artifact/com.alibaba/dubbo --> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.6.2</version> </dependency> <!-- The registry uses zookeeper,Introducing operations zookeeper Client --> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>2.12.0</version> </dependency> </dependencies> </project>
OrderServiceImpl
package com.ty.service.impl; import com.ty.bean.UserAddress; import com.ty.service.OrderService; import com.ty.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; /** * 1,Registering service providers with the registry (exposing services) * 1),Import dubbo dependencies (2.6.2)\Clients operating zookeeper (curator) * 2),Configure service providers * * 2,Let service consumers go to the registry to subscribe to the service address of the service provider * @author lfy * */ @Service public class OrderServiceImpl implements OrderService { @Autowired UserService userService; @Override public List<UserAddress> initOrder(String userId) { // TODO Auto-generated method stub System.out.println("user id: "+userId); //1,Query the user's receipt address List<UserAddress> addressList = userService.getUserAddressList(userId); for (UserAddress userAddress : addressList) { System.out.println(userAddress.getUserAddress()); } return addressList; } }
MainApplication
package com.ty; import com.ty.service.OrderService; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.io.IOException; public class MainApplication { @SuppressWarnings("resource") public static void main(String[] args) throws IOException { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("consumer.xml"); OrderService orderService = applicationContext.getBean(OrderService.class); orderService.initOrder("1"); System.out.println("Call complete...."); System.in.read(); } }
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://dubbo.apache.org/schema/dubbo" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <context:component-scan base-package="com.ty.service.impl"></context:component-scan> <dubbo:application name="order-service-consumer"></dubbo:application> <dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry> <!-- Configure local stubs--> <!--Declare the interface of the remote service that needs to be invoked; generate the remote service proxy --> <!-- 1),Precision first (Method level takes precedence, interface level takes precedence, global configuration takes precedence) 2),Consumer Setting Priority(If the level is the same, the consumer takes precedence over the provider) --> <!-- timeout="0" Default is 1000 ms--> <!-- retries="":Number of retries, excluding the first call, 0 means no retry--> <!-- Power (set retry count) [query, delete, modify], non-power (cannot set retry count) [add] --> <dubbo:reference interface="com.ty.service.UserService" id="userService" timeout="5000" retries="3" version="*"> <!-- <dubbo:method name="getUserAddressList" timeout="1000"></dubbo:method> --> </dubbo:reference> <!-- Uniform Rule for Configuring Current Consumers: No Services Checked --> <dubbo:consumer check="false" timeout="5000"></dubbo:consumer> <dubbo:monitor protocol="registry"></dubbo:monitor> <!-- <dubbo:monitor address="127.0.0.1:7070"></dubbo:monitor> --> </beans>
3. Testing
1. Start zooker's service and dubbo-admin from the previous blog post (java-jar way started)
2. main method in MainApplication to start user-service-provider
E:\jdk\bin\java.exe "-javaagent:E:\utils\Intellij idea\IntelliJ IDEA 2018.3.2\lib\idea_rt.jar=51328:E:\utils\Intellij idea\IntelliJ IDEA 2018.3.2\bin" -Dfile.encoding=UTF-8 -classpath E:\jdk\jre\lib\charsets.jar;E:\jdk\jre\lib\deploy.jar;E:\jdk\jre\lib\ext\access-bridge-64.jar;E:\jdk\jre\lib\ext\cldrdata.jar;E:\jdk\jre\lib\ext\dnsns.jar;E:\jdk\jre\lib\ext\jaccess.jar;E:\jdk\jre\lib\ext\jfxrt.jar;E:\jdk\jre\lib\ext\localedata.jar;E:\jdk\jre\lib\ext\nashorn.jar;E:\jdk\jre\lib\ext\sunec.jar;E:\jdk\jre\lib\ext\sunjce_provider.jar;E:\jdk\jre\lib\ext\sunmscapi.jar;E:\jdk\jre\lib\ext\sunpkcs11.jar;E:\jdk\jre\lib\ext\zipfs.jar;E:\jdk\jre\lib\javaws.jar;E:\jdk\jre\lib\jce.jar;E:\jdk\jre\lib\jfr.jar;E:\jdk\jre\lib\jfxswt.jar;E:\jdk\jre\lib\jsse.jar;E:\jdk\jre\lib\management-agent.jar;E:\jdk\jre\lib\plugin.jar;E:\jdk\jre\lib\resources.jar;E:\jdk\jre\lib\rt.jar;E:\workspaceidea\dubbo\user-service-providor\target\classes;E:\workspaceidea\dubbo\gmall-interface\target\classes;E:\respository\com\alibaba\dubbo\2.6.2\dubbo-2.6.2.jar;E:\respository\org\springframework\spring-context\4.3.16.RELEASE\spring-context-4.3.16.RELEASE.jar;E:\respository\org\springframework\spring-aop\4.3.16.RELEASE\spring-aop-4.3.16.RELEASE.jar;E:\respository\org\springframework\spring-beans\4.3.16.RELEASE\spring-beans-4.3.16.RELEASE.jar;E:\respository\org\springframework\spring-core\4.3.16.RELEASE\spring-core-4.3.16.RELEASE.jar;E:\respository\commons-logging\commons-logging\1.2\commons-logging-1.2.jar;E:\respository\org\springframework\spring-expression\4.3.16.RELEASE\spring-expression-4.3.16.RELEASE.jar;E:\respository\org\javassist\javassist\3.20.0-GA\javassist-3.20.0-GA.jar;E:\respository\org\jboss\netty\netty\3.2.5.Final\netty-3.2.5.Final.jar;E:\respository\org\apache\curator\curator-framework\2.12.0\curator-framework-2.12.0.jar;E:\respository\org\apache\curator\curator-client\2.12.0\curator-client-2.12.0.jar;E:\respository\org\apache\zookeeper\zookeeper\3.4.8\zookeeper-3.4.8.jar;E:\respository\log4j\log4j\1.2.16\log4j-1.2.16.jar;E:\respository\jline\jline\0.9.94\jline-0.9.94.jar;E:\respository\io\netty\netty\3.7.0.Final\netty-3.7.0.Final.jar;E:\respository\com\google\guava\guava\16.0.1\guava-16.0.1.jar;E:\respository\org\slf4j\slf4j-api\1.7.6\slf4j-api-1.7.6.jar com.ty.MainApplication log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment). log4j:WARN Please initialize the log4j system properly. log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info. SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
3. Open http://localhost:7001/
You can see that there are already two services, indicating that user-service-provider started ok
4. Test order-service-consumer (run its main method)
User id:1 3rd Floor of Hongfu Science Park Complex Building, Changping District, Beijing 3rd Floor, Block B, Silicon Valley Building, west of Baoan District, Shenzhen (Shenzhen Branch) Call complete...
Indicates that the consumer has also invoked successfully
dubbo hello world uploaded github: https://github.com/ali-mayun/dubbo