1.1软件架构
(1)单一应用架构
当网站流量很小时 ,应用规模小时,只需要一个应用,见所有功能都部署在一起,以减少部署服务器数量和成本,此时,用于简化增删改查工作量的数据框架orm是关键。数据库的处理时间影响时间性能。
这种结构的应用适合小型系统,小型网站,或者企业内部系统,用户较少,请求量不大,对请求的处理时间没有太高的要求,将所有功能都部署到一个服务器,简单易用。开发项目难度低。
缺点:
1.性能扩张比较困难。
2.不利于多人同时开发。
3.不利于升级维护
4.整个系统的空间占用比较大
(2)分布式服务框架
当应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求,此时,用于提高业务复用及整合的分布式服务框架(RPC)是关键 分布式系统将服务作为独立的应用,实现服务共享和重用。
1.2分布式系统
1.2.1什么是分布式系统
分布式系统是若干独立计算机(服务器)的集合,这些计算机对于用户来说就像单个相关系统,分布式系统(distributed system)是建立在网络之上的服务器端的一种结构
1.2.2 rpc是什么?
rpc 是指远程过程调用,是一种进程间通信方式,是一种技术思想 而不是规范。它允许程序调用另一个地址空间(网络上的另一台机器上)的过程,而不用开发人员显示编码的调用细节,调用本地方法和调用远程方法一样。
RPC的实现方式可以不同。例如java的rmi,spring远程调用。
RPC特点:
1.简单:使用简单,建立分布式应用更容易
2.高效:调用过程清晰 效率高
3.通用:进程间通讯方式,有通用的规则
rpc通讯时基于tcp或udp协议
序列化方式(xml/json/二进制)
第二章 dubbo框架
2.1dubbo概述
dubbo是一款高性能,轻量级的开源java rpc框架
dubbo是一个分布式服务框架,致力于提供高性能和透明化的PRC远程服务调用方案,服务治理方案。
官网:http://dubbo.apache.org/zh-cn/
面向接口代理:调用接口方法,在A服务器调用B服务器的方法,有dubbo实现对B的调用,无需关心实现细节,就像MyBatis访问Dao接口,可以操作数据库一样,不用关心dao接口方法的实现
2.2 基本框架
服务提供者 :暴露服务的服务提供方,服务提供者在启动时,向注册中心注册自己提供的服务。
服务消费者:调用远程服务的服务消费方,服务消费者在启动时,向注册中心订阅自己所需的服务,服务消费者。从提供者地址列表中,基于软负载均衡算法 选一台提供者进行调用,如果调用失败 在选另一台调用。
注册中心:注册中心返回服务提供者地址列表给消费者。如果有变更,注册中心将基于长连接推送变更数据给消费者
监控中心:服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
调用关系说明:
服务容器负责启动,加载,运行服务提供者
服务提供者在启动时,想注册中心注册自己提供的服务
服务消费者在启动时,想注册中心订阅自己所需要的服务
注册中心返回服务提供者列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果失败,在选另一台调用。
服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送ICi统计数据在监控中心上。
2.3dubbo支持的协议
支持多协议:dubbo,http,rmi,redis,dubbo协议等
dubbo官方支持推荐dubbo协议。dubbo协议默认端口号 20880
使用dubbo协议,spring配置文件加入:
<dubbo:protocol name="dubbo" port="20880'>
2.4 直连方式
点对点的直连项目:消费者直接访问服务提供者,没有注册中心。消费者必须指定服务提供者的访问url
消费者直接通过url地址访问固定的服务提供者,这个url地址时不变的
dubbo直连的方式见 dubbo直连
2.5 dubbo服务化最佳实践
2.5.1分包
建议将服务接口,服务模型,服务异常等均放在公共包中
2.5.2 粒度
服务接口尽可能大粒度,每个服务方法应代表一个功能,而不是某功能的一个步骤,
否则将面临分布式事务问题,Dubbo暂未提供分布式事务支持。
服务接口将以以业务场景为单位划分,并对相近业务做抽象,防止接口数量爆炸。
不建议使用过于抽象的通用接口,如Map query(Map) 不好维护
2.5.3版本
每个接口都应定义版本号,为后续不兼容升级提供可能,如:
<dubbo:service interface=“com.xxx.XxxService" version="1.0">
建议使用两位版本号,要变更服务版本,先升级一般提供者为新版本,在将消费者全部升为新版本,然后将剩下一半提供者升为新版本。
link-interface是一个maven java工程 dubbo官方推荐使用的一个模式 将实体bean和业务接口存放到接口工程中
直连演示
1.创建一个java工程 (编写实体类【要序列化】和接口)
package com.bjpowernode.dubbo.model; import java.io.Serializable; public class User implements Serializable { private Integer id; private String username; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + '}'; } }
package com.bjpowernode.dubbo.service; import com.bjpowernode.dubbo.model.User; public interface UserService { User queryUserById(Integer id); Integer queryAllUserCount(); }
2. 创建一个maven web工程 :服务的提供者 link-userservice-provider
2.1修改pom文件 添加spring依赖 和Dubbo依赖 和接口工程依赖 jdk编译级别
<?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.bjpowernode</groupId> <artifactId>004-link-userservice-provider</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <dependencies> <!--spring依赖--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.16.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.3.16.RELEASE</version> </dependency> <!--dubbo依赖--> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.6.2</version> </dependency> <!--接口工程--> <dependency> <groupId>com.bjpowernode</groupId> <artifactId>003-link-interface</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
2.2实现服务接口:UserServiceImpl
package com.bjpowernode.dubbo.service.impl; import com.bjpowernode.dubbo.model.User; import com.bjpowernode.dubbo.service.UserService; public class UserServiceImpl implements UserService { @Override public User queryUserById(Integer id) { User user=new User(); user.setId(id); user.setUsername("张三") return user; } @Override public Integer queryAllUserCount() { return 52; } }
2.3配置dubbo服务提供者的核心配置文件 dubbo-userservice-provider.xml
a.声明dubbo服务提供者的名称:保证唯一
b.声明dubbo使用的协议和端口号
c.暴露服务,使用直连方式
d.加载业务接口的实现类到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.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"> <!--声明dubbo服务提供者的名称:保证唯一性--> <dubbo:application name="004-link-userservice-provider"/> <!--设置dubbo使用的协议端口号 name:dubbo使用的协议名称 port:dubbo服务的端口号 --> <dubbo:protocol name="dubbo" port="20880"></dubbo:protocol> <!--暴露服务接口--> <dubbo:service interface="com.bjpowernode.dubbo.service.UserService" ref="userService" registry="N/A"></dubbo:service> <!--加载业务接口的实现类到spring容器中--> <bean id="userService" class="com.bjpowernode.dubbo.service.impl.UserServiceImpl"></bean> </beans>
2.4 添加监听器,加载配置文件
<?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_4_0.xsd" version="4.0"> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:dubbo-userservice-provider.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app>
3.创建一个maven web工程:服务消费者 link-consumer
3.1配置pom文件:添加需要的依赖(spring,dubbo,接口工程)jdk编译级别
<?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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <packaging>war</packaging> <name>005-link-consumer</name> <groupId>com.bjpowernode</groupId> <artifactId>005-link-consumer</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <!--spring依赖--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.16.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.3.16.RELEASE</version> </dependency> <!--dubbo依赖--> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.6.2</version> </dependency> <!--接口工程--> <dependency> <groupId>com.bjpowernode</groupId> <artifactId>003-link-interface</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
3.2 设置dubbo的核心文件(dubbo-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.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"> <!--声明服务消费者名称--> <dubbo:application name="005-link-consumer"></dubbo:application> <!--引用远程接口服务--> <dubbo:reference id="userService" interface="com.bjpowernode.dubbo.service.UserService" url="dubbo://localhost:20880" registry="N/A" ></dubbo:reference> </beans>
applicationContext.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: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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!--扫描组件--> <context:component-scan base-package="com.bjpowernode.dubbo.web"></context:component-scan> <!--配置注解驱动--> <mvc:annotation-driven></mvc:annotation-driven> <!--视图解析器--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/"/> <property name="suffix" value=".jsp"/> </bean> </beans>
3.3编写controller
package com.bjpowernode.dubbo.web.controller; import com.bjpowernode.dubbo.model.User; import com.bjpowernode.dubbo.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class UserController { @Autowired private UserService userService; @RequestMapping("/userDetail") public String userDetail(Model model,Integer id){ //根据用户标识获取用户详情 User user = userService.queryUserById(id); //获取用户总人数 Integer count = userService.queryAllUserCount(); model.addAttribute("user",user); model.addAttribute("count",count); return "userDetail"; } }
3.4 配置中央调度器(就是一个servlet:DispatcherServlet)
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <!--中央调度器--> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml,classpath:dubbo-consumer.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
3.5 jsp页面 user Detail.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>用户详情</title> </head> <body> <h3>用户详情</h3> <div>用户标识:${user.id}</div> <div>用户姓名:${user.username}</div> <div>用户总人数:${count}</div> </body> </html>