SOA架构概念
SOA全称为Service-Oriented Architecture,即面向服务的架构。它可以根据需求通过网络对松散耦合的粗粒度应用组件(服务)进行分布式部署、组合和使用。一个服务通常以独立的形式存在于操作系统进程中。
站在功能的角度,把业务逻辑抽象成可复用的服务,通过服务的编排实现业务的快速再生,目的:把原先固有的业务功能转变为通用的业务服务,实现业务逻辑的快速复用。
Dubbo概念
简单来讲**:Dubbo就是用于连接各个项目(如WEB层项目对Service层项目)之间的桥梁*,这个桥梁的原理是通过web来传递请求,且该桥梁有很多种工具可以替代,我们这里就选择了Dubbo
服务注册中心Zookeeper
概念
Zookeeper用于注册服务,Dubbo官方推荐使用Zookeeper作为服务注册中心。
简而言之,Dubbo依赖于Zookeper,所以在使用SOA架构开发时,必须要用到Zookeeper.
下载Zookeeper
官方下载地址:http://archive.apache.org/dist/zookeeper/
自己用的(版本为3.4.6):https://pan.baidu.com/s/1lNa01kEn37dOsWa6E_5qjA
提取码: 62qi
方式一:在centods系统运行
第一步:安装 jdk(略)
第二步:把 zookeeper 的压缩包(zookeeper-3.4.6.tar.gz)上传到 linux 系统
第三步:解压缩压缩包
tar -zxvf zookeeper-3.4.6.tar.gz
第四步:进入zookeeper-3.4.6目录,创建data目录
mkdir data
第五步:进入conf目录 ,把zoo_sample.cfg 改名为zoo.cfg
cd conf
mv zoo_sample.cfg zoo.cfg
第六步:打开zoo.cfg文件, 修改data属性:dataDir=/root/zookeeper-3.4.6/data
第七步:进入Zookeeper的bin目录,
启动服务命令
./zkServer.sh start
停止服务命令
./zkServer.sh stop
查看服务状态:
./zkServer.sh status
方式二:在windows系统运行
参考ttps://www.cnblogs.com/zlslch/p/8561791.htm
Dubbo应用(快速入门)
注意:AOP架构可以应用于DAO层,SERVICE层等等,而我们这次仅仅用web层到service的数据传输做举例.所以步骤内容并非是绝对的,只能当作参考,重在了解思想.
步骤一:创建注册服务提供方工程(后端)
步骤一:创建maven工程,并导入pom坐标
pom坐标固定内容如下:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring.version>5.0.5.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- dubbo相关 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.0</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.7</version>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.12.1.GA</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<!-- 指定端口 -->
<port>8081</port>
<!-- 请求路径 -->
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
步骤二:配置web.xml文件
固定格式:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<!-- 此处为匹配本项目Dubbo的配置文件 -->
<param-value>classpath:applicationContext*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
步骤三:创建服务接口,并定义应用方法
格式:
public interface 自定义接口名 {
public 自定义返回值类型 自定义方法名(参数列表);
}
列如:
public interface HelloService {
public String sayHello(String name);
}
步骤四:创建服务实现类
注意,此处要声明Service注解,但这个Service注解是dubbo的,而非是Spring的
.
他们的功能都是用于声明切入点,但底层原理不同.
格式:
@Service
public class 自定义实现类名 implements 自定义接口名 {
public 自定义返回值类型 自定义方法名(参数列表){
//业务代码
retrun 返回数据;
}
}
列如:
package cn.dubbo.service.impl;
import cn.dubbo.service.ServiceProvider;
import com.alibaba.dubbo.config.annotation.Service;
@Service //注意:此处的Service注解并非是Srping的,而是dubbo的注解 import com.alibaba.dubbo.config.annotation.Service;
public class ServiceProviderImpl implements ServiceProvider {
@Override
public String sayHell(String name) {
return "你好~ Hello";
}
}
步骤五:创建Dubbo配置文件
在src/main/resources下创建applicationContext-service.xml (非固定文件名,如果你的后端是用于dao的,那可以是applicationContext-dao.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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 当前应用名称,用于注册中心计算应用间依赖关系,注意:消费者和提供者应用名不要一样 -->
<dubbo:application name="dubbodemo_provider" />
<!-- 连接服务注册中心zookeeper ip为zookeeper所在服务器的ip地址-->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!-- 注册 协议和port 端口默认是20880 -->
<dubbo:protocol name="dubbo" port="20881"></dubbo:protocol>
<!-- 扫描指定包,加入@Service注解的类会被发布为服务 注意:该直接包路径下必须存在Service实现类.而不能是间接包路径存在实现类 -->
<dubbo:annotation package="cn.dubbo.service.impl" />
</beans>
步骤二:创建注册服务消费方工程(前端)
步骤一:创建Maven工程,并导入pom坐标
导入的pom坐标跟"注册服务提供方"的pom坐标一摸一样,因此省略.
只是,假如你的注册服务提供方和注册服务消费方在同一个服务器部署的话,那么该处的tomcat端口不能跟注册服务提供方的tomcat端口冲突.
步骤二:配置web.xml文件
固定格式:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 指定加载的配置文件 ,通过参数contextConfigLocation加载 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<!-- 此处为匹配本项目Dubbo的配置文件 -->
<param-value>classpath:applicationContext-web.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
步骤三:将提供者中的接口复制到消费者
这么做的主要目的,就是让消费者能够通过Duddo耦合到提供者里头的接口,来达到调用的目的.
步骤四:编写Controller(WEB)
注意:我们既然要调用接口进而简介调用到提供者的接口方法,那么就需要定义一个切面来引入这个接口.
这里我们使用Reference注解来替代Autowired注解,且Reference的注解是dubbo的
格式:
@Controller
public class 自定义类名 {
@Reference//与以往不同的是,这次引用切入面是使用dubbo的Reference注解 import com.alibaba.dubbo.config.annotation.Reference;
private 自定义接口名 自定义接口成员对象;
@RequestMapping("/虚拟路径")
@ResponseBody
public 自定义返回值类型 getName(参数列表){
//远程调用消费者之方法体
return 返回数据;
}
}
列如:
package cn.dubbo.controller;
import cn.dubbo.service.ServiceProvider;
import com.alibaba.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller//定义为web页面类
@RequestMapping("/test")
public class ControllerWeb {
@Reference //与以往不同的是,这次引用切入面是使用dubbo的Reference注解 import com.alibaba.dubbo.config.annotation.Reference;
private ServiceProvider serviceObj;
@RequestMapping("/hello")
@ResponseBody
public String getName(String name){
//通过Dubbo远程调用服务注册提供者的方法
String result = serviceObj.sayHell(name);
System.out.println(result);
return result;
}
}
步骤五:创建Dubbo配置文件
在src/main/resources下创建applicationContext-web.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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 当前应用名称,用于注册中心计算应用间依赖关系,注意:消费者和提供者应用名不要一样 -->
<dubbo:application name="dubbodemo-consumer" />
<!-- 连接服务注册中心zookeeper ip为zookeeper所在服务器的ip地址-->
<dubbo:registry address="zookeeper://192.168.134.129:2181"/>
<!-- 扫描的方式暴露接口 -->
<dubbo:annotation package="com.itheima.controller" />
</beans>
步骤三:运行
必须要先运行提供者,才能再运行消费者
注意:我们消费者作为前端,我们自然而然要在浏览器访问消费者
Dubbo扩展:优化接口调用
目的
上面的Dubbo入门案例中我们是将HelloService接口从服务提供者工程(dubbodemo_provider)复制到服务消费者工程(dubbodemo_consumer)中,这种做法是否合适?还有没有更好的方式?
方案
这种做法显然是不好的,同一个接口被复制了两份,不利于后期维护。更好的方式是单独创建一个maven工程,将此接口创建在这个maven工程中。需要依赖此接口的工程只需要在自己工程的pom.xml文件中引入maven坐标即可。
即:创建一个专门存放接口的Maven工程.消费者和提供者都引用该工程里头的接口
Dubbo问题解决:事务管理(待补充)
阐述
前面我们已经完成了Dubbo的入门案例,通过入门案例我们可以看到通过Dubbo提供的标签配置就可以进行包扫描,扫描到@Service注解的类就可以被发布为服务。
但是我们如果在服务提供者类上加入@Transactional事务控制注解后,服务就发布不成功了。原因是事务控制的底层原理是为服务提供者类创建代理对象,而默认情况下Spring是基于JDK动态代理方式创建代理对象,而此代理对象的完整类名为com.sun.proxy.$Proxy42(最后两位数字不是固定的),导致Dubbo在发布服务前进行包匹配时无法完成匹配,进而没有进行服务的发布。
解决
步骤一:修改提供者配置文件
配置数据源,事务管理器,声明事务注解支持,并在注解支持声明处添加’proxy-target-class’属性,将值改为true.
意思是改为使用cglib代理方式为Service类创建代理对象
注意:数据源的连接信息一定要配置正确
模板:
<!--数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="username" value="root" />
<property name="password" value="root" />
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/test" />
</bean>
<!-- 事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--开启事务控制的注解支持-->
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
步骤二:修改提供者的实现类
在提供者的实现类里头,给Service标签指定protocol,interfaceClass这两个属性和对应值.
其中,protocol属性可省略,但如果不省略,则值必须为’dubbo’.
格式:
@Service(protocol = "dubbo",interfaceClass = 该实现类的接口名.class)
列如
@Service(protocol = "dubbo",interfaceClass = ServiceProvider.class)
工具:Dubbo管理控制台
我们在开发时,需要知道Zookeeper注册中心都注册了哪些服务,有哪些消费者来消费这些服务。我们可以通过部署一个管理中心来实现。其实管理中心就是一个web应用,部署到tomcat即可。
5.1 安装
安装步骤:
(1)将资料中的dubbo-admin-2.6.0.war文件复制到tomcat的webapps目录下
(2)启动tomcat,此war文件会自动解压
(3)修改WEB-INF下的dubbo.properties文件,注意dubbo.registry.address对应的值需要对应当前使用的Zookeeper的ip地址和端口号
dubbo.registry.address=zookeeper://192.168.134.129:2181
dubbo.admin.root.password=root
dubbo.admin.guest.password=guest
(4)重启tomcat
5.2 使用
操作步骤:
一.访问http://localhost:8080/dubbo-admin-2.6.0/,输入用户名(root)和密码(root)
二.设置页面为中文
三.启动服务提供者工程和服务消费者工程,可以在查看到对应的信息