京淘后端商品管理-Day16

1. Zookeeper中的集群说明

1.1 为什么集群一般都是奇数个?

公式: 当前剩余节点数量 > N/2 集群可以正常的使用!!!
分析1:
1台主机能否搭建集群 1-1 > 0.5??? 1台服务器不能搭建集群的
2台服务器 2-1>1??? 2台服务器也不能搭建集群.
3台服务器 3-1>1.5??? 3台服务器是搭建集群的最小单位.
4台服务器 4-1>2 ??? 4台服务器也能搭建集群

分析2: 为什么集群是奇数台,不是偶数台
3台服务器允许宕机的最大的数量是几台? 3个节点最多允许宕机1台服务器.
4台服务器允许宕机的最大的数量是几台? 4个节点最多允许宕机1台服务器.
结论: 搭建偶数台的容灾效果与奇数台相同,所以从成本的角度考虑,搭建奇数台.

1.2 Zookeeper的集群选举原理

问题1:如果是3台zookeeper 将主机宕机之后,集群内部有高可用机制.谁当主机 B

A: 2181 100万 B:2183 对

问题2: 如果再次将现有的主机宕机,问谁是主机? C
A: 2181 B. 剩余其他服务器 C.没有主机!!!(当前集群奔溃)

问题3: 如果依次初始化1-5台服务器. C 1-7
问1.谁是主机?
问2:哪几台服务器不能当主机?

A: 主机是随机的
都可以当主机,看宕机集群是否正常工作.

B: 由启动顺序决定
1-2的服务器不能当主机

C: t第三台当主机.
1-2的服务器不能当主机.

集群选举的原理: zk集群选举时由启动顺序决定.一般采用最大值(myid)优先策略. 投票数超过半数当选主机.

2. Dubbo入门案例

2.1 导入jar包

说明:在父级项目中引入dubbo的jar包文件

<!--引入dubbojar包文件  -->
		<dependency>
			<groupId>com.alibaba.boot</groupId>
			<artifactId>dubbo-spring-boot-starter</artifactId>
			<version>0.2.0</version>
		</dependency>

2.2编辑中立的接口项目interface

1).接口项目创建过程
在这里插入图片描述

2.定义service接口
在这里插入图片描述

2.3定义服务提供者

2.3.1 提供者代码结构

在这里插入图片描述

2.3.2 配置userServiceImpl

在这里插入图片描述

2.3.3 编辑YML配置文件

#关于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  #每一个服务都有自己特定的端口 不能重复.

2.3.4 dubbo通讯原理

在这里插入图片描述

2.4定义服务消费者

2.4.1 消费者代码结构

在这里插入图片描述

2.4.2 编辑消费者Controller

@RestController
public class UserController {
	
	//利用dubbo的方式为接口创建代理对象 利用rpc调用
	
	@Reference     //(loadbalance="leastactive")
	//@Autowired	   //只能注入spring家的对象
	private UserService userService; 
	
	/**
	 * Dubbo框架调用特点:远程RPC调用就像调用自己本地服务一样简单
	 * @return
	 */
	@RequestMapping("/findAll")
	public List<User> findAll(){
		
		//远程调用时传递的对象数据必须序列化.
		return userService.findAll(); //rpc调用
	}
	
	@RequestMapping("/saveUser/{name}/{age}/{sex}")
	public String saveUser(User user) {
		
		userService.saveUser(user);
		return "用户入库成功!!!";
	}
}

2.4.3 编辑消费者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

3. Dubbo 负载均衡策略

3.1 dubbo负载均衡说明

说明:Dubbo框架对外提供了负载均衡的机制.该机制称之为客户端负载均衡. 消费者在发起请求之前.就已经清除的知道将来访问的服务器是谁.

3.2 负载均衡接口说明

在这里插入图片描述

3.3 hash一致性算法

说明:消费者访问绑定了指定的提供者

	//要求所有的字母全部小写
	@Reference(loadbalance="consistenthash")
	private UserService userService; 

3.3 最小访问量

说明: 挑选当前服务器访问压力最小的服务器进行访问

//要求所有的字母全部小写
@Reference(loadbalance="leastactive")
private UserService userService; 

3.4 随机算法

说明:该算法是默认的配置.

	//要求所有的字母全部小写
	@Reference(loadbalance="random")
	private UserService userService; 

3.5 轮询算法

说明:根据配置依次轮询访问.

	//要求所有的字母全部小写
	@Reference(loadbalance="roundrobin")
	private UserService userService; 

4. 京淘项目改造

4.1 改造说明

JT-WEB 应该充当 消费者
JT-MANAGE 应该充当 提供者
JT-SSO 应该充当 提供者

4.2 添加jar包

		<!--引入dubbo配置 -->
		<dependency>
			<groupId>com.alibaba.boot</groupId>
			<artifactId>dubbo-spring-boot-starter</artifactId>
			<version>0.2.0</version>
		</dependency>

4.3 准备中立接口

说明:在jt-common中,添加中立的接口
在这里插入图片描述

4.3 改造JT-SSO 服务提供者

4.3.1 添加DubboUserService实现类

