cgb2010- 京淘我的项目 Day18
1.ZK 集群搭建
阐明: 个体搭建内容, 参见课前材料的文档.
1.1 搭建集群规定
规定: 残余存活节点的数量 > N/2 N 代表节点总数
计算:
1 个节点 1-1 > 1/2 假的 一个节点不能搭建集群
2 个节点 2-1 > 2/2 假的 二个节点不能搭建集群
3 个节点 3-1 > 3/2 真的 集群的最小的单位 3 台.
4 个节点 4-1 > 4/2 真的
1.2 为什么集群个别都是奇数台
从容灾性 / 经济性的角度思考问题
奇数 3 台 3-1 > 3/2 宕机 1 台能够失常工作
3-2 > 3/2 宕机 2 台集群解体
偶数 4 台 4-1 > 2/4 宕机 1 台能够失常工作
4-2 > 4/2 宕机 2 台集群解体
答: 发现奇数台和偶数台的容灾性雷同的, 所以搭建 奇数台更好.
1.3 zk 集群选举规定
规定: myid 最大值优先 只探讨 1 轮
考题:
编号 1,2,3,4,5,6,7 顺次启动. 至多 4 台…
问题 1: 谁当主机? 4 当主…
问题 2: 谁永远当不了主机? 1,2,3
2.Dubbo 框架
2.1 Dubbo 介绍
Dubbo(读音 [ˈdʌbəʊ]) 是阿里巴巴公司开源的一个 高性能优良的服务框架(SOA),使得利用可通过高性能的 RPC 实现服务的输入和输出性能,能够和 [1] Spring 框架无缝集成。
Dubbo 是一款高性能、轻量级的开源 Java RPC 框架,它提供了三大外围能力:面向接口的近程办法调用,智能容错和负载平衡,以及服务主动注册和发现。
2.2 Dubbo 入门案例
2.2.1 批改配置文件
1). 查看 POM 文件是否正确
2). 批改 SpringBoot 版本
2.3 接口定义
阐明: interface 与被消费者 / 生产者 (提供者) 依赖.
2.4 编辑服务提供者
2.4.1 提供者代码构造
2.4.2 编辑 Service 实现类
`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);
}
}
2.4.3 编辑 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 #开启驼峰映射规定
2.5 编辑服务消费者
2.5.1 消费者代码构造
2.5.2 编辑 Controller 代码
2.5.3 编辑 YML 配置文件
2.5.4 页面成果测试
2.6 微服务框架测试
2.6.1 服务高可用测试
敞开一个服务提供者, 检查用户的拜访是否收到影响. 通过测试. 用户拜访不受影响.
2.6.2 zk 高可用测试
将 zk 主机敞开, 检查用户拜访是否受限. 通过测试拜访不受限制.
2.6.3 zk 集群宕机测试
将 zk 集群全副敞开, 检查用户拜访是否受限?? 不受影响 因为消费者本地也有服务列表信息(之前缓存的)
2.7 对于负载平衡阐明
2.7.1 集中式负载平衡
阐明: 对立由服务器进行负载平衡的调度. 反向代理机制.
2.7.2 客户端式负载平衡
2.7.3 Dubbo 框架中负载平衡形式
1.ConsistentHashLoadBalance 一致性 hash 算法 消费者绑定惟一的服务提供者
2.LeastActiveLoadBalance 最小拜访 筛选以后服务器压力最小的提供者进行拜访.
3.RandomLoadBalance 随机算法 是默认的负载平衡机制
- RoundRobinLoadBalance 轮询机制
3. 京淘我的项目 Dubbo 革新
3.1 导入 jar 包
`<!-- 引入 dubbo 配置 -->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>
3.2 定义中立接口
3.3 革新 JT-MANAGE
3.3.1 定义实现类
3.3.2 编辑 YML 配置文件
`server:
port: 8091
servlet:
context-path: /
spring:
datasource:
#url: jdbc:mysql://192.168.126.129:8066/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
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-item #一个接口对应一个服务名称
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 #每一个服务都有本人特定的端口 不能反复.
3.4 构建服务消费者 -JT-WEB
3.4.1 编辑 ItemController
3.4.2 编辑 YML 配置文件
`server:
port: 8092
spring: #定义 springmvc 视图解析器
mvc:
view:
prefix: /WEB-INF/views/
suffix: .jsp
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
4. 商品前台展示
4.1 业务剖析
阐明: 用户点击某个商品时, 应该跳转到商品的展示页面 item.jsp 中.
数据获取规定:
须要查问后盾服务器获取以后的商品信息, 之后将数据保留到域对象中, 通过 el 表达式动静获取 ${item.title}
数据 1: Item 对象信息
数据 2: ItemDesc 对象信息
4.2 编辑 ItemController
`package com.jt.controller;
import com.alibaba.dubbo.config.annotation.Reference;
import com.jt.pojo.Item;
import com.jt.pojo.ItemDesc;
import com.jt.service.DubboItemService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Controller // 页面跳转.......
public class ItemController {
// 先启动服务消费者 临时不校验是否有提供者
@Reference(check = false)
private DubboItemService itemService;
/**
*
* 业务需要: 依据商品 id 号查问商品 / 商品详情信息
* url 地址: http://www.jt.com/items/562379.html
* 参数: restFul 格调
* 返回值: 跳转页面 item.jsp
* 页面取值: Item/ItemDesc 对象
*/
@RequestMapping("/items/{itemId}")
public String findItemById(@PathVariable Long itemId, Model model){Item item = itemService.findItemById(itemId);
ItemDesc itemDesc = itemService.findItemDescById(itemId);
// 须要将数据保留到域对象中
model.addAttribute("item", item);
model.addAttribute("itemDesc", itemDesc);
return "item";
}
}
4.3 编辑 ItemService
`package com.jt.web.service;
import com.alibaba.dubbo.config.annotation.Service;
import com.jt.mapper.ItemDescMapper;
import com.jt.mapper.ItemMapper;
import com.jt.pojo.Item;
import com.jt.pojo.ItemDesc;
import com.jt.service.DubboItemService;
import org.springframework.beans.factory.annotation.Autowired;
@Service(timeout = 3000)
public class DubboItemServiceImpl implements DubboItemService {
@Autowired
private ItemMapper itemMapper;
@Autowired
private ItemDescMapper itemDescMapper;
// 查问商品信息
@Override
public Item findItemById(Long itemId) {return itemMapper.selectById(itemId);
}
// 查问商品详情信息
@Override
public ItemDesc findItemDescById(Long itemId) {return itemDescMapper.selectById(itemId);
}
}
4.4 成果展示
4.5 对于 POJO 报错阐明
阐明: 如果遇到这样的报错信息, 则须要重启服务器即可.
起因: 因为热部署速度很快 导致 zk 服务器外部呈现了 2 条截然不同的服务信息. 不晓得应该拜访哪个报错.
- 用户模块革新
==========
5.1 编辑 DubboUserService
5.2 编辑 YML 配置文件
`server:
port: 8093
servlet:
context-path: /
spring:
datasource:
#url: jdbc:mysql://192.168.126.129:8066/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
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: 20881 #每一个服务都有本人特定的端口 不能反复.
- 用户注册实现
==========
6.1 业务剖析
6.1.1 页面 URL 剖析
6.1.2 参数剖析
6.1.3 查看页面 JS
6.2 编辑 JT-WEB UserController
6.3 编辑 JT-SSO UserService
package com.jt.service;
import com.alibaba.dubbo.config.annotation.Service;
import com.jt.mapper.UserMapper;
import com.jt.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.DigestUtils;
@Service(timeout = 3000)
public class DubboUserServiceImpl implements DubboUserService{
@Autowired
private UserMapper userMapper;
@Override
public void saveUser(User user) {
// 将明码 md5 加密
byte[] bytes = user.getPassword().getBytes();
String md5Pass = DigestUtils.md5DigestAsHex(bytes);
user.setPassword(md5Pass);
// 要求 email 不为 null 临时应用电话代替
user.setEmail(user.getPhone());
userMapper.insert(user);
}
}