1 Dubbo框架的介绍
1.1 Dubbo框架的通讯的方式
浏览器与服务器之间的通讯协议是Http协议。
而在Dubbo框架内部,消费者与服务提供者之间的通讯协议是dubbo协议。
dubbo协议中封装了tcp-ip协议。
9001是消费者的tomcat服务器运行的端口号,
同理,9000是服务提供者的tomcat服务器运行的端口号。
而通常都是消费者9001需要求 服务者9000帮他干活,服务者9000通常都通过调用dubbo框架20880来干活,
所以可以理解为消费者9001是去调用人家的dubbo框架20880.
服务者9000的tomcat服务器一启动,它里面就会加载dubbo框架20880。
tomcat服务器相当于一个大容器。
dubbo框架属于这个大容器中的一个服务,它提供服务的端口号是20880.
消费者9001要想访问dubbo20880的服务,消费者9001就要连接20880端口。
一般协议都有ip和port。
而消费者9001需要通过一定的协议才能请求到dubbo的20880.
这个dubbo协议的ip是dubbo动态生成的,port就是dubbo的20880
我无法通过在浏览器中输入localhost:9000 这种http协议规范,访问到dubbo框架,
因为dubbo框架在9000服务器的内部,dubbo只支持dubbo协议的规范
如果有多个服务提供者ABCD
那么服务提供者A中的dubbo的端口号是20880,
服务提供者B中的duboo的端口号就得换了,比如20881,
服务提供者C中的duboo的端口号就得换了,比如20882,
…以此类推
1.2 zookeeper是如何存储数据的?
1.连接zookeeper的客户端
2.出现如图:
3.这个router就是dubbo框架控制自动生成协议ip的文件
4. 看看消费者consumers文件中都是啥内容
5.再看看服务者provides文件中有啥
zookeeper通过一个树形结构存储信息,一般是3级:
1.3 负载均衡–两大类
1.3.1 集中式负载均衡 (压力集中到了nginx身上)
由于nginx处于负载均衡的中心,所以各种各样的服务都会经过nginx之后再转向到不同的服务器中. 所以会造成nginx的负载压力很大很大.
而nginx的主要的功能是反向代理,负载均衡只是它的副业。
1.3.2 客户端的负载均衡
在微服务调用过程中每个服务的消费者都可以在客户端实现负载均衡的操作,
即由消费者自己去决定它去请求哪台服务者的服务。
在消费者每次请求之前通过服务列表获取将要访问的服务者的服务信息.实现了压力在消费者端的私有化.
1.3.3 Dubbo框架中的负载均衡的方式
Dubbo框架中,消费者的请求默认的负载均衡的方式是 Random 随机的方式。
在消费者的controller中,在引入服务者的Service对象时,在@Reference注解中规定用哪种负载均衡的方式
如果不写,默认就是Random。
通常用到的 共有4种:
名称都是类名的前半部分都小写即可.
1.RandomLoadBalance 随机负载均衡 语法: random (默认的)
2.RoundRobinLoadBalance 轮询策略 语法: roundrobin
3.ConsistentHashLoadBalance 一致性hash算法 将消费者与服务提供者绑定 (一个2^32的圆环,根据hash算出key属于哪个节点管理,就让消费者去访问这个服务提供者) 语法: consistenthash
4.LeastActiveLoadBalance 挑选“最近被访问次数最少的”服务器进行访问 语法: leastactive
2 京淘项目的服务提供者中引入Dubbo框架
2.1 改造计划
1.jt-common充当接口项目
2.jt-sso 充当服务提供者 ,服务端口号20880, 服务名称 provider-sso, 接口DubboUserService
3.jt-web 充当消费者
记得提前启动nginx和redis集群!!!!
2.2 jt父级pom.xml中导入Dubbo jar包
<!--引入dubbo配置 -->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>
2.3 编辑Dubbo接口
在jt-common中添加Dubbo的业务接口,会用到Cart,Item,Order,User这四个方面的接口
2.4 编辑jt-sso服务提供者
2.4.1 编辑Service实现类—DubboUserServiceImpl
在jt-sso中的service中新建一个实现类DubboUserServiceImpl,让它去实现jt-common接口中的DubboUserService接口
2.4.2 编辑服务提供者jt-sso的yml文件
在原yml文件的基础上,在最下面添加关于dubbo的配置。
由于2.3中要求 服务名称 是provider-sso,所以application的name后面要写provider-sso
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的支持
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-sso #一个接口对应一个服务名称
registry: #zk集群 主机中的信息与从机中的信息一致的 从zk中获取数据的时候链接的从机 主机的作用就是监控集群
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.5 编辑服务消费者jt-web
2.5.1 编辑jt-web的UserController
在jt-web中,编辑UserController
2.5.2 编辑jt-web的yml文件
由于需要让dubbo框架整体笼罩着消费者和服务者,所以消费者中也需要配置一些dubbo的相关配置,消费者才能去访问服务者中的dubbo服务。
配置dubbo时,消费者的yml文件与服务者的yml文件的不同地方:
1.application的name后面不同,消费者有消费者的名字,服务者有服务者的名字
2.服务者的yml文件中添加了protocol的name和port的配置,规定了协议的名字(dubbo)和提供服务的端口号(20880),
而消费者不配置这个protocal,因为消费者是要去根据协议去请求服务者的访问的。谁提供服务,谁就配置protocol。
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 用户模块(User)一些功能的实现
3.1 用户注册
在用户注册页面,用户填写好信息后,提交后,将信息保存到数据库中。
3.1.1 浏览器页面分析
目前 当我在用户注册页面输入username ,password,phone和email(由于京淘项目功能还不完善,email暂时不需要填写,入库时会自动保存跟phone一样的信息),点击提交后:
浏览器的network中显示:
3.1.2 页面JS分析
通过上图中url中的关键字:/user/doRegister
去IDEA中进行搜索(ctrl+h),可以快速找到京淘项目定义这个请求的前台JS代码
3.1.3 编辑jt-web中的UserController
在UserController中添加doRegister()
注意 在上面要引入DubboUserService对象
/**
* 在dubbo框架下,完成用户信息的注册
* url: http://www.jt.com/user/doRegister
* 参数:{password:_password,username:_username,phone:_phone}
* 返回值: SysResult对象
* 业务说明: 通过dubbo框架将user信息RPC传入jt-sso,实现用户注册信息的入库操作
*/
@RequestMapping("/doRegister")
@ResponseBody
public SysResult doRegister(User user){//用User对象去接收用户在注册页面中填写的各种信息
//调用jt-common接口中定义的对象
dubboUserService.saveUser(user);
//告诉用户 他注册成功了(失败的话由全局异常处理类去告知)
return SysResult.success();
}
3.1.4 编辑jt-common中的DubboUserService
在jt-common中,编辑DubboUserService
//用户
public interface DubboUserService {
//通常来说save操作的返回值是int,但在用户注册的这个业务中,不用告诉用户save操作影响了几行,只需要告诉他成功与否即可
//所以这里可以手动把返回值由SysResult 改成了 void
void saveUser(User user);
}
3.1.5 编辑jt-sso中的DubboUserServiceImpl
在jt-sso中,新建DubboUserServiceImpl类,并让它实现jt-common中的saveUser方法
@Service //dubbo包中的service注解
public class DubboUserServiceImpl implements DubboUserService{
@Autowired
private UserMapper userMapper;
/**
* 将用户提交的注册信息保存到数据库中
* 1.邮箱暂时使用电话号码代替
* 2.需要将密码进行加密处理 (MD5-hash加密)
* @param user
* @return
*/
@Override
@Transactional //记得进行事务控制
public void saveUser(User user) {
//1.获取密码明文
String password = user.getPassword();
//2.利用spring的工具API对密码明文进行加密
password = DigestUtils.md5DigestAsHex(password.getBytes());
//3.将加密后的密码和邮箱(这里其实就是电话号)再添加给user对象
user.setPassword(password).setEmail(user.getPhone());
//4.将user对象的信息保存到数据库中
userMapper.insert(user);
}
}
3.1.6 关于POJO转化异常说明
报错说明:
由于SpringBoot配置了热部署的工具,当代码有了稍微的修改之后,程序就会重新启动.
在重启的过程中,服务提供者又会再次链接zookeeper注册中心.
由于zookeeper的心跳检测机制存在超时时间(一般zookeeper要检测3次服务提供者是否在工作中,并且每次检测之间都有时间间隔,可能在间隔时间中,服务提供者重启成功了,它就又去zookeeper中注册了一下它的状态),这样就可能在zookeeper中会出现2条一模一样的服务提供者的信息.
解决方法: 手动再次重启服务提供者的服务器即可
3.2 单点登录实现策略
3.2.1 需求说明
要求用户只需要登录一次,他就可以访问其他的认证系统,无需他再次输入用户名和密码去登录.
如果采用如下的配置,则必然会出现用户频繁登录的现象.
1.用户登录不同的系统,如manage系统登录完,再去访问CART系统还需要登录,去访问WEB系统还需要登录…
2.不仅如此,由于用户的登录信息在服务器端 在会话过程中是存在于session对象中的,单看在一个系统中,比如manage系统
中肯定有多态manage服务器,而每台manage服务器中的session对象是自己独有的,不会跟别的manage服务器共享的,所以即使用户只登录manage系统,在访问到不同的资源时,也会需要不断的登录。
怎么解决这个问题呢?
就用SSO:单点登录系统
3.2.2 SSO介绍
单点登录(SingleSignOn,SSO),就是通过用户的一次性鉴别登录。
当用户在身份认证服务器上登录一次以后,即可获得访问单点登录系统中其他关联系统和应用软件的权限,
同时这种实现是不需要管理员对用户的登录状态或其他信息进行修改的,这意味着在多个应用系统中,用户只需一次登录就可以访问所有相互信任的应用系统。
这种方式减少了由登录产生的时间消耗,辅助了用户管理,是目前比较流行的 一种登录方式
3.2.3 单点登录实现策略
步骤:
1.当用户输入用户名和密码时需要将数据传递给jt-web服务器进行登录操作.
2.jt-web服务器需要将数据传到jt-sso服务器中进行数据的校验.
3.jt-sso根据username/password查询数据库校验数据是否有效.
4.如果用户名和密码正确则将数据经过处理之后保存到redis中 KEY=UUID(每次生成的都不一样) VALUE=“userJSON”
5.如果用户写入redis成功,之后需要将用户的登录的凭证返回给客户端.
6.JT-WEB服务器将获取的TICKET信息保存到客户端的Cookie中,方便下次使用. 并且要求cookie共享的.
ticket长什么样呢?
它就是UUID去掉“-”后的字符串。比如“9f8fc1303bb2483a9493258f2db56acb”
3.3 用户登录具体实现
TODO
3.4 用户登录信息回显到主页
TODO