irpas技术客

分布式RPC调用和分布式文件存储_Dubbo 实战_脑袋不灵光的小白羊

网络 7326

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:通知给 Consumerinvoke: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://·.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&timestamp=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://·/xml/ns/javaee" xmlns:xsi="http://·/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> <!--SpringMVC中的编码过滤器--> <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; /** * Consumer的业务层 */ @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/> <!-- lookup parent from repository --> </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/> <!-- lookup parent from repository --> </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 //使用的是Spring的@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) //在Provider中使用的dubbo的@Service注解。 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"> <!-- 该字符会添加到最终tar.gz包的名称后面,作为后缀 当前应用 : dubbo-rpc-service-impl 打包后 : dubbo-rpc-service-impl-assembly.tar.gz --> <id>assembly</id> <!-- 指定打包的格式为tar.gz,该类型压缩包在linux中比较常见 --> <formats> <format>tar.gz</format> </formats> <!-- 在tar.gz压缩包中是否包含根文件夹,该根文件夹名称和tar.gz去掉id后缀一致 --> <includeBaseDirectory>true</includeBaseDirectory> <fileSets> <!-- 将项目根路径下assembly/bin路径中的内容打包到压缩包中的根目录下的bin目录中 --> <fileSet> <!-- 相对项目根路径的相对路径 --> <directory>assembly/bin</directory> <outputDirectory>bin</outputDirectory> <!-- 设置最终tar.gz中该文件夹下的权限,跟linux权限写法一致 --> <fileMode>0755</fileMode> </fileSet> <!-- 将项目根路径下assembly/conf路径中的内容打包到压缩包中的根目录下的conf目录中 --> <fileSet> <directory>assembly/conf</directory> <outputDirectory>conf</outputDirectory> <!-- 设置其linux权限 --> <fileMode>0644</fileMode> </fileSet> </fileSets> <!-- 将所有依赖的jar包打包到压缩包中的根目录下的lib目录中 --> <!-- 此lib目录中包含自己开发的项目jar包以及dubbo-rpc-service-impl.jar, 还有第三方的jar包 --> <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> <!--Dubbo Starter Dependency Version:2.7.6--> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>${dubbo.spring.starter.version}</version> </dependency> <!--Zookeeper Registry Dependency Version:2.7.6--> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-registry-zookeeper</artifactId> <version>${dubbo.registry.zookeeper.version}</version> </dependency> <!--Mybatis Starter Dependency Version:2.1.2--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>${mybatis.spring.starter.version}</version> </dependency> <!--MySQL Driver Dependency Version:5.1.38--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.connector.version}</version> </dependency> </dependencies> </dependencyManagement> <build> <pluginManagement> <plugins> <!--MyBatis Generator Plugin--> <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> <!--Zookeeper Registry 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> <!--Dubbo Starter 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/> <!-- lookup parent from repository --> </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> <!--Dependency dubbo_parent--> <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> <!--user_api Dependency --> <dependency> <groupId>com.bjsxt</groupId> <artifactId>user_api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!--Spring Boot Starter Web Dependency --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--Spring Boot Starter Thymeleaf Dependency --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <!--Spring Boot Starter Test 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> <!--POJO Dependency--> <dependency> <groupId>com.bjsxt</groupId> <artifactId>pojo</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!--MyBatis Starter Dependency--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> <!--MySQL Driver Dependency--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> </dependencies> <build> <plugins> <!--MyBatis Generator Plugin--> <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> <!--Configure Resource Copy Path--> <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/> <!-- lookup parent from repository --> </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> <!--Mapper Dependency--> <dependency> <groupId>com.bjsxt</groupId> <artifactId>mapper</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!--user_api Dependency--> <dependency> <groupId>com.bjsxt</groupId> <artifactId>user_api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!--Spring Boot Starter Dependency--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!--Spring Boot Test Starter 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")//指定扫描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" /> <!-- 实体类中包含toString() --> <plugin type="org.mybatis.generator.plugins.ToStringPlugin" ></plugin> <commentGenerator> <!-- 是否去除自动生成的注释 true:是 : false:否 --> <property name="suppressAllComments" value="true" /> </commentGenerator> <!--数据库连接的信息:驱动类、连接地址、用户名、密码 --> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/bjsxt" userId="root" password="root"> </jdbcConnection> <!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 和 NUMERIC 类型解析为java.math.BigDecimal --> <javaTypeResolver> <property name="forceBigDecimals" value="false" /> </javaTypeResolver> <!-- targetProject:生成POJO类的位置 --> <javaModelGenerator targetPackage="com.bjsxt.pojo" targetProject=".\src\main\java"> <!-- enableSubPackages:是否让schema作为包的后缀 --> <property name="enableSubPackages" value="false" /> <!-- 从数据库返回的值被清理前后的空格 --> <property name="trimStrings" value="true" /> </javaModelGenerator> <!-- targetProject:mapper映射文件生成的位置 --> <sqlMapGenerator targetPackage="com.bjsxt.mapper" targetProject=".\src\main\java"> <!-- enableSubPackages:是否让schema作为包的后缀 --> <property name="enableSubPackages" value="false" /> </sqlMapGenerator> <!-- targetPackage:mapper接口生成的位置 --> <javaClientGenerator type="XMLMAPPER" targetPackage="com.bjsxt.mapper" targetProject=".\src\main\java"> <!-- enableSubPackages:是否让schema作为包的后缀 --> <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> <!--pojo Dependency--> <dependency> <groupId>com.bjsxt</groupId> <artifactId>pojo</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!--Zookeeper Registry 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> <!--Dubbo Starter 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>&nbsp;&nbsp;&nbsp;<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; /** * 查询全部用户 * @return */ @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(); /** * 查询所有用户 * @return */ @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; /** * 预更新用户查询 * @param userid * @return */ @Override public Users preUpdateUsers(Integer userid) { return this.usersMapper.selectByPrimaryKey(userid); } /** * 更新用户 * @param users */ @Override public void updateUsers(Users users) { this.usersMapper.updateByPrimaryKey(users); } } 5.3.2 在 Consumer 中调用更新用户业务 5.3.2.1 修改 Consumer 业务层添加预更新查询用户业务 Users preUpdateUsers(Integer userid); /** * 根据用户ID查询用户 * @param userid * @return */ @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); /** * 更新用户 * @param 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; /** * 根据用户ID删除用户 * @param userid */ @Override public void deleteUsersById(Integer userid) { this.usersMapper.deleteByPrimaryKey(userid); } } 5.4.2 在 Consumer 中调用删除用户业务 5.4.2.1 修改 Consumer 业务层添加删除用户业务 void deleteUsersById(Integer userid); /** * 根据用户ID删除用户 * @param 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


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #实战 #dubbo #实战主要内容Dubbo #简介Dubbo #架构详解Dubbo #支持的协议Dubbo #支持的注册中心Dubbo