通过一个简单的例子,介绍Dubbo环境的搭建。
使用到的组件:
zookeeper 3.5.4-beta
dubbo 2.7.1
org.slf4j 1.7.26
log4j 2.11.2
curator 4.2.0
准备4个工程以及包含的类和配置文件:
SSO-API
com.test.sso.intf.SSODataStore
com.test.sso.intf.SSOServiceProvider
SSO-DataStore
com.test.sso.App
com.test.sso.SSODataStoreImpl
sso-service-dataStore.xml
log4j2.xml
SSO-ServiceProvider
com.test.sso.App
com.test.sso.SSOServiceProviderImpl
sso-service-provider.xml
log4j2.xml
SSO-Consumer
com.test.sso.App
sso-service-consumer.xml
log4j2.xml
其中,SSO-API只存放接口,SSO-ServiceProvider即是Provider又是Consumer,SSO-DataStore只是Provider,SSO-Consumer只是Consumer,调用关系为SSO-Consumer -> SSO-ServiceProvider -> SSO-DataStore。
Maven的pom.xml文件中统一使用如下配置:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<dubbo.version>2.7.1</dubbo.version>
<log4j2.version>2.11.2</log4j2.version>
<curator.version>4.2.0</curator.version>
<disruptor.version>3.4.2</disruptor.version>
<slf4j.version>1.7.26</slf4j.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j2.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j2.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>${log4j2.version}</version>
</dependency>
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>${disruptor.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>${curator.version}</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-client</artifactId>
<version>${curator.version}</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>${curator.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
如果zookeeper使用的版本为3.5.4-beta,则curator要用4.2.0的版本。如果zookeeper使用的版本为3.4.14,则curator要在依赖中将zookeeper排除,同时要单独添加对zookeeper版本3.4.X的依赖。由于spring中还用到了common-logging,所以需要使用jcl-over-slf4j将对common-logging API的调用转到slf4j上。另外,由于要用到异步logger,所以添加disruptor。
log4j2.xml配置:
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="error">
<Properties>
<Property name="baseDir">D:/Temp/eclipse/logs</Property>
<Property name="patternFormat">%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level[%3T]%c.%M:%L - %m%xEx%n</Property>
</Properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="${patternFormat}" />
</Console>
<RollingFile name="data_log" fileName="${baseDir}/data.log" filePattern="${baseDir}/data-%d{yyyyMMddHHmm}.log">
<PatternLayout pattern="${patternFormat}" />
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true" />
<SizeBasedTriggeringPolicy size="250MB" />
</Policies>
<DefaultRolloverStrategy>
<Delete basePath="${baseDir}" maxDepth="2">
<IfFileName glob="data-*.log" />
<IfLastModified age="10m" />
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
</Appenders>
<Loggers>
<asyncLogger name="com.test.sso" level="info" additivity="false" includeLocation="true">
<AppenderRef ref="data_log" />
</asyncLogger>
<Root level="info" includeLocation="true">
<AppenderRef ref="Console" />
</Root>
</Loggers>
</configuration>
由于使用了<asyncLogger>,如果要打印出代码行号和方法名,则需要includeLocation="true",但这样会影响性能。这几个工程的log4j2.xml内容类似,所以只给出一个例子。
SSO-API
package com.test.sso.intf;
import java.util.List;
public interface SSODataStore {
List<String> getAllActions(long appId, long userId, byte state);
}
package com.test.sso.intf;
import java.util.List;
public interface SSOServiceProvider {
long checkLogin(String userName, String pwd);
List<String> fetchActionsAllowed(long appId, long userId);
boolean checkAction(long userId, long appId, String actionName);
}
SSO-DataStore
package com.test.sso;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.test.sso.intf.SSODataStore;
public class SSODataStoreImpl implements SSODataStore {
private final static Logger LOG = LoggerFactory.getLogger(SSODataStoreImpl.class);
public List<String> getAllActions(long appId, long userId, byte state) {
LOG.info("appId={}, userId={}, state={}", appId, userId, state);
List<String> actionList = new ArrayList<>();
actionList.add("gate_login");
actionList.add("gate_logout");
actionList.add("gate_heartbeat");
return actionList;
}
}
package com.test.sso;
import java.io.IOException;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) throws IOException {
System.setProperty("java.net.preferIPv4Stack", "true");
System.setProperty("dubbo.application.logger", "slf4j");
// System.setProperty("log4j2.contextSelector", "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("sso-service-dataStore.xml");
context.start();
System.in.read();
}
}
其中需要注意的是如下这行代码
System.setProperty("dubbo.application.logger", "slf4j");
它将使dubbo采用slf4j作为底层日志API。可以在org.apache.dubbo.common.logger.LoggerFactory中查看到源码。
sso-service-dataStore.xml
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://dubbo.apache.org/schema/dubbo
http://dubbo.apache.org/schema/dubbo/dubbo.xsd
">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="properties">
<props>
<prop key="service.port">20882</prop>
</props>
</property>
</bean>
<dubbo:application name="sso-service-dataStore">
<dubbo:parameter key="qos.enable" value="false" />
<dubbo:parameter key="qos.accept.foreign.ip" value="false" />
<dubbo:parameter key="qos.port" value="33333" />
</dubbo:application>
<!-- <dubbo:registry address="multicast://224.5.6.7:1234" /> -->
<dubbo:registry id="registryProvider" address="zookeeper://127.0.0.1:2181" />
<dubbo:protocol id="protocolProvider" name="dubbo" port="${service.port}" />
<!-- service definition -->
<bean id="SSODataStoreBean" class="com.test.sso.SSODataStoreImpl" />
<dubbo:service id="SSODataStore" interface="com.test.sso.intf.SSODataStore"
ref="SSODataStoreBean" version="1.0.0" registry="registryProvider" protocol="protocolProvider" />
</beans>
此应用执行时,可以使用-Dservice.port=XXXX的方式覆盖此配置文件中设置的端口号。由于qos暂时用不到,将其禁用,防止端口冲突。
SSO-ServiceProvider
package com.test.sso;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.test.sso.intf.SSODataStore;
import com.test.sso.intf.SSOServiceProvider;
public class SSOServiceProviderImpl implements SSOServiceProvider {
private final static Logger LOG = LoggerFactory.getLogger(SSOServiceProviderImpl.class);
private SSODataStore dataStore;
public void setDataStore(SSODataStore dataStore) {
this.dataStore = dataStore;
}
public long checkLogin(String userName, String pwd) {
LOG.info("userName={}, pwd={}", userName, pwd);
return 1001;
}
public List<String> fetchActionsAllowed(long appId, long userId) {
LOG.info("appId={}, userId={}", appId, userId);
return dataStore.getAllActions(appId, userId, (byte) 2);
}
public boolean checkAction(long userId, long appId, String actionName) {
LOG.info("userId={}, appI={}, actionName={}", userId, appId, actionName);
return true;
}
}
package com.test.sso;
import java.io.IOException;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) throws IOException {
System.setProperty("java.net.preferIPv4Stack", "true");
System.setProperty("dubbo.application.logger", "slf4j");
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("sso-service-provider.xml");
context.start();
System.in.read();
}
}
sso-service-provider.xml
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://dubbo.apache.org/schema/dubbo
http://dubbo.apache.org/schema/dubbo/dubbo.xsd
">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="properties">
<props>
<prop key="service.port">20880</prop>
</props>
</property>
</bean>
<dubbo:application name="sso-service-provider">
<dubbo:parameter key="qos.enable" value="false" />
<dubbo:parameter key="qos.accept.foreign.ip" value="false" />
<dubbo:parameter key="qos.port" value="33333" />
</dubbo:application>
<dubbo:registry id="registryProvider" address="zookeeper://127.0.0.1:2181" />
<dubbo:protocol id="protocolProvider" name="dubbo" port="${service.port}" />
<!-- service reference -->
<dubbo:reference id="SSODataStore" interface="com.test.sso.intf.SSODataStore" version="1.0.0" />
<!-- service definition -->
<bean id="SSOServiceProviderBean" class="com.test.sso.SSOServiceProviderImpl">
<property name="dataStore" ref="SSODataStore" />
</bean>
<dubbo:service id="SSOServiceProvider" interface="com.test.sso.intf.SSOServiceProvider" ref="SSOServiceProviderBean" version="1.0.0"
registry="registryProvider" protocol="protocolProvider" />
</beans>
SSO-Consumer
package com.test.sso;
import java.util.List;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.test.sso.intf.SSOServiceProvider;
public class App {
public static void main(String[] args) {
System.setProperty("dubbo.application.logger", "slf4j");
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("sso-service-consumer.xml");
context.start();
SSOServiceProvider ssoService = (SSOServiceProvider) context.getBean("SSOServiceProvider");
boolean ret = ssoService.checkAction(1001L, 1, "actionName");
System.out.println(ret);
long userId = ssoService.checkLogin("xl", "12345678");
System.out.println(userId);
long appId = 1;
List<String> actionsAllowed = ssoService.fetchActionsAllowed(appId, userId);
System.out.println(actionsAllowed);
}
}
sso-service-consumer.xml
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://dubbo.apache.org/schema/dubbo
http://dubbo.apache.org/schema/dubbo/dubbo.xsd
">
<dubbo:application name="sso-service-consumer">
<dubbo:parameter key="qos.enable" value="false" />
<dubbo:parameter key="qos.accept.foreign.ip" value="false" />
<dubbo:parameter key="qos.port" value="33333" />
</dubbo:application>
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
<dubbo:protocol name="dubbo" />
<dubbo:reference id="SSOServiceProvider" interface="com.test.sso.intf.SSOServiceProvider" version="1.0.0" />
</beans>
可以使用如下命令分别启动zookeeper服务器和客户端:
zkServer.cmd
zkCli.cmd -server 127.0.0.1:2181
然后,启动SSO-DataStore和SSO-ServiceProvider,最后启动SSO-Consumer就可以看到执行结果。
如果想启用dubbo-admin,可以使用如下命令下载并安装dubbo-admin
git clone https://github.com/apache/incubator-dubbo-admin.git
cd incubator-dubbo-admin
mvn clean package
cd dubbo-admin-distribution/target
java -jar dubbo-admin-0.1.jar
参考文档
Quick start
incubator-dubbo
incubator-dubbo-admin
dubbo一些你不一定知道但是很好用的功能