传统的系统架构模式
因为传统应用架构有很多的不足:
1.基本上所有的项目都会使用同一个代码库。这样造成 内容过多,效率变得低下。
2.如果采用多模块开发,相互依赖,如果产品上线了,发布的是很大的工作量。
3.单系统的架构,采用了三层架构来区分,但在实际中可能出现改动而带来的同步变动,失去了分层的独立性。
4.当业务变大,一个系统可能会被查分成多个子系统,业务之间存在的关联。这时就要解决基础服务公用的问题。
5.运营团队遇到重大危机,不能解决。
微服务
是将产品或项目分解为独立的服务,这些服务独立地部署,并且不依赖于其他的服务。
微服务的优势:
1.单系统只有一种开发语言,但是微服务每个服务独立,因此每个服务可以选择最合适的服务技术开发。
2.一个服务代码和业务都不大,开发人员能很好的把握代码。
3.服务间进行调用时,可以通过API来进行通讯,如REST(HTTP),也可以使用分布式服务管理框架如Dubbo(rpc) 、SpringCloud(HTTP)等。
微服务的不足:
因为每个功能是独立的,所以管理每个功能就很复杂。建立统一的日志管理系统来解决。
系统应用架构
单一应用架构
当网站流量很小时,只需一个应用,将所有功能都部署在一起。
用于简化增删改查工作量的 数据访问框架(ORM) 。
垂直应用架构
当访问量逐渐增大,将应用拆成互不相干的几个应用,以提升效率。
用于加速前端页面开发的 Web框架(MVC)/三层架构。
分布式服务架构
当垂直应用越来越多,将核心业务抽取出来,作为独立的服务。
用于提高业务复用及整合的 分布式服务框架(RPC) 是关键
流动计算架构
服务越来越多,根据访问的行为来调度管理,提高集群利用率。
用于提高机器利用率的 资源调度和治理中心(SOA)。
Dubbo
dubbo是一个分布式服务治理框架,致力于提供高性能和透明化的RPC远程服务调用方案,可以和 Spring框架无缝集成。
dubbo框架设计一共划分了10个层:
服务接口层(Service)、配置层(Config)、服务代理层(Proxy)、服务注册层(Registry)、集群层(Cluster)、监控层(Monitor)、远程调用层(Protocol)、信息交换层(Exchange)、网络传输层(Transport)和数据序列化层(Serialize)。
dubbo核心:
Provider: 暴露服务的服务提供方。
Consumer: 调用远程服务的服务消费方。
Registry: 服务注册与发现的注册中心。
Monitor: 统计服务的调用次调和调用时间的监控中心。
Container: 服务运行容器。
调用关系说明:
服务容器负责启动,加载,运行服务提供者。
- 服务提供者在启动时,向注册中心注册自己提供的服务。
- 服务消费者在启动时,向注册中心订阅自己所需的服务。
- 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
- 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
- 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
dubbo的获取
http://central.maven.org/maven2/com/alibaba/dubbo
<project>
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
</dependencies>
</project>
Dubbo本地服务化
导入dubbo,zookeeper客户端jar包
<!--dubbo包-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</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>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>
创建公共项目工程:普通的Maven工程,提供utils、DO、接口的代码。
pom.xml 无任何依赖
package cn.itsource.dao;
public interface DemoService {
String sayHello(String name);
}
提供者
配置prover.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">
<!-- 提供方应用信息,用于计算依赖关系 -->
<dubbo:application name="dobbo-order" />
<!-- 使用multicast广播注册中心暴露服务地址 -->
<!-- <dubbo:registry address="multicast://224.5.6.7:12341" />-->
<dubbo:registry address="zookeeper://localhost:2181" client="zkclient" />
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880" />
<!-- 声明需要暴露的服务接口
<dubbo:service interface="cn.itsource.dao.DemoService" ref="demoService" />
<!– 和本地bean一样实现服务 –>
<bean id="demoService" class="cn.itsource.dao.impl.DemoServiceImpl" />-->
<dubbo:annotation package="cn.itsource"/>
</beans>
在实现类上打注解
@Service
public class DemoServiceImpl implements DemoService {
public String sayHello(String name) {
return "Hello " + name;
}
}
启动提供则服务
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:provider.xml")
public class Provider {
@Test
public void test() throws Exception{
System.in.read(); // 按任意键退出
}
}
在消费者
配置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">
<!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
<dubbo:application name="consumer-of-helloworld-app" />
<!-- 使用multicast广播注册中心暴露发现服务地址 -->
<!--<dubbo:registry address="multicast://224.5.6.7:12341" />-->
<dubbo:registry address="zookeeper://localhost:2181" client="zkclient" />
<!-- 生成远程服务代理,可以和本地bean一样使用demoService
<dubbo:reference id="demoService" interface="cn.itsource.dao.DemoService" />-->
<dubbo:annotation package="cn.itsource"/>
</beans>
@refence 导入提供者提供的服务接口
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:consumer.xml")
public class Consumer {
@Reference
DemoService demoService;
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); // 显示调用结果
}
@Test
public void name() throws Exception {
String name = demoService.sayHello("哈哈哈");
System.out.println(name);
}
}
配置注册中心
Zookeeper是一个分布式的服务框架,是树型的目录服务的数据存储,能做到集群管理数据 ,这里能很好的作为Dubbo服务的注册中心,Dubbo能与Zookeeper做到集群部署,当提供者出现断电等异常停机时,Zookeeper注册中心能自动删除提供者信息,当提供者重启时,能自动恢复注册数据,以及订阅请求。我们先在windows上安装Zookeeper,我们安装最简单的单点,集群环境需要有兴趣的同学主动查找资料并利用虚拟机搭建
下载地址:http://dubbo.apache.org/zh-cn/blog/download.html
出现了
打开这个jar包,编辑dubbo-admin.xml
在cmd中运行
java -jar dubbo-admin-0.0.1-SNAPSHOT.jar
Dubbo 管控台可以对注册到 zookeeper 注册中心的服务或服务消费者进行管理,但 管控台是否正常对 Dubbo 服务没有影响,管控台也不需要高可用,因此可以单节点部署。
控制台主要包含: 提供者、 路由 规则 、 动态配置、 访问控制、 权重调节、 负载均衡、 负责人等管理功能,dubbo admin默认使用消息注册中心类型为:zookeeper。
安装zookeeper
下载地址:http://mirrors.cnnic.cn/apache/zookeeper/
下载好了之后解压。
在conf文件里面,要有
zoo.cfg.
配置
# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
dataDir=/tmp/zookeeper
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
最后在启动服务,在bin文件那里有个zkServer.cmd点击运行
Dubbo服务打包
1、使用Servlet容器(不用)
利用Tomcat、Jetty等WEB容器启动Dubbo服务。
缺点:增加管理配置的复杂性,不必要地使用http端口,浪费内存资源
2、Java的Main方法(不建议,本地调试可以用)
基于Spring框架,写一个Java类并提供Main方法启动。
缺点:无法使用Dubbo的一些高级特性,服务的管理需要自己额外提供实现
3、Dubbo框架Main方法
Dubbo框架本身提供了服务运行支持方法,基于com.alibaba.dubbo.container.Main
简单高效地运行服务
很好地支持Dubbo服务的发布、关停(ShutdownHook)
maven编译打包
<groupId>cn.itsource.service</groupId>
<artifactId>service-user</artifactId>
<version>${service-user.version}</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<!-- 打包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>applicationContext.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>
<dependencies>
</dependencies>
p2p集成dubbo功能并提供了服务注册接口
准备一个p2p项目。
配置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">
<!-- 提供方应用信息,用于计算依赖关系 -->
<dubbo:application name="ELoan-UIWeb" />
<!-- 使用multicast组播广播注册中心暴露服务地址 测试-->
<dubbo:registry address="zookeeper://localhost:2181" client="zkclient"/>
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20883" />
<!-- 声明需要暴露的服务接口
<dubbo:service interface="cn.itsource.dao.DemoService" ref="demoService" />-->
<!-- 和本地bean一样实现服务
<bean id="demoService" class="cn.itsource.dao.impl.DemoServiceImpl" /> -->
<!--注解配置-->
<dubbo:annotation package= "cn.itsource" />
<!-- 直连监控中心服务器地址,如:address="192.168.3.71:7070" -->
<dubbo:monitor protocol="registry"/>
</beans>
在spring-core.xml配置引入provider.xml
<import resource="provider.xml" />
注意:关联部分
<dependency>
<groupId>p2p-api</groupId>
<artifactId>p2p-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
因为一个项目中调用另外一个项目的接口。
Dubbo监控中心
监控中心是独立于服务和管理控制台的,在整个dubbo服务治理环节不是必须的,用户可根据实际情况选择性安装。
监控中心如果出现异常(宕机),并不会影响Provider和Consumer之间的服务调用,但会丢失故障期间的监控数据,再生产环境不会有任何风险。
SimpleMonitor是官方提供的一个基本功能版本的监控中心,本质上监控中心也是一个标准的dubbo服务。SimpleMonitor采用磁盘存储统计信息,请注意安装机器的磁盘限制,如果要集群,建议用mount共享磁盘,结合Dubbo管理
下载解压:
conf下面的dubbo.properties
dubbo.container=log4j,spring,registry,jetty
dubbo.application.name=simple-monitor
dubbo.application.owner=dubbo
#dubbo.registry.address=multicast://224.5.6.7:1234
dubbo.registry.address=zookeeper://127.0.0.1:2181
#dubbo.registry.address=redis://127.0.0.1:6379
#dubbo.registry.address=dubbo://127.0.0.1:9090
dubbo.protocol.port=7070
dubbo.jetty.port=7002
dubbo.jetty.directory=${user.home}/monitor
dubbo.charts.directory=${user.home}/monitor/charts
dubbo.statistics.directory=${user.home}/monitor/statistics
dubbo.log4j.file=logs/dubbo-monitor-simple.log
dubbo.log4j.level=WARN
启动在assembly.bin下面的start.bat
监控中心访问地址:http://localhost:7001