在这里插入图片描述

4.3.2 编辑YML配置文件

server:
  port: 8093
  servlet:
    context-path: /
spring:
  datasource:
    #引入druid数据源
    #type: com.alibaba.druid.pool.DruidDataSource
    #driver-class-name: com.mysql.cj.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

  mvc:
    view:
      prefix: /WEB-INF/views/
      suffix: .jsp
#mybatis-plush配置
mybatis-plus:
  type-aliases-package: com.jt.pojo
  mapper-locations: classpath:/mybatis/mappers/*.xml
  configuration:
    map-underscore-to-camel-case: true

logging:
  level: 
    com.jt.mapper: debug
    
#关于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  #每一个服务都有自己特定的端口 不能重复.    
    

4.4 改造JT-WEB消费者

4.4.1 编辑UserController

说明:在UserController中注入Dubbo接口
在这里插入图片描述

4.4.2 编辑消费者YML配置

	server:
  port: 8092    
spring:     #定义springmvc视图解析器
  mvc:
    view:
      prefix: /WEB-INF/views/
      suffix: .jsp
      
dubbo:
  scan:
    basePackages: com.jt
  application:
    name: consumer-web   #定义消费者名称
  registry:               #注册中心地址
    address: zookeeper://192.168.126.129:2181?backup=192.168.126.129:2182,192.168.126.129:2183

5. 用户注册

5.1 业务需求说明

1).当用户点击注册按钮时,将进行表单数据提交.
2).利用post请求提交 username/password/phone
3).返回值要求: SysResult对象
在这里插入图片描述

5.2 了解页面结构

1).利用F12检查用户的请求路径及提交参数
在这里插入图片描述

2).检查页面JS的参数提交情况.
在这里插入图片描述

5.3 编辑jt-web UserController

	/**
	 * 完成用户注册
	 * 1.url地址:  http://www.jt.com/user/doRegister
	 * 2.参数:         用户名/密码/电话号码
	 * 3.返回值:    SysResult对象
	 */
	@RequestMapping("/doRegister")
	@ResponseBody
	public SysResult doRegister(User user) {
		
		userService.saveUser(user);
		return SysResult.success();
	}

5.4 编辑JT-SSO DubboUserServiceImpl

说明:实现数据入库操作

@Service	//dubbo service注解
public class DubboUserServiceImpl implements DubboUserService {
	
	@Autowired
	private UserMapper userMapper;

	//将数据进行加密处理   email暂时用phone代替
	@Override
	@Transactional	//事务控制
	public void saveUser(User user) {
		
		String password = user.getPassword();  //明码
		password = DigestUtils.md5DigestAsHex(password.getBytes());
		user.setPassword(password).setEmail(user.getPhone())
			.setCreated(new Date()).setUpdated(user.getCreated());
		userMapper.insert(user);
	}
	
}

5.5 关于POJO转化异常

说明:如果dubbo操作过程中,出现了如下的报错,
问题原因: 程序的热部署导致的报错. 导致zk中出现了多条相同的服务信息. 导致负载均衡时不清楚如何挑选.导致报错.
解决方案: 停止服务器,重启即可.
在这里插入图片描述

5.6 注册效果展现

在这里插入图片描述

5.7 关于Dubbo调用流程

1). 检查nginx是否配置正确

#配置前端服务器 www.jt.com:80 转向到http://localhost:8092服务器中
	server {
		listen 80;
		server_name  www.jt.com;

		location / {
			proxy_pass http://localhost:8092;
		}
	}

	#配置前端服务器 sso.jt.com:80 转向到http://localhost:8093服务器中
	server {
		listen 80;
		server_name  sso.jt.com;

		location / {
			proxy_pass http://localhost:8093;
		}
	}

2). 检查hosts文件
在这里插入图片描述
3).检查提供者
检查注解 /YML配置文件./防火墙/IP地址等

4).检查生产者
检查注解/注册中心配置信息等

6 关于单点登录策略说明

6.1 传统登录方式存在问题

说明:由于都端服务都是集群部署.如果用户登录操作采用Session的形式进行保存.则必然导致用户多次登录,才能保证用户的请求不受影响. 该种方式没有办法实现用户信息共享.并且效率低.
在这里插入图片描述

6.2 SSO(单点登录)

单点登录(SingleSignOn,SSO),就是通过用户的一次性鉴别登录。当用户在身份认证服务器上登录一次以后,即可获得访问单点登录系统中其他关联系统和应用软件的权限,同时这种实现是不需要管理员对用户的登录状态或其他信息进行修改的,这意味着在多个应用系统中,用户只需一次登录就可以访问所有相互信任的应用系统。这种方式减少了由登录产生的时间消耗,辅助了用户管理,是目前比较流行的 [1]
重要信息: 身份认证服务器 JT-SSO
核心思想: 1.用户信息共享 2.保证用户信息安全

6.3 SSO单点登录实现原理

