今日学习总结
1.算法学习
迪杰斯特拉算法
主要核心思想:得到起始点,存入distancemap(存起始点到该点的最短距离),利用hashset(去掉已经使用过的点)
1.得到距离当前节点最近的节点
2.遍历该节点的所有边,如果能发现新的不在distancemap里的点,就把起始点到当前点的距离,加上当前点到边to的点的距离存入distancemap
3.如果distancemap里存在当前点,则比较原本存入的距离和当前点到to点的距离是否更短
4.更新最近点
package day09;
import day08Graph.Edge;
import day08Graph.Node;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
public class DijkstraMyWay {
public HashMap<Node,Integer> dijkstra(Node from){
HashMap<Node,Integer> distanceMap = new HashMap<>();
HashSet<Node> selectedSet = new HashSet<>();
Node minNode = getMinDistanceNodefromDistanceMap(distanceMap,selectedSet);
distanceMap.put(from,0);
while (minNode!=null){
int distance = distanceMap.get(minNode);
for (Edge edge : minNode.edges) {
Node toNode = edge.to;
if (!distanceMap.containsKey(toNode)){
distanceMap.put(toNode,edge.weight+distance);
}else {
distanceMap.put(toNode,Math.min(distanceMap.get(toNode),edge.weight+distance));
}
}
selectedSet.add(minNode);
minNode = getMinDistanceNodefromDistanceMap(distanceMap,selectedSet);
}
return distanceMap;
}
private Node getMinDistanceNodefromDistanceMap(HashMap<Node, Integer> distanceMap, HashSet<Node> selectedSet) {
Node minNode = null;
int minDistance = Integer.MAX_VALUE;
for (Map.Entry<Node, Integer> entry : distanceMap.entrySet()) {
Node node = entry.getKey();
int distance = entry.getValue();
if (!selectedSet.contains(node)&&distance<minDistance){
minNode = node;
minDistance = distance;
}
}
return minNode;
}
}
明日计划:利用优先队列对迪杰斯特拉算法进行优化,总结滑动窗口相关的算法内容
2.分布式技术学习-dubbo
1.dubbo概述
架构演变
- 单一应用架构
- 垂直应用架构
- 分布式服务架构
- 流动计算架构
dubbo简介
- 是分布式服务框架,阿里巴巴开源
- 致力于提高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案
- 简单来说,是个服务框架,如果没有分布式的需求,是不需要用的
RPC
远程过程调用,是一种进程间通信方式
- RPC基本的通信原理
- 在客户端将对象进行序列化
- 底层通信框架使用netty(基于TCP协议的Socket),将序列化的对象发送给服务提供方
- 服务提供方通过socket得到数据文件后,进行反序列化,获得要操作的对象
- 对象数据操作完毕,将新的对象序列化,再通过服务方提供的socket返回给客户端
- 客户端获得序列化数据,再反序列化,得到新的对象,至此,完成一次请求
RPC两个核心模块:通信、序列化
Dubbo角色
节点 | 角色说明 |
---|---|
Provider | 服务的提供方 |
Consumer | 调用远程服务的消费方 |
Registry | 服务注册和发现中心 |
Monitor | 统计服务的调用次数和调用时间的监控中心,在内存中累计调用次数和调用时间,每隔一段时间发送到数据监控中心 |
Container | 服务运行容器 |
调用关系
- 服务容器负责启动,加载,运行服务提供者
- 服务提供者在启动时,向注册中心注册自己提供的服务
- 服务消费者在启动时,向注册中心订阅自己所需的服务
- 在注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者
- 服务消费者,从提供者地址列表中,基于负载均衡算法,选一台提供者进行调用,如果调用失败,再调用另外一台
- 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心
明日计划:搭建一个简单的dubbo框架demo,了解dubbo框架的工作流程
3.项目学习-快速搭建三大服务,商品、订单和用户服务
本项目采用分布架构,这个项目的主要目的是了解微服务架构的搭建流程,包括通过nacos发现注册服务,接入网关等等
Order服务核心代码
通过调用restTemplate与其他微服务进行通讯,获取对应的对象,对订单进行一些简单的逻辑处理(判断用户是否存在,商品是否存在,库存是否足够,构建订单信息和订单详情并调用持久层存入)
@Autowired
private OrderMapper orderMapper;
@Autowired
private OrderItemMapper orderItemMapper;
@Autowired
private RestTemplate restTemplate;
@Override
@Transactional(rollbackFor = Exception.class)
public void saveOrder(OrderParams orderParams) {
if (orderParams.isEmpty()){
throw new RuntimeException("参数异常"+ JSONObject.toJSONString(orderParams));
}
User user = restTemplate.getForObject("http://localhost:8060/user/get/" + orderParams.getUserId(), User.class);
if (user == null){
throw new RuntimeException("未获取到用户信息:"+JSONObject.toJSONString(orderParams));
}
Product product = restTemplate.getForObject("http://localhost:8070/product/get/" + orderParams.getProductId(), Product.class);
if (product==null){
throw new RuntimeException("未获取到商品信息"+JSONObject.toJSONString(orderParams));
}
if (product.getProStock()<orderParams.getCount()){
throw new RuntimeException("商品库存不足:"+JSONObject.toJSONString(orderParams));
}
Order order = new Order();
order.setAddress(user.getAddress());
order.setPhone(user.getPhone());
order.setUserId(user.getId());
order.setUsername(user.getUsername());
order.setTotalPrice(product.getProPrice().multiply(BigDecimal.valueOf(orderParams.getCount())));
orderMapper.insert(order);
OrderItem orderItem = new OrderItem();
orderItem.setNumber(orderParams.getCount());
orderItem.setOrderId(order.getId());
orderItem.setProId(product.getId());
orderItem.setProName(product.getProName());
orderItem.setProPrice(product.getProPrice());
orderItemMapper.insert(orderItem);
Result<Integer> result = restTemplate.getForObject("http://localhost:8070/product/update_count/"+orderParams.getProductId()+"/"+orderParams.getCount(),Result.class);
if (result.getCode()!= HttpCode.SUCCESS){
throw new RuntimeException("库存扣减失败");
}
log.info("库存扣减成功");
}
测试
用户服务和商品服务同理,没有什么复杂的逻辑处理,后续会接入消息队列等等
明日计划:实现服务的自动注册和发现,实现服务调用负载均衡