1 优化JSONP调用
修改页面JS校验:
后端异常后,前端没有报错信息,参数校验一直处于校验过程中,但是页面返回信息正常,因为jsonp返回的结果需要进行特殊的格式处理
需要对全局异常处理机制进行处理
全局异常处理机制的编写
利用参数callBack是否为jsonp跨域请求
@RestControllerAdvice //aop+异常通知 是controller层的一个通知
@Slf4j
public class SystemException {
/**
* 确定该请求是一个跨域的JSONP请求时,才按照指定的格式返回!!! callback(JSON)
* 利用参数callback 判断是否为jsonp跨域, 如何获取???
* */
//当遇到某种类型的异常时才会执行
@ExceptionHandler({RuntimeException.class})
public Object exception(Exception e, HttpServletRequest request, HttpServletResponse response){
log.error(e.getMessage(),e);
e.printStackTrace();
//1.获取callback请求参数
String callback=request.getParameter("callback");
//2.判断是否为jsonP的跨域请求
if(StringUtils.hasLength(callback)){//如果有值则返回callback(JSON)
JSONPObject jsonpObject=new JSONPObject(callback, SysResult.fail());
return jsonpObject;
}
//如果出错,返回系统级别的报错数据即可
return SysResult.fail();
}
测试:
此时页面出现报错信息
跨域请求:浏览器发起的ajax请求违反了同源策略
实现方式: jsonp cors
数据通过F12可以查看,安全性差;而且不能对数据进行二次封装
jsonp 是利用script中的src属性发送请求获得数据,并将数据做特俗的格式封装后实现的调用
HttpClient 远程过程调用 服务A controller----service ------>服务B controller—service----mapper 业务结构繁琐
会被其他框架封装后使用,比如springCloud
直接由service层向后端服务器进行调用
SOA思想 (面向服务的开发模型) 抛开http协议,以最简单的方式进行的关系调用
RPC JSONP,CORS也是一种RPC(但凡调用第三方都是RPC调用)
OSI模型的七层模型:
TCP安全,UDP不安全但是速度快
2 微服务调用思想
2.1传统方式调用的问题说明
2.2微服务思想-注册中心
前端服务器只负责页面的展现,真正耗费性能的是后端服务器
注册中心:1 服务的名称
2 HOST-PORT
…
1 首先是后端服务器启动,自动注册;
2 web服务器连接注册中心将注册信息同步(实时同步)到web服务器,并保存到本地;
3 web服务器检查信息后直接访问服务器,此时若有多台服务器要进行负载均衡(减轻了nginx的压力(以前是nginx实现负载均衡));
4 注册中心里面有心跳检测机制,将注册信息中相应服务器标识为down
微服务:架构设计采用分布式思想,当服务器发生故障时,可以实现自动化故障的迁移,无人为干预
2.3注册中心原理
微服务: 架构设计采用分布式思想,当服务器发生故障时,可以实现自动化的故障迁移.无需人为干预.
注册中心实现原理:
1.当服务器启动时,会将服务器的状态(服务名称/IP/端口) 一起写入注册中心
2.注册中心接收到服务器信息时,会动态的维护服务列表数据.
3/4.当客户端(消费者)启动时,首先会链接注册中心,获取所有的服务列表数据.并且将服务列表数据保存到本地.
5.当消费者执行业务调用时,如果有多个服务的生产者时,采用负载均衡的思想挑选其中的一个服务进行访问(RPC).
6.当服务器发生宕机时,由于注册中心有心跳检测机制,所有会动态的维护服务列表数据.会全网广播通知所有的客户端(消费者)更新服务列表数据. 在更新服务列表时,数据的同步会陷入阻塞的状态.
2.4 关于微服务思想-负载均衡说明
2.4.1集中式负载均衡
说明:所有的请求都必须由某个服务器进行统一管理
nginx是反向代理加上负载均衡 主要作用是反向代理
2.4.2客户端负载均衡
说明:请求发送之前,每个客户端都非常清除知道自己要访问的服务器
常见的注册中心: zookeeper(apache) eureka(springCloud)
1).什么是集中式的负载均衡 (nginx)
特点:
1).用户访问服务器时,自己不清楚访问的真实的服务器到底是谁,由nginx服务器动态的反向代理实现.
2).统一由负载均衡服务器进行负载. 问题 负载均衡服务器访问压力高.
客户端负载均衡
1).消费者在访问服务提供者时清楚的了解 到底应该访问哪台服务器.
2).由于每个客户端都进行负载均衡.相当于将压力均匀的分配给客户端.访问压力低.
核心: 1).nginx一般只负责反向代理
2).在微服务框架中 几乎都是客户端负载均衡服务器.
2.5注册中心zookeeper安装
3 Zookepper介绍
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。
ZooKeeper的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。
ZooKeeper包含一个简单的原语集,提供Java和C的接口。
ZooKeeper代码版本中,提供了分布式独享锁、选举、队列的接口,代码在zookeeper-3.4.3\src\recipes。其中分布锁和队列有Java和C两个版本,选举只有Java版本。
总结:Zookeeper负责服务的协调调度.当客户端发起请求时,返回正确的服务器地址.
1 下载
http://zookeeper.apache.org/releases.html.
下载路径,点击download
下载Zookeeper地址
http://mirrors.hust.edu.cn/apache/zookeeper/
2 zookeeper安装
上传或者下载安装包
解压并改名:
启动成功页面
zookeeper是java编写的程序,所以必须安装jdk
端口占用情况
80 nginx/oracal
8080 tomcat
3306 mysql
8066 mycat
6379 redis
26379 哨兵
2181 zookeeper
3.1Zookeeper集群的搭建
3.1.1关于集群相关思想
1 几台服务器可以搭建集群????
公式:存活节点>N/2(N宕机前节点数量)
算数计算:
1个节点能否搭建集群? 1-1 > 0.5 假 不能搭建集群
2个节点能否搭建集群? 2-1 > 1 假 不能搭建集群
3个节点能否搭建集群? 3-1 > 1.5 真 可以搭建集群
4个节点能否搭建集群> 4-1 > 2 真 可以搭建集群
结论:集群的最小单位是3台
2 集群为什么一般都是奇数台???
分析集群宕机的条件:
3个节点最多允许宕机1台. 奇数
4个节点最多允许宕机1台 偶数
说明: 由于搭建偶数台和搭建奇数台的容灾效果相同的,所以一般都是奇数个.
结论:集群搭建都是奇数台
3 什么是脑裂现象????
由于集群工作过程中,主机意外宕机,集群开始进行选举,如果出现多次连续平票的状态时,可能出现脑裂现象
两个人投票,脑裂现象的概率是 1/8
如何有效降低脑裂现象发生: 增加节点的数量
如何有效降低脑裂现象的发生 增加节点的数量
3.1.2搭建3 台zookeeper集群
关掉单台zookeeper
创建zkCluster文件
创建zk1 zk2 zk3
mkdir zk1 zk2 zk3
mkdir {zk1,zk2,zk3}/{data,log}
vim zk1/data/myid 依次添加为1,2,3
进入zookeeper的conf目录下复制文件
vim zoo1.cfg文件:
启动文件
3.2关于zk集群选举的规范
说明: zk集群选举规则是myid最大值优先的算法,如果选举结束,则剩余的节点当新主机的从机.
考题1: 如果依次启动1-7台zk节点
问1: 谁当主机? 4
问2: 谁永远不能当选主机? 1,2,3
3.3 ZK工作原理说明
Zookeeper集群中leader负责监控集群状态同步数据,follower主要负责客户端链接获取服务列表信息.同时参与投票.
4 Dubbo框架
4.1Dubbo框架介绍
Apache Dubbo |ˈdʌbəʊ| 提供了六大核心能力:面向接口代理的高性能RPC调用,智能容错和负载均衡,服务自动注册和发现,高度可扩展能力,运行期流量调度,可视化的服务治理与运维。
Doubble入门案例
4.2导入jar包
<!--引入dubbo配置 -->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>
4.3导入 入门案例
修改版本
修改module中dubbo
在项目cgb2008_jt_1中右键粘贴
添加为pom项目 右键add as maven project
4.3.1项目的分析
1 先定义中立的接口 interface
接口中没有yml文件
interface接口项目接口:
UserService
2 定义服务的生产者
用TCP协议
接口的实现:
package com.jt.dubbo.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import com.alibaba.dubbo.config.annotation.Service;
import com.jt.dubbo.mapper.UserMapper;
import com.jt.dubbo.pojo.User;
@Service(timeout=3000) //3秒超时 内部实现了rpc
//@org.springframework.stereotype.Service//将对象交给spring容器管理
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public List<User> findAll() {
System.out.println("我是第一个服务的提供者");
return userMapper.selectList(null);
}
@Override
public void saveUser(User user) {
userMapper.insert(user);
}
}
生产者和接口之间是依赖关系
说明:注意注解导入的是dubbo的注解
provider的application.yml
server:
port: 9000 #定义端口
spring:
datasource:
#引入druid数据源
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
username: root
password: root
#关于Dubbo配置
dubbo:
scan:
basePackages: com.jt #指定dubbo的包路径
application: #应用名称
name: provider-user #一个接口对应一个服务名称
registry:
address: zookeeper://192.168.126.129:2181?backup=192.168.126.129:2182,192.168.126.129:2183
protocol: #指定协议
name: dubbo #使用dubbo协议(tcp-ip) web-controller直接调用sso-Service
port: 20880 #每一个服务都有自己特定的端口 不能重复.
mybatis-plus:
type-aliases-package: com.jt.dubbo.pojo #配置别名包路径
mapper-locations: classpath:/mybatis/mappers/*.xml #添加mapper映射文件
configuration:
map-underscore-to-camel-case: true #开启驼峰映射规则
一般一个接口一个实现
tomcat端口9000运行,加载dubbo服务
一般修改两个地方:
3 生产者测试
启动生产者自动生成dubbo ip地址:
4 消费者
package com.jt.dubbo.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.dubbo.config.annotation.Reference;
import com.jt.dubbo.pojo.User;
import com.jt.dubbo.service.UserService;
@RestController
public class UserController {
利用dubbo的方式为接口创建代理对象 利用rpc调用
@Reference(loadbalance="leastactive")
private UserService userService;
/**
* Dubbo框架调用特点:远程RPC调用就像调用自己本地服务一样简单
* @return
*/
@RequestMapping("/findAll")
public List<User> findAll(){
//远程调用时传递的对象数据必须序列化.
return userService.findAll();
}
@RequestMapping("/saveUser/{name}/{age}/{sex}")
public String saveUser(User user) {
userService.saveUser(user);
return "用户入库成功!!!";
}
}
为接口创建动态代理
编辑消费者的yml配置文件
server:
port: 9001
dubbo:
scan:
basePackages: com.jt
application:
name: consumer-user #定义消费者名称
registry: #注册中心地址
address: zookeeper://192.168.126.129:2181?backup=192.168.126.129:2182,192.168.126.129:2183
启动消费者(注意启动顺序,先有生产者再有消费者)
测试: