1. Dubbo
1.1 Dubbo介绍
Apache Dubbo |ˈdʌbəʊ| 是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。
1.2 Dubbo特点
2 Dubbo入门案例
2.1 定义公共接口项目
说明:接口项目一般定义公共的部分,并且被第三方依赖.
2.2 服务提供者介绍
2.2.1 提供者代码结构
2.2.2 编辑实现类
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)
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
);
}
}
2.2.3 编辑提供者配置文件
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的包路径 扫描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
2.3 服务消费者介绍
2.3.1 编辑Controller
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 {
@Reference
private UserService userService
;
@RequestMapping("/findAll")
public List
<User> findAll(){
return userService
.findAll();
}
@RequestMapping("/saveUser/{name}/{age}/{sex}")
public String
saveUser(User user
) {
userService
.saveUser(user
);
return "用户入库成功!!!";
}
}
2.3.2 编辑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
2.3.3 Dubbo入门案例测试
2.4 关于Dubbo框架知识点
2.4.1 问题1:如果其中一个服务器宕机 用户访问是否受限?
答:由于zk的帮助,使得程序永远可以访问正确的服务器.并且当服务重启时,duboo有服务的自动发现功能,消费者不需要重启即可以访问新的服务.
2.4.2 问题2:如果ZK集群短时间宕机,用户访问是否受限?
答: 用户的访问不受影响,由于消费者在本地存储服务列表信息,当访问故障机时,自动的将标识信息改为down属性.
2.5 Dubbo负载均衡策略
2.5.1 负载均衡种类
1.客户端负载均衡 Dubbo/SpringCloud等微服务框架 2.服务端负载均衡 说明:客户端发起请求之后,必须由统一的服务器进行负载均衡,所有的压力都在服务器中. NGINX
2.5.2 Dubbo负载均衡方式
@RestController
public class UserController {
@Reference(loadbalance
= "leastactive")
private UserService userService
;
}
3 京淘项目Dubbo改造
3.1 改造JT-SSO
3.1.1 添加jar包文件
<!--引入dubbo配置
-->
<dependency>
<groupId>com
.alibaba
.boot
</groupId
>
<artifactId>dubbo
-spring
-boot
-starter
</artifactId
>
<version>0.2.0</version
>
</dependency
>
3.1.2 创建DubboUserService接口
3.1.3 创建提供者实现类
3.1.4 编辑提供者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
3.1.5 启动服务提供者
测试Dubbo服务器启动是否正常.
3.2 改造服务消费者JT-WEB
3.2.1 注入Service接口
3.2.2 编辑消费者配置文件
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
3.2.3 启动效果测试
4.用户模块实现
4.1 用戶注册
4.1.1 URL分析
根据url地址说明请求为同域请求. 参数信息:
4.1.2 页面JS分析
说明:根据分析获取返回值数据信息应该为SysResult对象
4.1.3 编辑UserController
@RequestMapping("/doRegister")
@ResponseBody
public SysResult
saveUser(User user
){
userService
.saveUser(user
);
return SysResult
.success();
}
4.1.4 编辑UserService
@Override
public void saveUser(User user
) {
String md5Pass
=
DigestUtils
.md5DigestAsHex(user
.getPassword().getBytes());
user
.setEmail(user
.getPhone())
.setPassword(md5Pass
);
userMapper
.insert(user
);
}
4.1.5 页面效果展现
4.2 关于ZK数据存储结构
说明:在zk中数据的存储采用树形结构的方式保存 命令: [root@localhost bin]# sh zkCli.sh 查询命令: ls /…
4.3 用户单点登录原理介绍
4.3.1 传统方式登录存在的问题
说明: 如果采用SESSION的方式实现用户的登录操作,由于nginx负载均衡的策略,用户可以访问不同的服务器.但是Session不能共享,所以导致用户频繁的登录. 用户的体验不好.
4.3.2 SSO
单点登录(SingleSignOn,SSO),就是通过用户的一次性鉴别登录。当用户在身份认证服务器上登录一次以后,即可获得访问单点登录系统中其他关联系统和应用软件的权限,同时这种实现是不需要管理员对用户的登录状态或其他信息进行修改的,这意味着在多个应用系统中,**用户只需一次登录就可以访问所有相互信任的应用系统。**这种方式减少了由登录产生的时间消耗,辅助了用户管理,是目前比较流行的 [1]
4.3.3 京淘项目单点登录设计
实现步骤: 1.当用户输入用户名和密码点击登录时,将请求发送给JT-WEB消费者服务器. 2.JT-WEB服务器将用户信息传递给JT-SSO单点登录系统完成数据校验. 3.如果登录成功,则动态生成密钥信息,将user数据转化为json.保存到redis中. 注意超时时间的设定. 4.JT-SSO将登录的凭证 传给JT-WEB服务器. 5.JT-WEB服务器将用户密钥TICKET信息保存到用户的cookie中 注意超时时间设定. 6.如果登录不成功,则直接返回错误信息即可.
4.4 用户单点登录实现
4.4.1 页面url分析
4.4.2 页面参数分析
4.4.3 页面JS分析
4.4.4 编辑UserController
@RequestMapping("/doLogin")
@ResponseBody
public SysResult
doLogin(User user
, HttpServletResponse response
){
String ticket
= userService
.doLogin(user
);
if(StringUtils
.isEmpty(ticket
)){
return SysResult
.fail();
}else{
Cookie cookie
= new Cookie("JT_TICKET",ticket
);
cookie
.setMaxAge(7*24*60*60);
cookie
.setPath("/");
cookie
.setDomain("jt.com");
response
.addCookie(cookie
);
return SysResult
.success();
}
}
4.4.5 编辑UserService
@Override
public String
doLogin(User user
) {
String md5Pass
=
DigestUtils
.md5DigestAsHex(user
.getPassword().getBytes());
user
.setPassword(md5Pass
);
QueryWrapper
<User> queryWrapper
= new QueryWrapper<>(user
);
User userDB
= userMapper
.selectOne(queryWrapper
);
if(userDB
== null
){
return null
;
}else{
String ticket
= UUID
.randomUUID().toString();
userDB
.setPassword("123456你信不??");
String userJSON
= ObjectMapperUtil
.toJSON(userDB
);
jedisCluster
.setex(ticket
, 7*24*60*60, userJSON
);
return ticket
;
}
}
4.4.6 页面效果展现