第九章 Dubbo
1. Dubbo的发展背景
随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fExrWkHq-1602494371674)(https://ae01.alicdn.com/kf/H8d8556092f7b4d59921529a161412470O.png)]
1.1 单一应用架构
当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。 此时,用于简化增删改查工作量的数据访问框架(ORM)是关键。使用一个web容器(如tomcat),然后使用Servlet/JSP技术,最后选择一个合适数据库管理系统来存储数据(MySQL、Oracle)。
1.2 垂直应用架构
当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,提升效率的方法之一是将应用拆成互不相干的几个应用
,以提升效率。
此时,用于加速前端页面开发的Web框架(MVC)是关键。
用户系统、权限系统、商品系统、订单系统、物流系统…
特点:系统独立部署,每一个系统都有完整的前后端;
问题:各个系统无法做到完全独立,公共模块无法复用,系统之间通信比较麻烦;
1.3 分布式服务架构
作为独立的服务
,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的分布式服务框架(RPC)是关键。
分布式架构的难点:
- 各个系统如何进行远程调用
- 如何进行业务拆分
1.4 流动计算架构
当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。此时,用于提高机器利用率的资源调度和治理中心(SOA)是关键。
2.RPC
RPC(Remote Procedure Call)- 远程过程调用,它是一种通过网络从远程计算机程序上请求服务,不需要了解底层的网络技术协议。RPC假定某种传输协议的存在(如TCP),为通信程序携带数据;通俗的说,RPC可以让我们像调用本地方法一样调用远程计算机提供的服务;
2.1 RPC简单原理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MiZ7OC2C-1602494371684)(https://ae01.alicdn.com/kf/Hf87aef8fc1314dd696b626b9d9a99551s.png)]
- 客户端以本地调用的方式调用远程服务
- client stub接收到调用后,将方法、参数等组装成能够进行网络传输的消息;
- client stub查找服务地址,找到之后,将消息发送到服务端;
- server stub收到消息之后,对收到的消息进行解码;
- server stub根据解码结果,使用反射的方式调用本地服务;
- 服务端执行完成之后将结果返回给Server stub;
- server stub将返回结果打包成消息并发送给客户端;
- client stub收到消息后,对结果进行解码;
3. Dubbo
Apache Dubbo是一款高性能的 Java RPC框架
。
Apache Dubbo |ˈdʌbəʊ| 是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及 服务自动注册和发现。
3.1 Dubbo架构
1. 架构中的角色
- Provider :服务提供者
- Consumer :服务消费者
- Registry :服务注册和发现的中心
- Monitor :监控中心,用于统计服务调用情况
- Container : Dubbo的容器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V6RtSRDw-1602494371688)(https://ae02.alicdn.com/kf/Ha1e1718a05e545e5bcec9f268fa807adK.png)]
2. 调用关系
- 容器负责启动、加载、运行服务提供者、消费者
- 服务提供者在启动时,向注册中心注册自己提供的服务
- 服务消费者在启动时,向注册中心订阅自己需要的服务
- 注册中心返回服务提供者的地址列表给消费者,如果有服务变更(服务的上线和下线),注册中心会基于长连接的方式推送变更过给消费者
- 服务这从地址列表中,基于**软件负载聚恒算法**,选择一个服务提供者进行调用,如果调用失败,可以重试其他提供者。
- 服务消费者和提供者,在内存中累计调用时间和调用次数,每分钟向监控中心发送一次统计数据。
4. 安装单机Zookeeper
4.1 windows 版本
-
解压zookeeper-3.4.12.tar.gz 到当前目录
-
在 zookeeper-3.4.12 目录下创建
data
目录[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xySseaGU-1602494371693)(https://ae01.alicdn.com/kf/H2265729af51e43498cd2b848e6bc545d0.png)]
-
将
zookeeper-3.4.12/conf
目录下的zoo_sample.cfg
文件重命名为zoo.cfg
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jqI0pNVm-1602494371696)(https://ae03.alicdn.com/kf/Hebfa5db0720a4650805653e83f2a2049v.png)] -
修改
zoo.cfg
文件中的dataDir
选项[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3pC4AbTc-1602494371698)(https://ae01.alicdn.com/kf/H2b2484131b324d4caf53959d68115e53U.png)]
-
双击 zookeeper-3.4.12/bin/zkServer.cmd ,启动服务端
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3yFXrDCS-1602494371699)(https://ae01.alicdn.com/kf/He0fb1d817ff34bb28eefb34ca85879b5C.png)]
- 双击 zookeeper-3.4.12/bin/zkCli.cmd ,启动客户端
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hy4IYze9-1602494371701)(https://ae04.alicdn.com/kf/H23c84676e2e8495f83ebc63f731e9b002.png)]
4.2 Linux / Mac 版本
- 将 zookeeper-3.4.12.tar.gz 上传到
/opt
目录
#在压缩包目录上 运行git bash
scp zookeeper-3.4.12.tar.gz root@ip:/opt
#解压 压缩包
cd /opt
tar -zxvf zookeeper-3.4.12.tar.gz -C /opt
#创建软连接
ln -s zookeeper-3.4.12.tar.gz zookeeper
- 进入zookeeper 创建data 目录
cd zookeeper
mkdir data
- 进入zookeeper-3.4.12.tar.gz/conf目录下,将zoo_sample.cfg修改为zoo.cfg
cd conf
mv zoo_sample.cfg zoo.cfg
- 编辑zoo.cfg
vim zoo.cfg
# 输入12GA 将dataDir修改为 ../data
- 启动zookeeper服务
cd ../bin
./zkServer.sh start
- 启动ZK客户端
./zkCli.sh
5. Dubbo控制台安装
-
dubbo主要用于服务治理
-
可以通过控制台查看所有服务
-
可以设置负载均衡、权重调节、服务降级策略等
#控制台默认访问地址 http://localhost:7001 #默认的用户名和密码 root / root
-
在dubbo-admin.jar 所在的目录运行 cmd
java -jar dubbo-admin.jar 即可
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-71B7loOM-1602494371703)(https://ae02.alicdn.com/kf/H8098147f09e64c52bf8b0ce501b16a0cJ.png)]
6. dubbo普通工程
6.1创建maven父工程 dubbo-hello
- 引入maven依赖
<dependencyManagement>
<dependencies>
<!-- Dubbo -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.5</version>
<exclusions>
<!-- 排除低版本(4.3.16)的spring-context -->
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 引入高版本的spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<!-- curator: zk客户端 -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.13.0</version>
</dependency>
</dependencies>
</dependencyManagement>
6.2 创建子工程服务接口 dubbo-hello-interface
- 创建服务接口
/**
* 服务接口
*
* 服务提供者实现这个接口 提供服务
* 消费者引用这个接口 消费服务
*/
public interface HelloService {
String sayHello(String name);
}
- 创建本地存根,[暂时这个工程不需要]
/*
*使用本地存根需要在服务接口的包下创建 [接口名字]Stub类
*继承自[接口名字]类
*/
package com.etoak.service;
public class HelloServiceStub implements HelloService{
HelloService helloService;
public HelloServiceStub(HelloService helloService) {
this.helloService = helloService;
}
@Override
public String sayHello(String name) {
if(name != null && !"".equals(name) ){
return helloService.sayHello(name);
}
return "参数异常";
}
}
6.3 创建消息提供者 [dubbo-hello-provider]
- 引入maven依赖
<dependencies>
<!-- 服务提供者引入接口功能,用于实现服务接口-->
<dependency>
<artifactId>dubbo-hello-interface</artifactId>
<groupId>com.etoak.et1912.dubbo</groupId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- Dubbo -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<!-- 引入高版本的spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<!-- curator: zk客户端 -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
</dependency>
</dependencies>
- 配置provider.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://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">
<!--1.配置应用名称-->
<dubbo:application name="hello-provider" ></dubbo:application>
<!--2.配置zookeeper注册中心-->
<dubbo:registry address="zookeeper://127.0.0.1:2181" ></dubbo:registry>
<!--3.使用dubbo协议在20880端口暴露服务-->
<dubbo:protocol name="dubbo" port="20880" />
<!--4.暴露服务,也就是向注册中心注册服务-->
<dubbo:service interface="com.etoak.service.HelloService" ref="helloService" stub="true"/>
<!--5.配置服务实现-->
<bean id="helloService" class="com.etoak.service.HelloServiceImpl" ></bean>
</beans>
- 书写服务提供类
package com.etoak.service;
public class HelloServiceImpl implements HelloService{
@Override
public String sayHello(String name) {
return String.format("Hello %s",name);
}
}
- 书写测试类
package com.etoak.test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.io.IOException;
public class ProviderMain {
public static void main(String[] args) throws IOException {
new ClassPathXmlApplicationContext("provider.xml");
System.in.read();
}
}
-
运行测试类即可在测试端或者网页管理器中查看到注册的服务
- 在客户端查看已经注册的服务
ls /dubbo ls /dubbo/[service name] ls /dubbo/[service name]/provider
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NMkZohIW-1602494371705)(https://ae02.alicdn.com/kf/Hb8b621867fa145b3b3fc9b112c71b8ecY.png)]
- 在浏览器查看消息提供者
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NxbkRqXP-1602494371706)(https://ae02.alicdn.com/kf/He5fd4a7a4e054e88b5ee1507fffcab2fG.png)]
6.4 创建消息消费者 [dubbo-hello-consumer]
- 引入maven依赖
<dependencies>
<!-- 服务提供者引入接口功能,用于实现服务接口-->
<dependency>
<artifactId>dubbo-hello-interface</artifactId>
<groupId>com.etoak.et1912.dubbo</groupId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- Dubbo -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<!-- 引入高版本的spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<!-- curator: zk客户端 -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
</dependency>
</dependencies>
- 配置consumer.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
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">
<!--1.配置应用名称-->
<dubbo:application name="hello-consumer" />
<!--2.向注册中心订阅服务-->
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
<!--3.引用远程服务,创建服务代理-->
<dubbo:reference id="helloService" interface="com.etoak.service.HelloService"></dubbo:reference>
</beans>
- 创建消费者
package com.etoak.test;
import com.etoak.service.HelloService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.io.IOException;
public class ConsumerMain {
public static void main(String[] args) throws IOException {
ApplicationContext ioc = new ClassPathXmlApplicationContext("consumer.xml");
//获取远程服务的代理对象
HelloService helloService = ioc.getBean(HelloService.class);
String result = helloService.sayHello("");
System.out.println(result);
System.in.read();
}
}
- 在控制端和网页端查看消费者
-
在控制端查看
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aLI99lem-1602494371708)(https://ae04.alicdn.com/kf/H3213ad17eb8a4e3e94d527ee35823a7aG.png)]
-
在网页端查看
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XuZ1SEvW-1602494371710)(https://ae04.alicdn.com/kf/H372640990885404a8d64a2170a9fabf7g.png)]
7. dubbo 整合 springmvc
7.1 创建父工程[dubbo-mvc]
- 创建maven工程 dubbo-mvc,并引入maven依赖
<dependencyManagement>
<dependencies>
<!-- servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- spring-web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<!-- spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<!-- spring-context-support -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<!-- spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<!-- spring-tx -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<!-- thymeleaf -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>
<!-- thymeleaf-spring5 -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>
<!-- jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<!-- druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!-- myabtis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.1</version>
</dependency>
<!-- pageHelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.10</version>
</dependency>
<!-- dubbo相关依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.5</version>
<exclusions>
<!-- 剔除低版本的spring-context -->
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.13.0</version>
</dependency>
<dependency>
<groupId>com.alibaba.spring</groupId>
<artifactId>spring-context-support</artifactId>
<version>1.0.2</version>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>
</dependencyManagement>
7.2 创建 Bean工程
- 创建普通maven 工程引入lombok依赖
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
7.3 创建服务接口[dubbo-mvc-interface]
- 引入bean工程依赖
<dependencies>
<!--依赖bean工程-->
<dependency>
<artifactId>dubbo-mvc-bean</artifactId>
<groupId>com.etoak.et1912.dubbo</groupId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
7.4 创建服务提供者[dubbo-mvc-provider]
- 引入maven依赖
javax.servlet-api
spring-web
spring-context-support(spring框架的)
spring-tx
spring-jdbc
mysql
mybatis
mybatis-spring
druid
pagehelper
logback-classic
dubbo
curator-framework
spring-context-support(alibaba的)
- 配置web.xml文件
<!-- 这里只整合了spring-web,没有整合spring-webmvc,
只需要配置spring容器即可 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-root.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
- 开发用户服务接口
在interface工程开发UserService接口
- 发布用户服务到zk
<!-- 配置Dubbo -->
<dubbo:annotation package="com.etoak" />
<dubbo:application name="user-service" />
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
<dubbo:protocol name="dubbo" port="20880" />
package com.etoak.service.impl;
import com.alibaba.dubbo.config.annotation.Service;
import com.etoak.bean.User;
import com.etoak.mapper.UserMapper;
import com.etoak.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
/**
* dubbo提供的@Service注解:用于发布Dubbo服务
*/
@Service
public class UserServiceImpl implements UserService {
private static final Logger LOG =
LoggerFactory.getLogger(UserServiceImpl.class);
@Autowired
UserMapper userMapper;
@Override
public User getById(Integer id) {
LOG.info("param id - {}", id);
User user = userMapper.getById(id);
LOG.info("result - {}", user);
return user;
}
}
- 测试
1、先启动注册中心、dubbo控制台(可选)
2、再启动服务提供者
3、再启动服务消费者
4、开始测试
7.5 创建服务消费者[dubbo-mvc-consumer]
- 引入maven依赖
<dependencies>
<!--servlet-api-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<!--spring-webmvc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<!--spring:spring-context-support-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<!--thymeleaf-->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
</dependency>
<!--thymeleaf-spring5-->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
</dependency>
<!--jackson-databind-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!--logback-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--dubbo-->
</dependencies>
- 配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!--过滤器-->
<filter>
<filter-name>encoding</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>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--前端控制器-->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
- 配置spring-mvc容器
注意:address后边的地址一定不要写错,不然就报错
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
<?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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd">
<!--1. 开启注解扫描-->
<context:component-scan base-package="com.etoak">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.RestController"/>
<context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
<!--2.开启mvc配置-->
<mvc:annotation-driven></mvc:annotation-driven>
<!--3.静态文件处理-->
<mvc:default-servlet-handler />
<!--4.thymeleaf三个配置-->
<!--4.1 SpringResourceTemplateResolver-->
<bean id="templateResolver" class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
<property name="prefix" value="/templates/" />
<property name="suffix" value=".html" />
<property name="templateMode" value="HTML" />
<property name="characterEncoding" value="UTF-8" />
<property name="cacheable" value="false" />
</bean>
<!--4.2 SpringTemplateEngine-->
<bean id="templateEngine" class="org.thymeleaf.spring5.SpringTemplateEngine">
<property name="templateResolver" ref="templateResolver" />
</bean>
<!--4.3 ThymeleafViewResolver-->
<bean class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<property name="templateEngine" ref="templateEngine" />
<property name="characterEncoding" value="UTF-8" />
</bean>
<!--dubbo配置-->
<dubbo:annotation package="com.etoak" />
<dubbo:application name="mvc-consumer" />
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
</beans>
- 创建控制器测试
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/index")
public String index(){
return "index";
}
}
8.Dubbo详解
8.1 Dubbo在ZK中的存储结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hEAEUmtS-1602494371713)(https://ae04.alicdn.com/kf/H1a6dfd8de43b4b0b84107a34c5a469caA.png)]
8.2 Dubbo的注册中心有哪些
1、
Multicast
:Multicast 注册中心不需要启动任何中心节点,只要广播地址一样,就可以互相发现。2、
Zookeeper
是 Apache Hadoop 的子项目,是一个树型的目录服务,支持变更推送,适合作为 Dubbo 服务的注册中心,工业强度较高,可用于生产环境,并推荐使用;3、
Nacos
是 Dubbo 生态系统中重要的注册中心实现,其中dubbo-registry-nacos
则是 Dubbo 融合 Nacos 注册中心的实现。4、基于 Redis 实现的注册中心 。
5、
Simple
注册中心本身就是一个普通的 Dubbo 服务,可以减少第三方依赖,使整体通讯方式一致。
8.3 Dubbo支持的协议
dubbo、rmi、hessian、http、webservice、rest、thrift、memcached、redis、grpc
Dubbo官方推荐使用 dubbo协议
8.4 启动时检查
Dubbo 缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止 Spring 初始化完成,以便上线时,能及早发现问题,默认 check="true"
。
8.4.1 关闭注册中的启动检查
<dubbo:registry check="false"
address="zookeeper://127.0.0.1:2181" />
8.4.2 关闭单个服务的启动检查
<dubbo:reference id="helloService"
check="false"
interface="com.etoak.service.HelloService">
</dubbo:reference>
8.4.3 关闭所有服务的启动检查
<dubbo:consumer check="false" />
8.5 配置加载流程
文档地址
8.5.1 配置来源
首先,从Dubbo支持的配置来源说起,默认有四种配置来源:
- JVM System Properties,-D参数(配置虚拟机参数)
- Externalized Configuration,外部化配置(外部配置中心)
- ServiceConfig、ReferenceConfig等编程接口采集的配置
- 本地配置文件dubbo.properties(dubbo.properties需要放在classpath根路径下)
8.5.2 配置加载优先级
jvm参数 > 外部化配置 > api编程配置、spring配置 > dubbo.properties
idea中jvm配置
8.6 XML配置 - 不同粒度配置的覆盖关系
以 timeout 为例,下图显示了配置的查找顺序,其它 retries, loadbalance, actives 等类似:
-
方法级优先,接口级次之,全局配置再次之。
方法级配置项:
<dubbo:method>
接口级配置项:
<dubbo:service>
、<dubbo:reference>
全局级配置项:
<dubbo:provider>
、<dubbo:consumer>
-
如果级别一样,则消费方优先,提供方次之。
其中,服务提供方配置,通过 URL 经由注册中心传递给消费方。
8.7 直连提供者
在开发及测试环境下,经常需要绕过注册中心,只测试指定服务提供者,这时候可能需要点对点直连,点对点直连方式,将以服务接口为单位,忽略注册中心的提供者列表,A 接口配置点对点,不影响 B 接口从注册中心获取列表。
<dubbo:reference id="helloService"
url="dubbo://127.0.0.1:20880"
interface="com.etoak.service.HelloService">
</dubbo:reference>
8.8 本地存根
提供方有些时候想在客户端也执行部分逻辑,比如:做 ThreadLocal 缓存,提前验证参数,调用失败后伪造容错数据等等
-
实现步骤
1、在服务接口包中创建一个HelloServiceStub类,实现HelloService接口
2、需要提供一个构造方法,构造方法的参数就是HelloService的远程代理对象
3、在spring中配置本地存根
<dubbo:service ref="helloService" stub="true" interface="com.etoak.service.HelloService"> </dubbo:service>
<dubbo:service ref="helloService" stub="com.etoak.service.HelloServiceStub" interface="com.etoak.service.HelloService"> </dubbo:service>
8.9 服务分组
当一个接口有多种实现时,可以用 group 区分。
8.10 服务的多版本
当一个接口实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务相互间不引用。
可以按照以下的步骤进行版本迁移:
- 在低压力时间段,先升级一半提供者为新版本
- 再将所有消费者升级为新版本
- 然后将剩下的一半提供者升级为新版本
8.11 负载均衡 LoadBalance
在集群负载均衡时,Dubbo 提供了多种均衡策略,默认是 random
随机调用。
1. Random LoadBalance
随机
,按权重设置随机概率。
在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。
2. RoundRobin LoadBalance
轮询,按公约后的权重
设置轮询比率。
存在慢的提供者累积请求的问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。
3. LeastActive LoadBalance
最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差
。
使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。
4. ConsistentHash LoadBalance
一致性 Hash,相同参数的请求总是发到同一提供者
。
当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。
算法参见:http://en.wikipedia.org/wiki/Consistent_hashing
默认只对第一个参数 Hash,如果要修改,请配置:<dubbo:parameter key=“hash.arguments” value=“0,1” />
默认用 160 份虚拟节点,如果要修改,请配置 <dubbo:parameter key=“hash.nodes” value=“320” />
控制台配置
8.12 服务降级
可以通过服务降级
功能临时屏蔽某个出错的非关键服务,并定义降级后的返回策略。
mock=force:return+null
表示消费方对该服务的方法调用都直接返回 null 值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。- 还可以改为
mock=fail:return+null
表示消费方对该服务的方法调用失败后,再返回 null 值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。
控制台配置
9.dubbo整合spring问题
为什么引入dubbo之后就会找不到spring-root容器
Dubbo开发者不确定使用者使用什么mvc框架,如果使用者使用的是struts,那么系统中是没有spring mvc容器的,这个时候只能去spring root容器中查找配置了,所以Dubbo默认的是查找一定会存在的spring root 容器。
X.错误集锦
- Caused by: java.lang.NumberFormatException: For input string: “127.0.0.1:2181”
引发原因:dubbo整合spring mvc时连接写错了
解决办法:address后边的url一定要书写正确
<dubbo:registry address="zookeeper://127.0.0.1:2181" />