在这里插入图片描述
实现步骤:
1.用户通过浏览器输入用户名和密码点击登录按钮开始执行单点登录操作.
2.JT-WEB服务器将用户请求传递给JT-SSO 单点登录服务器 进行数据校验.
3.JT-SSO接收用户名和密码之后,开始校验.如果用户名和密码正确则将user对象转化为JSON字符串.之后动态生成UUID.保存到Redis中. 注意超时时间(7天超时)
4.无论登录是否成功,都应该返回TICKET信息(可以为null)
5.用户通过浏览器提供的COOKIE保存返回的秘钥信息.方便下次访问.


6.当用户执行业务操作时,动态的获取TICKET信息,之后校验.校验通过则放行请求,否则拦截重定向到用户登录页面.

6.4 用户登录具体实现

6.4.1 页面url分析

1).登录页面分析
在这里插入图片描述
2).查看登录页面JS
在这里插入图片描述

6.4.2 编辑UserController(jt-web)

	/**
	 * 15分钟联系    
	 * A. 我清楚的知道我要干什么 ,代码我会写  时间问题    少
	 * B. 我大概了解干什么,思路清楚,代码会写一部分   API不熟
	 * C. 图能看懂 ,只会写controller(部分-全部) service没有思路
	 * D. 图能看懂.但是代码不会写  没思路  不会API.  
	 * 业务需求:实现单点登录
	 * url地址:  /user/doLogin
	 * 参数:     {username:_username,password:_password}
	 * 返回值:    SysResult对象
	 * 
	 * 关于Cookie参数说明:
	 * Cookie特点: Cookie默认条件下,只能在自己的网址下进行展现, 京东的网站,看不到百度的cookie.
	 * Domain: 指定域名可以实现Cookie数据的共享.
	 * Path:(权限设定) 只有在特定的路径下,才能获取Cookie.
	 * 		  网址: www.jd.com/abc/findAll
	 * 		 cookie.setPath("/aa"); 只允许/aa的路径获取该Cookie信息 
	 * 		 cookie.setPath("/");  任意网址,都可以获取Cookie信息.
	 */
	@RequestMapping("/doLogin")
	@ResponseBody	//返回JSON
	public SysResult doLogin(User user,HttpServletResponse response) {
		
		//1.通过user传递用户名和密码,交给业务层service进行校验,获取ticket信息(校验之后的回执)
		String ticket = userService.doLogin(user);
		
		if(StringUtils.isEmpty(ticket)) {
			//证明用户名或密码错误.
			return SysResult.fail();
		}
		
		
		//2.准备Cookie实现数据存储.
		Cookie cookie = new Cookie("JT_TICKET", ticket);
		cookie.setDomain("jt.com");
		cookie.setPath("/");
		cookie.setMaxAge(7*24*60*60); //7天超时
		//将cookie保存到客户端中.
		response.addCookie(cookie);
		
		return SysResult.success();
	}

6.4.3 编辑UserService

	/**
	 * 步骤:
	 * 	1.校验用户信息是否正确
	 *  2.如果正确则利用redis保存到   key/value 
	 *  3.返回用户秘钥
	 */
	@Override
	public String doLogin(User user) {
		
		String password = DigestUtils.md5DigestAsHex(user.getPassword().getBytes());
		user.setPassword(password);
		//查询数据库检查是否正确   根据对象中不为null的属性充当where条件
		QueryWrapper<User> queryWrapper = new QueryWrapper<User>(user);
		User userDB = userMapper.selectOne(queryWrapper);
		
		if(userDB == null) {
			return null;
		}
		
		//用户名和密码正确.  开始单点登录
		String ticket = UUID.randomUUID().toString().replace("-", "");
		//防止涉密信息泄露,则需要进行脱敏处理
		userDB.setPassword("你猜猜,看看能不能猜对!!!!");
		String value = ObjectMapperUtil.toJSON(userDB);
		jedisCluster.setex(ticket, 7*24*3600, value);
		return ticket;
	}

6.5 用户信息回显

6.5.1 业务需求

说明:当用户登录成功之后,需要回显用户信息.
在这里插入图片描述
当用户登录成功之后,F12检查是否发起跨域请求.
在这里插入图片描述
页面JS分析
在这里插入图片描述

6.5.2 编辑JT-SSO的UserController

	/**
	 * 利用jsonp获取用户信息
	 * url:http://sso.jt.com/user/query/826f4938c2a544edb7282139a35ddf56?callback=jsonp1595583195159&_=1595583195203
	 */
	@RequestMapping("/query/{ticket}")
	public JSONPObject findUserByTicket(String callback,@PathVariable String ticket) {
		
		if(jedisCluster.exists(ticket)) {
			//用户之前登录过
			String data = jedisCluster.get(ticket);
			System.out.println(data);
			SysResult sysResult = SysResult.success(data);
			return new JSONPObject(callback, sysResult);
		}else {
			//用户信息有误
			SysResult sysResult = SysResult.fail();
			return new JSONPObject(callback, sysResult);
		}
	}

6.5.3 页面效果展现

数据正确回显

在这里插入图片描述

7作业

1.完成用户登录/注册/回显
2.完成用户退出操作. 要求重定向到系统首页.

猜你喜欢

转载自blog.csdn.net/qq_16804847/article/details/107553975
今日推荐