一、传统系统架构模式
主要三层架构:表现层 、业务逻辑层 、数据访问层
存在不足之处:
所有的代码在同一个项目中不方便维护,比如:100个类写在同一个包下
所有的项目都会使相同的一个代码库,当程序员提交一些错误代码,改动代码,当内容增多,效率变得低下。
商业价值:防止被别人偷取代码,直接影响公司的利益。
多模块之间相互依赖,把所有的包变成一个项目,
三层架构难免也存在责任交叉,某些地方的改动可能会带来其他层会同步变动,失去了分层的独立性。
单系统只能用一种开发语言,不能用多种开发技术
1.1 存在以上这么多的不足,那么怎么解决呢?
采用微服务方式:
a、将产品或者项目分解为众多独立的服务,这些服务独立的部署,并且不依赖与其他服务,就相当于把一个项目的各个模
块分解为不同的微服务进行项目部署
b、单系统只能用一种开发语言,但微服务每个独立服务,因此每个模块可以利用不同的技术开发,比如商品模块用SSM框
架,订单模块用SSH框架
c、开发集中在一个服务,业务和代码量都不大,开发人员更好的把握代码招不同的开发人员开发项目,提高公司的利润,
不同的人做不同的事情,开发公司成本是很重要的,如果一个公司都只会SSM框架,成本很高,肯定会招一些小弟开发项
目节约成本。
1.2 微服务也存在一些问题,怎么解决呢?
因为每个功能都是独立的服务,因此在一个较大的项目中,检测管理服务变得更加复杂,如果某一个服务出错的话,调试
跟踪比单系统更加复杂,因此建立统一的日志管理系统可能是目前解决这问题的最佳方案。那么可以采用dubbo(rpc技术)
框架 、Spring Cloud框架
二、Dubbo框架
2.1 dubbo简介
是一个分布式服务治理框架,提供高性能和透明化的RPC远程服务调用方案,可以和Spring无缝集成,是阿里巴巴SOA服
务化治理方案的核心框架,每天为2000+服务提供3亿次访问量支持
它采用的是一种非常简单的模型,要么是提供服务,要么是消费服务,所以基于这一点抽象出服务提供方(Provider) 和 服
务消费方(Consumer)两个角色
主要解决以下问题:
服务注册中心来管理服务提供方提供的接口,那么服务消费方到注册中心获取提供方提供的接口。
当dubbo开源后,当当网根据自身的需求,为Dubbo实现了一些新的功能,
2.2 Dubbo的核心要点:
服务监控:无论是哪一方,他们都需要对服务调用的实际状态进行有效的监控,从而改进服务质量。
远程通信与信息交换:双方约点的协议
服务定义:围绕服务提供方和消费方,服务提供方实现服务,服务消费方调用服务
服务注册:通过服务统一管理,比如Spring 管理整个项目,这些服务会被居中管理,Dubbo提供的注册中心有四种类型:
Multicast(多播/组播)注册中心
Zookeeper注册中心
Redis注册中心
Simle注册中心
步骤:
提供方提供服务到注册中心,消费方到注册中心调用提供方的服务,这里的服务就是接口。
在调用的时候可以监控调用是否成功,调用几次。监控中心
2.3 怎么做到分布式应用,怎么做到单项目变成多项目,可怎么做到让一个项目负载均衡?可以让以前的老项目变成dubbo项目?
2.3.1 Dubbo-parent:
实际操作步骤:
a、看官方maven仓库
b、Dubbo-parent:
导包,放在父类,子类也会依赖,是它的作用多模块那么就需要一个父模块,下面有很多子模块,父类什么都不做,
只是负责依赖jar包,创建maven项目
c、pom.xml配置和dubbo-api公共代码
d、两个不同的项目怎么交流呢?就好比有两个提供者
通过RPC技术
该接口需要单独打包,提供方和消费方需要共享
再创建一个dubbo-api 公共的代码。注意需要相互依赖
<?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>dubbo-provider</groupId>
<artifactId>dubbo-provider</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!--dubbo 阿里巴巴分布式应用框架-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>dubbo-api</groupId>
<artifactId>dubbo-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- junit测试包-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<!-- zk 客户端-->
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
</dependencies>
<!-- 打包jar详细配置 -->
<build>
<!-- jar包名字 -->
<finalName>provder</finalName>
<!-- 打包资源配置,如配置文件 -->
<resources>
<resource>
<targetPath>${project.build.directory}/classes</targetPath>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
</resource>
<!-- 结合com.alibaba.dubbo.container.Main
官方文档:dubbo会自动在classes/META-INF/spring下去加载spring的配置文件
因此打包时需要将spring配置文件复制到该目录
-->
<resource>
<targetPath>${project.build.directory}/classes/META-INF/spring</targetPath>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>provider.xml</include>
</includes>
</resource>
</resources>
<pluginManagement>
<plugins>
<!-- 解决Maven插件在Eclipse内执行了一系列的生命周期引起冲突 -->
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<versionRange>[2.0,)</versionRange>
<goals>
<goal>copy-dependencies</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore />
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<!-- 打包jar文件时,配置manifest文件,加入lib包的jar依赖 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<classesDirectory>target/classes/</classesDirectory>
<archive>
<manifest>
<mainClass>com.alibaba.dubbo.container.Main</mainClass>
<!-- 重要:打包时 MANIFEST.MF文件不记录的时间戳版本 -->
<useUniqueVersions>false</useUniqueVersions>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
<manifestEntries>
<Class-Path>.</Class-Path>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<type>jar</type>
<includeTypes>jar</includeTypes>
<!-- <useUniqueVersions>false</useUniqueVersions>-->
<outputDirectory>
${project.build.directory}/lib
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
=============================================================
public interface DemoService {
String sayHello(String name);
void save(User user);
}
@Service
public class DemoServiceImpl implements DemoService {
public String sayHello(String name) {
return "Hello " + name;
}
public void save(User user) {
System.out.println(user.getName());
}
}
=======================================================
public class User implements Serializable {
private Integer id;
private String name;
setter / getter 方法
}
2.3.2 Dubbo-order: 服务提供者
a、定义服务接口
b、在服务提供方实现该接口
上面两部已经被抽取到父类中
c、在resources下新建provider.xml 需要给Spring集成
<?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="dubbo-order" />
<!-- 使用multicast广播注册中心暴露服务地址 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181" client="zkclient"/>
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880" />
<!-- 声明需要暴露的服务接口
<dubbo:service interface="cn.itsource.DemoService" ref="demoService" owner="zs" />-->
<!-- 和本地bean一样实现服务
<bean id="demoService" class="cn.itsource.DemoServiceImpl" /> -->
<!-- 注解 -->
<dubbo:annotation package="cn.itsource" />
加载Spring的配置:启动
public class Provider2 {
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"provider.xml"});
context.start();
System.out.println("服务发布成功");
System.in.read(); // 按任意键退出
}
还可以使用Junit4测试启动
接下来可以在管理中心和检测中心查看
}
</beans>
2.3.3 Dubbo-user:服务消费者
a、通过Spring配置引用远程服务
public class Consumer {
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"consumer.xml"});
context.start();
DemoService demoService = (DemoService)context.getBean("demoService"); // 获取远程服务代理
String hello = demoService.sayHello("world"); // 执行远程方法
System.out.println( hello ); // 显示调用结果
}
}
2.3.4 Dubbo服务打包:
Dubbo服务的运行方式:
使用servlet(不推荐)
Java的main方法(不建议,本地调用可以用)
Dubbo框架的main方法
Dubbo服务Jar包运行:
Cmd窗口:
定位到jar包所在的目录
输入: java –jar xxxx.jar
2.3.5 Dubbo管理控制台:
对提供方的服务以及消费方的服务进行管理
管理员有禁用服务启用服务的权限
Dubbo-admin部署配置
启动管理控制台 bin/startup.bat
通过浏览器访问管理控制台http://127.0.0.1:端口
默认用户名及密码 : root root guest guest
2.3.6 Dubbo监控中心:
监控中心负责为服务的监控运维采集各维度的数据,统计各服务的调用次数、时间等,统计先在服务端和消费端内存中汇总,
每隔一分钟发送到监控中心服务器,并以报表的形式展现。
2.3.7 负载均衡:
如果有两个提供者,那么消费者怎么操作的呢?
注意:名称 、端口 不能一样
随机访问策略 、轮询 、
如果一个提供方代码错误的话,那怎么办?
不放在注册中心,那么就出现直连调试模式,在开发测试环境下,可以绕过注册中心,通过xml配置,
那么一定要注册它,怎么办?
也通过xml配置,直接访问提供者,在消费方直接直连,配置路径需要地址
** 三、Zookper注册中心:**
3.1 zookper注册中心和组播注册中心的区别
zookper注册中心: 健康检查、当管理员真的禁用的时候就直接禁用了,主要用在项目开发中
组播注册中心 :如果使用组播注册中心的话需要一定的时间才能消失,不能及时禁用, 主要用在测试中
步骤:
修改注册中心地址 2.3以后需要配置客户端
<dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry>
下载包 依赖完之后
http://mirrors.cnnic.cn/apache/zookeeper/
安装zookper 在里面启动
测试zookper注册中心 :先启动服务提供者,再启动服务消费者
使用注解的话,在消费方调用接口的时候不能使用autowired注入了,而是使用reference
但是可以在其他地方使用autowired注入提供方的试下类需要配置阿里巴巴的service,
不是spring的service了,Spring的service是父类,没有阿里巴巴的service强大,
还需要配置在xml中配置注解配置
3.2 监控中心的作用及特点:
个性化运维:服务的健康情况、服务压力及性能分析、告警通知
扩展接口:com.alibaba.dubbo.monitor.MonitorFactory
com.alibaba.dubbo.monitor.Monitor
** 四、 不同项目区间怎么使用dubbo框架连接?**
如果两个不同的项目 ,就有两个不同的数据库,都有自己的user表,怎么使用在同一个项目中,让一方提供一个接口,
另一方直接调用接口就行
只要是一个实现接口的实现类都要实现序列化接口,因为两个是通过网络传输的,底层是二进制实现的,达到网络传输速度快
4.1 实现步骤:
提供一个api
导dubbo的jar包
配置文件.xml
提供一个api里面提供一个接口,需要配置Pom.xml
让项目方来实现这个接口
不同的工作区间需要打包,直接把这个包给注册中心,到时候到本地仓库里面去找
需要在spring-croe中引入配置文件
启动
五、面试题:
5.1 如何实现Dubbo的本地调试?
先取消连接注册中心,配置服务为直连模式绕过注册中心,从而实现本地调用,直接连接提供方的服务。
当服务调试稳定后,再使用Zookeeper注册中心,并把服务发布出去。
5.2 Dubbo的核心理念是什么?
① 服务定义、② 服务注册、③ 服务监控、④ 远程通信与信息交换、⑤ 服务调用
5.3 Dubbo的注册中心的作用是什么?
对于服务提供方,它需要发布服务,由于应用系统的复杂性,服务的数量、类型也不断膨胀;对于服务消费方,
它最关心如何获取到它所需要的服务,而面对复杂的应用系统,需要管理大量的服务调用。而且,
对于服务提供方和服务消费方来说,他们还有可能兼具这两种角色,既需要提供服务,又需要消费服务。
通过将服务统一管理起来,可以有效地优化内部应用对服务发布/使用的流程和管理。服务注册中心可以通过特定协议
来完成服务对外的统一
5.4 Dubbo监控中心是干嘛的?
监控中心负责为服务的监控运维采集各维度的数据,统计各服务的调用次数、时间等,统计先在服务端和消费端内存中汇总,
每隔一分钟发送到监控中心服务器,并以报表的形式展现。
监控中心是独立于服务和管理控制台的,在整个dubbo服务治理环节不是必须的,用户可根据实际情况选择性安装。
监控中心如果出现异常(宕机),并不会影响提供方和消费方之间的服务调用,会丢失故障期间的监控数据,
再生产环境不会有任何风险。
5.5 谈谈你对Zookeeper的理解?
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,
是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、
分布式同步、组服务等。
ZooKeeper代码版本中,提供了分布式独享锁、选举、队列的接口。
Zookeeper作为Dubbo服务的注册中心,Dubbo原先基于数据库的注册中心,没采用Zookeeper,Zookeeper一个分布式的服务
框架,是树型的目录服务的数据存储,能做到集群管理数据 ,这里能很好的作为Dubbo服务的注册中心,Dubbo能与
Zookeeper做到集群部署,当提供者出现断电等异常停机时,Zookeeper注册中心能自动删除提供者信息,当提供者重启时,能
自动恢复注册数据,以及订阅请求。我们先在windows上安装Zookeeper,我们安装最简单的单点,集群有兴趣的同学可以查找
资料利用虚拟机搭建。