Dubbo 实战
主要内容 Dubbo 简介 Dubbo 架构详解 Dubbo 支持的协议 Dubbo 支持的注册中心 Dubbo 应用 Spring Boot 整合 Dubbo Dubbo 监控与管理 Dubbo 中服务的负载均衡 Dubbo 项目打包方式 Dubbo 实战案例
一、 Dubbo 简介
1 Dubbo 是什么
Dubbo 官网地址:https://dubbo.apache.org/zh/ Dubbo 最早是 Alibaba 开源的分布式服务框架,它最大的特点是按照分层的方式来架构, 使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合)。从服务模型的角度来看, Dubbo 采用的是一种非常简单的模型,要么是提供方提供服务,要么是消费方消费服务,所 以基于这一点可以抽象出服务提供方(Provider)和服务消费方(Consumer)两个角色。
2 发展历史
Dubbo 是最开始是阿里巴巴内部使用的 RPC 框架。 2011 年对外提供。 2012 年停止更新。 2017 年开始继续更新。 2019 年捐献给 Apache,由 Apache 维护 2.7 以上版本。
3 Dubbo 能做什么
- Dubbo 可实现透明化的远程方法调用,就像调用本地方法一样调用远程方法,只需简单配置即可,没有任何 API 侵入。
- 软负载均衡及容错机制,可在内网替代 F5 等硬件负载均衡器,降低成本,减少单点。
- 服务自动注册与发现,不再需要写死服务提供方地址,注册中心基于接口名查询服务提 供者的 IP 地址,并且能够平滑添加或删除服务提供者。
4 Dubbo 产生的背景
- 单一应用架构(单体架构)
当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。 此时,用于简化增删改查工作量的数据访问框架(ORM) 是关键。 - 垂直应用架构
当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的 几个应用,以提升效率。 此时,用于加速前端页面开发的 Web 框架(MVC) 是关键。 - 分布式服务架构(RPC 架构)
当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务, 逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。 此时,用于提高业务复用及整合的分布式服务框架(RPC) 是关键。 - 流动计算架构(SOA 架构)
当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调 度中心基于访问压力实时管理集群容量,提高集群利用率。 此时,用于提高机器利用率的资源调度和治理中心(SOA) 是关键。
二、 Dubbo 架构讲解
1 架构图
2 架构说明
2.1虚线
虚线表示异步,实线表示同步。异步不阻塞线程性能高,同步阻塞线程必须等待响应结果才能继续执行,相对性能低。
2.2Provider
暴露服务的服务提供方。
2.3Container
服务运行容器。Dubbo 完全基于 Spring 实现的。
2.4Registry
服务注册与发现的注册中心。注册中心,放置所有 Provider 对外提供的信息。包含 Provider 的 IP,访问端口,访问遵守的协议,对外提供的接口,接口中有哪些方法等相关信 息。
2.5Consumer
调用远程服务的服务消费方。
2.6Monitor
统计服务的调用次调和调用时间的监控中心。监控中心,监控 Provider 的压力情况等。 每隔 2 分钟 Consumer 和 Provider 会把调用次数发送给Monitor,由 Monitor 进行统计。
3 执行流程
- start:启动 Spring 容器时会把 Provider 启动。
- register:把 Provider 相关信息注册到 Registry 里
- subscribe:Consumer 从 Registry 中订阅 Provider 的信息
- notify:通知给 Consumer
- invoke:Consumer 根据 Registry 通知的信息进行调用 Provider 中方法。
- count:Consumer 和 Provider 把调用次数信息异步发送给 Monitor 进行统计。
三、 Dubbo 支持的协议
1 Dubbo 协议(官方推荐协议)
优点: 采用 NIO 复用单一长连接,并使用线程池并发处理请求,减少握手和加大并发效率, 性能较好(推荐使用)
缺点: 大文件上传时,可能出现问题(不使用 Dubbo 文件上传)
2 RMI(Remote Method Invocation)协议
优点: JDK 自带的能力。
缺点: 偶尔连接失败.
3 Hessian 协议
优点: 可与原生 Hessian 互操作,基于 HTTP 协议
缺点: 需 hessian.jar 支持,http 短连接的开销大
四、 Dubbo 支持的注册中心
1 Zookeeper(官方推荐)
- 优点:
支持分布式.很多周边产品. - 缺点:
受限于 Zookeeper 软件的稳定性。Zookeeper 是一款专门为分布式架构提供辅助型处 理的软件,稳定较优。
2 Multicast
- 优点:
去中心化,不需要单独安装软件. - 缺点:
2.2.1 Provider 和 Consumer 和 Registry 不能跨机房(路由)
3 Redis
- 优点:
支持集群,性能高 - 缺点:
要求服务器时间同步.否则可能出现集群失败问题.
4 Simple
- 优点:
标准 RPC 服务.没有兼容问题 - 缺点:
不支持集群.
五、 Dubbo 应用
Dubbo 在不同的版本中对于添加的依赖也是不同的。
1 创建父工程
1.1创建项目
1.2修改 POM 文件添加依赖
<?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.bjsxt</groupId>
<artifactId>parent</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<spring.version>5.2.5.RELEASE</spring.version>
<dubbo.version>2.7.6</dubbo.version>
<curator.version>4.2.0</curator.version>
<registry-zookeeper.version>2.7.6</registry-zookeeper.version>
<servlet.version>3.1.0</servlet.version>
<jsp.version>2.0</jsp.version>
<jstl.version>1.2</jstl.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-zookeeper</artifactId>
<version>${registry-zookeeper.version}</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>${curator.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlet.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>${jsp.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
2 创建服务接口
2.1创建项目
2.2添加接口
public interface DemoDubboService {
String showMsg(String str);
}
3 创建 Provider
3.1创建项目
3.2修改 POM 文件添加依赖
<?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>parent</artifactId>
<groupId>com.bjsxt</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>provider</artifactId>
<dependencies>
<dependency>
<groupId>com.bjsxt</groupId>
<artifactId>api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-zookeeper</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
</dependency>
</dependencies>
</project>
3.3添加接口实现
public class DemoDubboServiceImpl implements DemoDubboService {
@Override
public String showMsg(String str) {
return "Hello Dubbo "+str;
}
}
4 添加 Dubbo 的配置文件
4.1Dubbo 配置文件的存放位置
配置文件必须放到resources/META-INF/spring/*.xml
4.2配置文件内容
4.2.1 使用配置 bean 标签配置接口实现类
首先启动注册中心
<?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"
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="myProvider" />
<dubbo:registry address="192.168.233.130:2181" protocol="zookeeper"/>
<dubbo:protocol name="dubbo" port="20880" />
<dubbo:service interface="com.bjsxt.dubbo.service.DemoDubboService" ref="service"/>
<bean id="service" class="com.bjsxt.dubbo.service.impl.DemoDubboServiceImpl"/>
</beans>
4.2.2 使用注解方式开发服务接口
4.2.2.1 需改配置文件
<?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"
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="myProvider" />
<dubbo:registry address="192.168.233.130:2181,192.168.233.130:2182,192.168.233.130:2183" protocol="zookeeper"/>
<dubbo:protocol name="dubbo" port="20880" />
<dubbo:annotation package="com.bjsxt.dubbo.service.impl"/>
</beans>
4.2.2.2 修改接口实现类
@Service
public class DemoDubboServiceImpl implements DemoDubboService {
@Override
public String showMsg(String str) {
return "Hello Dubbo "+str;
}
}
4.3启动 Provider
4.3.1 创建 Dubbo 启动类
import org.apache.dubbo.container.Main;
public class Start {
public static void main(String[] args) {
Main.main(args);
}
}
打包 启动失败,但是没有报具体的错误原因,加一个log4j.properties就可以了
log4j.rootCategory=debug, CONSOLE ,LOGFILE
log4j.logger.com.bjsxt.mapper=DEBUG
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%C %d{YYYY-MM-dd hh:mm:ss} %m %n
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=d:/my.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%m %n
重新install,并重启,发现zookeeper连接失败 分析:这里我们搭建的是一个集群,而DUBBO默认的连接时间是5秒,这个时间对于我们的集群来说肯定是不够的,所以连接失败,所以去修改DUBBO的配置来解决。
解决: 打开官网,选择DOCS
<dubbo:registry address="192.168.233.130:2181,192.168.233.130:2182,192.168.233.130:2183" protocol="zookeeper" timeout="10000"/>
成功
5 使用 Zookeeper 客户端工具查看注册信息
ls /dubbo/服务接口名称/providers
5.1解码前
dubbo%3A%2F%2F192.168.233.1%3A20880%2Fcom.bjsxt.dubbo.service.DemoDubboServic
e%3Fanyhost%3Dtrue%26application%3DmyProvider%26deprecated%3Dfalse%26dubbo%3D2.0.
2%26dynamic%3Dtrue%26generic%3Dfalse%26interface%3Dcom.bjsxt.dubbo.service.DemoDub
boService%26methods%3DshowMsg%26pid%3D44932%26release%3D2.7.6%26side%3Dprovider
%26timestamp%3D1587025963250
5.2解码后
直接百度URL解码就行。
dubbo://192.168.233.1:20880/com.bjsxt.dubbo.service.DemoDubboService?anyhost=true&
application=myProvider&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interfac
e=com.bjsxt.dubbo.service.DemoDubboService&methods=showMsg&pid=44932&release=2.7.6
&side=provider×tamp=1587025963250
6 创建 Consumer
6.1创建项目
6.2修改 POM 文件添加依赖
<?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>parent</artifactId>
<groupId>com.bjsxt</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>consumer</artifactId>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>com.bjsxt</groupId>
<artifactId>api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-zookeeper</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>8080</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
</project>
6.3编写配置文件
6.3.1 Spring 配置文件
applicationContext-service.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<context:component-scan base-package="com.bjsxt.service"/>
</beans>
6.3.2 SpringMVC 配置文件
springmvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.bjsxt.web.controller"/>
<mvc:annotation-driven/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
6.3.3 Dubbo 配置文件
applicationContext-dubbo.xml
<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" xmlns:dubbot="http://dubbo.apache.org/schema/dubbo"
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
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<dubbo:application name="myConsumer"/>
<dubbo:registry address="192.168.233.130:2181,192.168.233.130:2182,192.168.233.130:2183" protocol="zookeeper" timeout="10000"/>
<dubbo:annotation package="com.bjsxt.service.impl"/>
</beans>
6.3.4 Web.xml 配置文件
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/applicationContext-*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>encodeFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodeFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
7 实现远程调用
7.1创建业务层
public interface DemoService {
String showInfo(String str);
}
import com.bjsxt.dubbo.service.DemoDubboService;
import com.bjsxt.service.DemoService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class DemoServiceImpl implements DemoService {
@Reference
private DemoDubboService demoDubboService;
@Override
public String showInfo(String str) {
return this.demoDubboService.showMsg(str);
}
}
7.2创建 Controller 层
@RestController
public class DemoController {
@Autowired
private DemoService demoService;
@RequestMapping("/getMsg")
public String getMsg(String str){
return this.demoService.showInfo(str);
}
}
7.3测试结果
六、 Spring Boot 整合 Dubbo
1 创建服务接口
1.1创建项目
1.2添加接口
public interface DemoDubboService {
String showMsg(String str);
}
2 创建 Provider
2.1创建项目
2.2修改 POM 文件添加依赖
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/>
</parent>
<groupId>com.bjsxt</groupId>
<artifactId>springbootdubbo_provider</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springbootdubbo_provider</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.bjsxt</groupId>
<artifactId>springbootdubbo_api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.6</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-zookeeper</artifactId>
<version>2.7.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.3添加接口实现
@Service
public class DemoDubboServiceImpl implements DemoDubboService {
@Override
public String showMsg(String str) {
return "Hello Dubbo "+str;
}
}
2.4在配置文件中配置 Dubbo
application.yml
#指定服务的名称
dubbo:
application:
name: myProvider
registry:
address: zookeeper://192.168.233.130:2181?backup=192.168.233.130:2182,192.168.233.130:2183
timeout: 10000
#配置服务所使用的协议
protocol:
name: dubbo
port: 20880
scan:
base-packages: com.bjsxt.springbootdubbo_provider.service.impl
2.5启动 Provider
2.5.1 通过 spring-boot-starter-web 启动 Dubbo
如果在项目中添加的是 spring-boot-starter-web 启动器,那么在启动 dubbo 后还会监听 一个端口,因为在 web 启动器中内置了一个 Tomcat,Tomcat 的启动不会影响 dubbo 的运行, 但是会多占用一个端口,未来在其他的 Provider 中还需要考虑端口分配的问题,避免端口抢 占。
2.5.2 通过 spring-boot-starter 启动 Dubbo
可以使用 spring-boot-starter 起来启动 Dubbo,在该启动器中并未包含 Tomcat 所以并不 会监听端口。
3 创建 Consumer
3.1创建项目
3.2修改 POM 文件添加依赖
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/>
</parent>
<groupId>com.bjsxt</groupId>
<artifactId>springbootdubbo_consumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springbootdubbo_consumer</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.bjsxt</groupId>
<artifactId>springbootdubbo_api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.6</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-zookeeper</artifactId>
<version>2.7.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3.3编写配置文件
application.yml
#指定服务的名称
dubbo:
application:
name: myConsumer
registry:
address: zookeeper://192.168.233.130:2181?backup=192.168.233.130:2182,192.168.233.130:2183
timeout: 10000
#配置服务所使用的协议
protocol:
name: dubbo
3.4实现远程调用
3.4.1 创建业务层
public interface DemoService {
String getMsg(String str);
}
@Service
public class DemoServiceImpl implements DemoService {
@Reference
private DemoDubboService demoDubboService;
@Override
public String getMsg(String str) {
return this.demoDubboService.showMsg(str);
}
}
3.4.2 创建 Controller 层
@RestController
public class DemoController {
@Autowired
private DemoService demoService;
@RequestMapping("/getMsg")
public String getMsg(String str){
return this.demoService.getMsg(str);
}
}
3.4.3 测试结果
七、 Dubbo 监控与管理
1 监控平台: dubbo-monitor
1.1Dubbo Monitor 简介
主要用来统计服务的调用次数和调用时间,服务消费者和提供者,在内存中累计调用次 数和调用时间,定时每分钟发送一次统计数据到监控中心,监控中心则使用数据绘制图表来显示。
1.2Dubbo Monitor 的使用
修改 Monitor 的配置文件
1.3启动 Monitor
1.4Monitor 监控界面
2 管理控制台:dubbo-admin
2.1Dubbo-Admin 简介
主要包含:路由规则、动态配置、服务降级、访问控制、权重调整、负载均衡等管理功 能。
2.2Dubbo Admin 的使用
2.3启动 Admin
2.4Admin 管理界面
八、 Dubbo 中服务的负载均衡
1 什么是服务集群
一个服务,部署多次,形成的整体称为服务集群。
1.1服务集群优点
避免出现单点故障:如果集群中有某个服务宕机,其他服务可继续运行。
提高效率:在集群模式下有多个服务处理业务,相比非集群模式下可分担单个服务的压 力,提高服务效率。
1.2集群模式
1.2.1 真实集群
真实集群是指在集群中,每一个节点在一个独立的物理机中运行,当某个物理机出现设 备故障并不会影响其他节点的运行。建议在生产环境中使用。
优点:单个硬件出现故障并不会影响集群中其他节点的运行。
缺点:加大硬件成本的开销。
1.2.2 伪集群
集群中所有的服务都部署到同一台设备上,通过不同端口区分不同个体。当设备出现问 题会导致整个集群不可用。学习阶段可以使用,但不建议在生产环境中使用。
优点:可节省硬件成本开销。
缺点:硬件出现故障会影响正个集群的使用。
2 什么是负载均衡
2.1负载均衡简介
负载均衡(Load Balance),是指将负载(工作任务,访问请求)进行平衡、分摊到多 个操作单元(服务器,组件)上进行执行。 最常见的负载均衡 这一种古老的方式,通过入口提供不同线路、不同服务器链接的方式,来实现负载均衡, 一般在提供下载业务的网站比较常见。
3 负载均衡解决方案分类及特征
3.1集中式负载均衡
即在客户端和服务端之间使用独立的负载均衡设施(可以是硬件,如 F5, 也可以是软件, 如 nginx), 由该设施负责把访问请求通过某种策略转发至服务端。
3.1.1 常见的集中式负载均衡方式
3.1.1.1 DNS 轮询
大多域名注册商都支持 DNS 轮询,DNS 服务器将解析请求按照配置顺序,逐一分配到 不同的 IP 上,这样就完成了简单的负载均衡。
3.1.1.2 反向代理负载均衡
使用代理服务器,可以将请求转发给内部的服务器。Nginx 是比较常见的服务反向代理 技术。在 Nginx 中是支持对代理的服务的负载均衡处理的。
3.1.1.3 基于硬件的负载均衡
硬件负载均衡解决方案是直接在服务器和外部网络间安装负载均衡设备,这种设备我们 通常称之为负载均衡器,由于专门的设备完成专门的任务,独立于操作系统,整体性能得到 大量提高,加上多样化的负载均衡策略,智能化的流量管理,可达到最佳的负载均衡需求。 常见的主流产品: F5 BIG-IP 负载均衡器(LTM) 思科 IOS 路由器 Radware 的 AppDirector 系列
3.2进程内负载均衡
将负载均衡逻辑集成到服务组件中,服务组件从服务注册中心获知有哪些地址可用,然 后根据指定的负载均衡策略选择出一个合适的服务来调用。
4 Dubbo 的内置负载均衡策略
4.1Random
随机访问集群中节点。访问概率和权重有关。是 Dubbo 的默认负载均衡策略。 权重(weight):占有比例。集群中每个项目部署的服务器的性能可能是不同,性能好 的服务器权重应该高一些。
4.2RoundRobin
轮询。访问频率和权重有关。
4.3LeastActive
最少活跃调用数,相同活跃数的随机。 如果某个机器性能越差,那么接收的请求越少,越不活跃,此时就会给不活跃的性能差 的机器分配更少的请求。
4.4ConsistentHash
一致性 Hash 算法,相同参数的请求一定分发到同一个 Provider 如果需要某一类请求 都到一个节点,那么可以使用一致性 Hash 策略。
5 Dubbo 负载均衡的使用
Dubbo 的负载均衡可以在 Consumer 或者 Provider 中通过配置文件或者注解来配置。
5.1在 Consumer 中配置负载均衡
将 Provider 启动三次,在启动时注意修改 dubbo.protocol.port 的值。
5.1.1 启动 Provider 集群
5.1.1.1 通过创建多个启动类启动
可以为 Provider 创建多个启动类来启动,通过不同的启动类来启动集群中不同的节点。
5.1.1.2 通过一个启动类启动多次
打开配置启动项 选择需要多次运行的启动类,将 Allow parallel run 选中,开启允许并行运行。
5.1.2 通过注解配置负载均衡
在 Dubbo 中,如果没有指定负载均衡策略,那么 Dubbo 默认的使用随机策略调用 Provider。
5.1.2.1 指定负载均衡策略
修改@Refrence 注解添加 loadbalance 属性指定负载均衡策略。
@Reference(loadbalance ="负载均衡策略")
5.1.2.2 随机策略配置权重
随机获取一个[0, totalWeight) 之间的数, offset = offset - weight ,如果 offset 小于 0,则 选中,很明显 weight 大的更容易让 offset 的值小于 0。 举个例子 有 4 权重分别为(1,2, 3, 4),totalWeight = 10 , 假如 offset = 6, 6 - 1 = 5, 5 大于 0,继续 5 - 2 = 3 大于 0,3 - 3 = 0, 0 - 4 小于 0 ,所以选择权重为 4 的 invoker, 这里可以发现只要 offset >= 6 则选择权重为 4 的 invoker, 正好是 40%。
5.1.2.3 通过 Provider 的@Service 注解配置权重
@Service(weight = 权重数)
例如:
@Service(weight = 3)
public class DemoDubboServiceImpl implements DemoDubboService {
@Override
public String showMsg(String str) {
System.out.println("20883......");
return "Hello Dubbo "+str;
}
}
5.1.2.4 配置轮询策略
所谓轮询是指将请求轮流分配给每台服务器。举个例子,我们有三台服务器 A、B、C。 我们将第一个请求分配给服务器 A,第二个请求分配给服务器 B,第三个请求分配给服务 器 C,第四个请求再次分配给服务器 A。这个过程就叫做轮询。
@Reference(loadbalance = "roundrobin")
5.1.2.5 轮询策略加权
如果我们将等量的请求分配给性能较差的服务器,这显然是不合理的。因此,这个时候 我们需要对轮询过程进行加权,以调控每台服务器的负载。经过加权后,每台服务器能够得 到的请求数比例,接近或等于他们的权重比。
@Service(weight = 权重数)
5.1.3 通过配置文件配置配置负载均衡
在 SpringBoot 的配置文件中可以配置全局的负载均衡。Consumer 中所有调用 Provider 集群的业务层都会使用该负载均衡策略。
与注解配置方式区别: 注解配置方式:局部,只针对当前业务层生效。 配置文件方式:全局,对所有业务层生效。
dubbo:
consumer:
loadbalance: random
5.2在 Provider 中配置负载均衡
5.2.1 在 Dubbo 的@Service 注解中配置负载均衡以及权重
@Service(loadbalance = "roundrobin",weight = 3)
5.2.2 通过配置文件配置负载均衡
dubbo:
provider:
loadbalance: aoundrobin
九、 项目打包
1 基于 SpringBoot 整合 Dubbo 的打包方式
通过 SpringBoot 打包插件打包项目
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
2 基于 Assembly 插件打包
2.1Assembly 插件
Assembly是Mave的打包插件,他的作用是可以帮助我们对jar 项目做打包处理。在Spring 整合 dubbo 的项目中,需要使用 Assembly 打包插件来对项目做打包处理。
2.2使用步骤
- 需要在项目根下创建一个目录,名称为 assembly
- 将示例中 bin,conf 目录拷贝到 assembly 的根目录中
- 删除 conf 目录中 dubbo.properties 配置文件中的
内容 - 修改项目的 POM 文件添加 assembly 的打包插件
- 在 assembly 目录下添加 assembly.xml 配置文件
<?xml version='1.0' encoding='UTF-8'?>
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
<id>assembly</id>
<formats>
<format>tar.gz</format>
</formats>
<includeBaseDirectory>true</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>assembly/bin</directory>
<outputDirectory>bin</outputDirectory>
<fileMode>0755</fileMode>
</fileSet>
<fileSet>
<directory>assembly/conf</directory>
<outputDirectory>conf</outputDirectory>
<fileMode>0644</fileMode>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<outputDirectory>lib</outputDirectory>
</dependencySet>
</dependencySets>
</assembly>
- 运行打包插件,对项目进行打包处理。可以使用 maven 的 install 命令,也可以使用 插件的命令
- 修改 start.sh 或 start.bat 中配置信息,将启动类修改为当前 dubbo 版本的启动类
nohup java $JAVA_OPTS $JAVA_MEM_OPTS $JAVA_DEBUG_OPTS $JAVA_JMX_OPTS
-classpath $CONF_DIR:$LIB_JARS org.apache.dubbo.container.Main >
$STDOUT_FILE 2>&1 &
十、 Dubbo 实战案例
1 案例介绍
1.1需求
完成对用户表的 CRUD 操作。
1.2架构方式
使用分布式架构方式。
1.3技术选型
Maven、Spring Boot、Thymeleaf、Zookeeper、Dubbo、MySql
1.4项目结构设计
2 创建表
CREATE TABLE `users` (
`userid` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(30) DEFAULT NULL,
`userage` int(11) DEFAULT NULL,
PRIMARY KEY (`userid`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
3 创建项目
3.1创建 dubbo_parent 父项目
3.1.1 创建项目
3.1.2 修改 POM 文件
<?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.bjsxt</groupId>
<artifactId>dubbo_parent</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<properties>
<dubbo.spring.starter.version>2.7.6</dubbo.spring.starter.version>
<dubbo.registry.zookeeper.version>2.7.6</dubbo.registry.zookeeper.version>
<mybatis.spring.starter.version>2.1.2</mybatis.spring.starter.version>
<mysql.connector.version>5.1.38</mysql.connector.version>
<mybatis-generator.version>1.3.5</mybatis-generator.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>${dubbo.spring.starter.version}</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-zookeeper</artifactId>
<version>${dubbo.registry.zookeeper.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.spring.starter.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.connector.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>${mybatis-generator.version}</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
3.2创建 user_api
3.2.1 创建项目
3.2.2 修改 POM 文件
<?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_parent</artifactId>
<groupId>com.bjsxt</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>user_api</artifactId>
<dependencies>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-zookeeper</artifactId>
<exclusions>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>
3.3创建 user_consumer
3.3.1 创建项目
3.3.2 修改 POM 文件
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/>
</parent>
<groupId>com.bjsxt</groupId>
<artifactId>user_consumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>user_consumer</name>
<description>Demo project for Spring Boot</description>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.bjsxt</groupId>
<artifactId>dubbo_parent</artifactId>
<version>1.0-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.bjsxt</groupId>
<artifactId>user_api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3.3.3 修改配置文件
dubbo:
application:
name: myConsumer
registry:
address: zookeeper://192.168.233.130:2181?backup=192.168.233.130:2182,192.168.233.130:2183
timeout: 10000
#配置服务所使用的协议
protocol:
name: dubbo
3.4创建 user_provider 项目及模块
3.4.1 创建项目及模块
3.4.2 修改项目模块的 POM 文件
3.4.2.1 修改 Mapper 项目的 POM 文件
<?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>user_provider</artifactId>
<groupId>com.bjsxt</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>mapper</artifactId>
<dependencies>
<dependency>
<groupId>com.bjsxt</groupId>
<artifactId>pojo</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
</dependency>
</dependencies>
<configuration>
<configurationFile>${project.basedir}/src/main/resources/generatorConfig.xml</configurationFile>
<verbose>true</verbose>
<overwrite>true</overwrite>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
</project>
3.4.2.2 修改 Provider 项目的 POM 文件
继承 Spring Boot 父工程
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.bjsxt</groupId>
<artifactId>provider</artifactId>
<version>0.0.1-SNAPSHOT</version>
继承 dubbo_parent 工程
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.bjsxt</groupId>
<artifactId>user_provider</artifactId>
<version>1.0-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
添加其他依赖
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.bjsxt</groupId>
<artifactId>mapper</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.bjsxt</groupId>
<artifactId>user_api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
3.4.3 配置 Provider
3.4.3.1 添加 application.yml 配置文件
#配置数据源
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.1.3:3306/bjsxt?serverTimezone=UTC
username: root
password: root
#Mybatis配置
mybatis:
type-aliases-package: com.bjsxt.pojo
#Dubbo配置
dubbo:
application:
name: myProvider
registry:
address: zookeeper://192.168.233.130:2181?backup=192.168.233.130:2182,192.168.233.130:2183
timeout: 10000
#配置服务协议及端口
protocol:
name: dubbo
port: 20880
#配置Dubbo扫描包
scan:
base-packages: com.bjsxt.provider.service.impl
3.4.3.2 需改启动类
@SpringBootApplication
@MapperScan("com.bjsxt.mapper")
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
3.5通过 Mybatis Generator 插件生成 Mapper 与 POJO
3.5.1 添加 generatorConfig.xml 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="testTables" targetRuntime="MyBatis3">
<plugin type="org.mybatis.generator.plugins.SerializablePlugin" />
<plugin type="org.mybatis.generator.plugins.ToStringPlugin" ></plugin>
<commentGenerator>
<property name="suppressAllComments" value="true" />
</commentGenerator>
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/bjsxt" userId="root"
password="root">
</jdbcConnection>
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<javaModelGenerator targetPackage="com.bjsxt.pojo"
targetProject=".\src\main\java">
<property name="enableSubPackages" value="false" />
<property name="trimStrings" value="true" />
</javaModelGenerator>
<sqlMapGenerator targetPackage="com.bjsxt.mapper"
targetProject=".\src\main\java">
<property name="enableSubPackages" value="false" />
</sqlMapGenerator>
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.bjsxt.mapper"
targetProject=".\src\main\java">
<property name="enableSubPackages" value="false" />
</javaClientGenerator>
<table schema="" tableName="users"></table>
</context>
</generatorConfiguration>
3.5.2 运行 Mybatis Generator 插件
3.5.3 将实体类拷贝到 pojo 项目中
4 修改 user_api 的 POM 文件添加 pojo 依赖
4.1添加 pojo 依赖
<?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_parent</artifactId>
<groupId>com.bjsxt</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>user_api</artifactId>
<dependencies>
<dependency>
<groupId>com.bjsxt</groupId>
<artifactId>pojo</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-zookeeper</artifactId>
<exclusions>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>
4.2排除冲突依赖
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-zookeeper</artifactId>
<exclusions>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
5 实现业务
5.1添加用户业务
5.1.1 创建添加用户业务接口
5.1.1.1 在 user_api 项目中创建添加用户接口
public interface AddUserService { void
addUser(Users users);
}
5.1.1.2 在 provider 中实现添加用户业务接口
package com.bjsxt.provider.service.impl;
import com.bjsxt.api.AddUserService;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
@Service
public class AddUserServiceImpl implements AddUserService {
@Autowired
private UsersMapper usersMapper;
@Override
public void addUser(Users users) {
this.usersMapper.insert(users);
}
}
5.1.2 在 Consumer 中调用添加用户业务接口
5.1.2.1 创建首页
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<link rel="shortcut icon" href="../resources/favicon.ico" th:href="@{/static/favicon.ico}"/>
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<a href="/addUser">添加用户</a> <a href="/user/getUser">查询用户</a>
</body>
</html>
5.1.2.2 创建页面跳转 Controller
package com.bjsxt.consumer.web.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class PageController {
@RequestMapping("/{page}")
public String showPage(@PathVariable String page){
return page;
}
}
5.1.2.3 解决项目无法获取 favicon.ico 的异常
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<link rel="shortcut icon" href="../resources/favicon.ico" th:href="@{/static/favicon.ico}"/>
5.1.2.4 创建添加用户页面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<link rel="shortcut icon" href="../resources/favicon.ico" th:href="@{/static/favicon.ico}"/>
<head>
<meta charset="UTF-8">
<title>添加用户</title>
</head>
<body>
<form action="/user/addUser" method="post">
用户姓名: <input type="text" name="username"/><br/>
用户年龄:<input type="text" name="userage"/><br/>
<input type="submit" value="OK"/>
</form>
</body>
</html>
5.1.2.5 创建 Consumer 业务层
package com.bjsxt.consumer.service;
import com.bjsxt.pojo.Users;
import java.util.List;
public interface UserService {
void addUser(Users users);
}
package com.bjsxt.consumer.service.impl;
import com.bjsxt.api.AddUserService;
import com.bjsxt.consumer.service.UserService;
import com.bjsxt.pojo.Users;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserServiceImpl implements UserService {
@Reference
private AddUserService addUserService;
@Override
public void addUser(Users users) {
this.addUserService.addUser(users);
}
}
5.1.2.6 创建添加用户 Controller
package com.bjsxt.consumer.web.controller;
import com.bjsxt.consumer.service.UserService;
import com.bjsxt.pojo.Users;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
@Controller
@RequestMapping("/user")
public class UsersController {
@Autowired
private UserService userService;
@RequestMapping("/addUser")
public String addUser(Users users){
this.userService.addUser(users);
return "redirect:/ok";
}
}
5.1.2.7 创建成功页面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<link rel="shortcut icon" href="../resources/favicon.ico" th:href="@{/static/favicon.ico}"/>
<head>
<meta charset="UTF-8">
<title>成功页面</title>
</head>
<body>
操作成功请<a href="/index">返回</a>
</body>
</html>
5.2查询用户业务
5.2.1 创建查询用户业务接口
5.2.1.1 在 user_api 项目中添加查询用户业务接口
public interface FindUserService {
List<Users> findUserAll();
}
5.2.1.2 在 provider 中实现查询用户业务接口
package com.bjsxt.provider.service.impl;
import com.bjsxt.api.FindUserService;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import com.bjsxt.pojo.UsersExample;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
@Service
public class FindUserServiceImpl implements FindUserService {
@Autowired
private UsersMapper usersMapper;
@Override
public List<Users> findUserAll() {
UsersExample example = new UsersExample();
return this.usersMapper.selectByExample(example);
}
}
5.2.2 在 Consumer 中调用查询用户业务
5.2.2.1 修改 Consumer 业务层添加查询用户业务
List<Users> getUsersAll();
@Override
public List<Users> getUsersAll() {
return this.findUserService.findUserAll();
}
5.2.2.2 修改 Consumer 添加处理查询用户请求
@RequestMapping("/getUser")
public String getUser(Model model){
List<Users> list = this.userService.getUsersAll();
model.addAttribute("list",list);
return "showUser";
}
5.2.2.3 创建 showUser 页面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<link rel="shortcut icon" href="../resources/favicon.ico" th:href="@{/static/favicon.ico}"/>
<head>
<meta charset="UTF-8">
<title>显示用户</title>
</head>
<body>
<table border="1" align="center">
<tr>
<th>用户ID</th>
<th>用户姓名</th>
<th>用户年龄</th>
<th>操作</th>
</tr>
<tr th:each="user:${list}">
<td th:text="${user.userid}"></td>
<td th:text="${user.username}"></td>
<td th:text="${user.userage}"></td>
<td>
<a th:href="@{/user/preUpdateUser(userid=${user.userid})}">修改用户</a>
<a th:href="@{/user/deleteUser(userid=${user.userid})}">删除用户</a>
</td>
</tr>
</table>
</body>
</html>
5.3更新用户业务
5.3.1 创建更新用户业务接口
5.3.1.1.1 在 user_api 项目中添加更新用户业务接口
public interface UpdateUserService {
Users preUpdateUsers(Integer userid);
void updateUsers(Users users);
}
5.3.1.1.2 在 provider 中实现更新用户业务接口
package com.bjsxt.provider.service.impl;
import com.bjsxt.api.UpdateUserService;
import com.bjsxt.mapper.UsersMapper;
import com.bjsxt.pojo.Users;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
@Service
public class UpdateUserServiceImpl implements UpdateUserService {
@Autowired
private UsersMapper usersMapper;
@Override
public Users preUpdateUsers(Integer userid) {
return this.usersMapper.selectByPrimaryKey(userid);
}
@Override
public void updateUsers(Users users) {
this.usersMapper.updateByPrimaryKey(users);
}
}
5.3.2 在 Consumer 中调用更新用户业务
5.3.2.1 修改 Consumer 业务层添加预更新查询用户业务
Users preUpdateUsers(Integer userid);
@Override
public Users preUpdateUsers(Integer userid) {
return this.updateUserService.preUpdateUsers(userid);
}
5.3.2.2 修改 Consumer 添加处理查询用户请求
@RequestMapping("/preUpdateUser")
public String preUpdateUser(Integer userid,Model model){
Users users = this.userService.preUpdateUsers(userid);
model.addAttribute("users",users);
return "updateUsers";
}
5.3.2.3 创建更新用户页面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<link rel="shortcut icon" href="../resources/favicon.ico" th:href="@{/static/favicon.ico}"/>
<head>
<meta charset="UTF-8">
<title>更新用户</title>
</head>
<body>
<form action="/user/updateUser" method="post">
<input type="hidden" name="userid" th:value="${users.userid}"/><br/>
用户姓名: <input type="text" name="username" th:value="${users.username}"/><br/>
用户年龄:<input type="text" name="userage" th:value="${users.userage}"/><br/>
<input type="submit" value="Update"/>
</form>
</body>
</html>
5.3.2.4 修改 Consumer 业务层添加更新用户业务
void updateUsers(Users users);
@Override
public void updateUsers(Users users) {
this.updateUserService.updateUsers(users);
}
5.3.2.5 修改 Consumer 添加处理更新用户请求
@RequestMapping("/updateUser")
public String updateUser(Users users){
this.userService.updateUsers(users);
return "redirect:/ok";
}
5.4删除用户业务
5.4.1 创建删除用户业务接口
5.4.1.1 在 user_api 项目中添加删除用户业务接口
public interface DeleteUserService {
void deleteUsersById(Integer userid);
}
5.4.1.2 在 provider 中实现删除用户业务接口
package com.bjsxt.provider.service.impl;
import com.bjsxt.api.DeleteUserService;
import com.bjsxt.mapper.UsersMapper;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
@Service
public class DeleteUserServiceImpl implements DeleteUserService {
@Autowired
private UsersMapper usersMapper;
@Override
public void deleteUsersById(Integer userid) {
this.usersMapper.deleteByPrimaryKey(userid);
}
}
5.4.2 在 Consumer 中调用删除用户业务
5.4.2.1 修改 Consumer 业务层添加删除用户业务
void deleteUsersById(Integer userid);
@Override
public void deleteUsersById(Integer userid) {
this.deleteUserService.deleteUsersById(userid);
}
5.4.2.2 修改 Consumer 添加处理删除用户请求
@RequestMapping("/deleteUser")
public String deleteUser(Integer userid){
this.userService.deleteUsersById(userid);
return "redirect:/ok";
}
5.5项目部署
5.5.1 部署环境
安装三台 Linux 操作系统,并正确安装 JDK。 192.168.233.130:部署 Zookeeper 192.168.233.131:部署 Provider 192.168.233.132:部署 Consumer
5.5.2 部署 Provider
5.5.2.1 在配置文件中修改数据库连接地址
#配置数据源
spring:
datasource: driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.1.3:3306/bjsxt?serverTimezone=UTC
username: root
password: root
5.5.2.2 在 Linux 系统中创建 Provider 目录
[root@localhost local]# mkdir provider
5.5.2.3 项目打包
5.5.2.4 上传启 Provider 项目与启动脚本
server.sh
#!/bin/bash
cd `dirname $0`
CUR_SHELL_DIR=`pwd`
CUR_SHELL_NAME=`basename ${BASH_SOURCE}`
JAR_NAME="项目名称"
JAR_PATH=$CUR_SHELL_DIR/$JAR_NAME
#JAVA_MEM_OPTS=" -server -Xms1024m -Xmx1024m -XX:PermSize=128m"
JAVA_MEM_OPTS=""
#如果是多环境配置需要在该选项中指定profile
SPRING_PROFILES_ACTIV="-Dspring.profiles.active=配置文件profile名称"
#如果没有多环境配置将 SPRING_PROFILES_ACTIV注释掉,将SPRING_PROFILES_ACTIV=""释放开
#SPRING_PROFILES_ACTIV=""
LOG_DIR=$CUR_SHELL_DIR/logs
LOG_PATH=$LOG_DIR/${JAR_NAME%..log
echo_help()
{
echo -e "syntax: sh $CUR_SHELL_NAME start|stop"
}
if [ -z $1 ];then
echo_help
exit 1
fi
if [ ! -d "$LOG_DIR" ];then
mkdir "$LOG_DIR"
fi
if [ ! -f "$LOG_PATH" ];then
touch "$LOG_DIR"
fi
if [ "$1" == "start" ];then
# check server
PIDS=`ps --no-heading -C java -f --width 1000 | grep $JAR_NAME | awk '{print $2}'`
if [ -n "$PIDS" ]; then
echo -e "ERROR: The $JAR_NAME already started and the PID is ${PIDS}."
exit 1
fi
echo "Starting the $JAR_NAME..."
# start
nohup java $JAVA_MEM_OPTS -jar $SPRING_PROFILES_ACTIV $JAR_PATH >> $LOG_PATH 2>&1 &
COUNT=0
while [ $COUNT -lt 1 ]; do
sleep 1
COUNT=`ps --no-heading -C java -f --width 1000 | grep "$JAR_NAME" | awk '{print $2}' | wc -l`
if [ $COUNT -gt 0 ]; then
break
fi
done
PIDS=`ps --no-heading -C java -f --width 1000 | grep "$JAR_NAME" | awk '{print $2}'`
echo "${JAR_NAME} Started and the PID is ${PIDS}."
echo "You can check the log file in ${LOG_PATH} for details."
elif [ "$1" == "stop" ];then
PIDS=`ps --no-heading -C java -f --width 1000 | grep $JAR_NAME | awk '{print $2}'`
if [ -z "$PIDS" ]; then
echo "ERROR:The $JAR_NAME does not started!"
exit 1
fi
echo -e "Stopping the $JAR_NAME..."
for PID in $PIDS; do
kill $PID > /dev/null 2>&1
done
COUNT=0
while [ $COUNT -lt 1 ]; do
sleep 1
COUNT=1
for PID in $PIDS ; do
PID_EXIST=`ps --no-heading -p $PID`
if [ -n "$PID_EXIST" ]; then
COUNT=0
break
fi
done
done
echo -e "${JAR_NAME} Stopped and the PID is ${PIDS}."
else
echo_help
exit 1
fi
5.5.2.5 为启动脚本分配执行权限
root@localhost provider]# chmod 777 server.sh
5.5.2.6 启动 Provider
[root@localhost logs]# ./server.sh start
5.5.3 部署 Consumer
5.5.3.1 在 Linux 系统中创建 Consumer 目录
[root@localhost local]# mkdir consumer
5.5.3.2 项目打包
5.5.3.3 上传启 Provider 项目与启动脚本
5.5.3.4 为启动脚本分配执行权限
root@localhost provider]# chmod 777 server.sh
5.5.3.5 启动 Consumer
[root@localhost logs]# ./server.sh start
5.5.3.6 测试
FastDFS
|