Dubbo分布式服务框架,springboot+dubbo+zookeeper
一Dubbo的简易介绍
1.Dubbo是什么?
Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。
简单的说,dubbo就是个服务框架,如果没有分布式的需求,其实是不需要用的,只有在分布式的时候,才有dubbo这样的分布式服务框架的需求,并且本质上是个服务调用的东西,说白了就是个远程服务调用的分布式框架(告别Web Service模式中的WSdl,以服务者与消费者的方式在dubbo上注册)。
其核心部分包含:
1. 远程通讯:
提供对多种基于长连接的NIO框架抽象封装,包括多种线程模型,序列化,以及“请求-响应”模式的信息交换方式。
2. 集群容错:
提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路由,动态配置等集群支持。
3. 自动发现
基于注册中心目录服务,使服务消费方能动态的查找服务提供方,使地址透明,使服务提供方可以平滑增加或减少机器。
2.Dubbo能做什么?
1.透明化的远程方法调用
就像调用本地方法一样调用远程方法,只需简单配置,没有任何API侵入。
2.软负载均衡及容错机制
可在内网替代F5等硬件负载均衡器,降低成本,减少单点。
3. 服务自动注册与发现
不再需要写死服务提供方地址,注册中心基于接口名查询服务提供者的IP地址,并且能够平滑添加或删除服务提供者。
Dubbo采用全spring配置方式,透明化接入应用,对应用没有任何API侵入,只需用Spring加载Dubbo的配置即可,Dubbo基于Spring的Schema扩展进行加载。
3.Dubbo核心组件

1)注册中心(registry)
生产者在此注册并发布内容,消费者在此订阅并接收发布的内容。
2)消费者(consumer)
客户端,从注册中心获取到方法,可以调用生产者中的方法。
3)生产者(provider)
服务端,生产内容,生产前需要依赖容器(先启动容器)。
4)容器(container)
生产者在启动执行的时候,必须依赖容器才能正常启动(默认依赖的是spring容器),
5)监控(Monitor)
统计服务的调用次数与时间等。
二.springboot+dubbo+zookeeper整合使用
1.在Linux中安装zookeeper实现服务注册

进入到镜像中
[root ~]# docker exec -it 46c8d188683b bash
查看zookeeper中的,服务情况

查看已经注册存在的服务

2.服务层中service,使用dubbo中的@Service注解

3.Providor服务提供者

3.0.application.yml
dubbo:provider:application: dubbo-providerregistry:address: zookeeper://192.168.58.128:2181scan:base-packages:- com.tjetc.serviceprotocol:name: dubbo #使用dubbo协议port: 20880 #协议端口为20880
server:port: 8081
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://192.168.58.128:3306/springboot?serverTimezone=GMT%2B8username: rootpassword: root
mybatis:type-aliases-package: com.tjetc.domain
logging:level:com.tjetc.mapper: debug
3.1.ProvidorApplication
import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
//开启dubbo服务注册
("com.tjetc.mapper")
public class ProvidorApplication {public static void main(String[] args) {SpringApplication.run(ProvidorApplication.class, args);}}
3.2.ProductServiceImpl,@Service使用dubbo中的注解
import com.alibaba.dubbo.config.annotation.Service;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tjetc.domain.Product;
import com.tjetc.mapper.ProductMapper;
import com.tjetc.service.ProductService;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import java.util.List;
public class ProductServiceImpl implements ProductService {private ProductMapper productMapper;public void add(Product product) {productMapper.add(product);}public PageInfo<Product> list(String name, Integer pageNum, Integer pageSize) {PageHelper.startPage(pageNum,pageSize);List<Product> list=productMapper.list(name);PageInfo<Product> pageInfo = new PageInfo<>(list);System.out.println("pageInfo.getList() = " + pageInfo.getList());return pageInfo;}public List<Product> listByName(String name) {return productMapper.listByName(name);}public Product findById(Integer id) {return productMapper.findById(id);}public void update(Product product) {productMapper.update(product);}public int del(Integer id) {return productMapper.del(id);}
}
4.mapper模块,代码省略

5.实体类对象模块domain,代码省略

6.Service服务接口,代码省略

7.consumer,服务消费者

7.0.ComsumerApplication

7.1.ProductController
import com.alibaba.dubbo.config.annotation.Reference;
import com.github.pagehelper.PageInfo;
import com.tjetc.domain.Product;
import com.tjetc.service.ProductService;
import com.tjetc.utils.FastDfsClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;import java.io.IOException;
import java.util.List;
("/product")
public class ProductController {("${fastdfs}")private String fastdfs;private ProductService productService;("/add")public String add(){return "add";}("/add")public String add(Product product, MultipartFile photo){System.out.println("photo = " + photo);System.out.println("product = " + product);if (photo!=null && photo.getSize()>0){String filename = photo.getOriginalFilename();String extName = filename.substring(filename.lastIndexOf(".")+1);FastDfsClient fastDfsClient = new FastDfsClient("classpath:client.properties");try {//7. 显示上传的结果(file_id 也就是文件的路径)String path = fastDfsClient.upload(photo.getBytes(), extName);System.out.println("path = " + path);product.setPhotopath(fastdfs+path);} catch (IOException e) {e.printStackTrace();}}System.out.println("product = " + product);productService.add(product);return "redirect:/product/list";}("/list")public String list((defaultValue = "") String name,(defaultValue = "1") Integer pageNum,(defaultValue = "3") Integer pageSize, Model model){System.out.println(productService);PageInfo<Product> pageInfo=productService.list(name,pageNum,pageSize);List<Product> list = pageInfo.getList();for (Product product : list) {System.out.println("product = " + product);}/*List<Product> list = productService.listByName(name);System.out.println("list = " + list);*/model.addAttribute("page",pageInfo);model.addAttribute("list",list);model.addAttribute("name",name);return "list";}("/findById")public String findById(Integer id,Model model){Product product=productService.findById(id);model.addAttribute("p",product);return "update";}("/update")public String update(Product product,MultipartFile photo){if (photo!=null && photo.getSize()>0){String fileName=photo.getOriginalFilename();String extName=fileName.substring(fileName.lastIndexOf(".")+1);FastDfsClient fastDfsClient = new FastDfsClient("classpath:client.properties");try {String path = fastDfsClient.upload(photo.getBytes(), extName);product.setPhotopath(fastdfs+path);} catch (IOException e) {e.printStackTrace();}}productService.update(product);return "redirect:/product/list";}("/del")public String del(Integer id){int i=productService.del(id);return "redirect:/product/list";}}
7.2.FastDfsClient集合文件系统工具类
import org.csource.common.MyException;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;/*** FastDFS上传文件的工具类*/
public class FastDfsClient {//声明4个成员变量private TrackerClient trackerClient=null;private TrackerServer trackerServer=null;// 4. 声明存储服务端storageprivate StorageServer storageServer=null;private StorageClient1 storageClient=null;/** 根据配置文件初始化4个成员变量* */public FastDfsClient(String config) {Properties properties = new Properties();if (config.contains("classpath:")) {try {config=config.replaceAll("classpath:","");System.out.println("config = " + config);// 使用ClassLoader加载properties配置文件生成对应的输入流InputStream in = this.getClass().getClassLoader().getResourceAsStream(config);// 使用properties对象加载输入流properties.load(in);System.out.println("properties = " + properties);// 1. 加载配置文件ClientGlobal.initByProperties(properties);} catch (IOException e) {e.printStackTrace();} catch (MyException e) {e.printStackTrace();}}else {try {ClientGlobal.initByProperties(config);} catch (IOException e) {e.printStackTrace();} catch (MyException e) {e.printStackTrace();}}// 2. 创建tracker的客户端this.trackerClient = new TrackerClient();try {// 3. 通过客户端得到服务端连接对象this.trackerServer = trackerClient.getConnection();} catch (IOException e) {e.printStackTrace();}// 5. 获取存储服务器的storage客户端对象this.storageClient = new StorageClient1(trackerServer, storageServer);}public FastDfsClient() {}public String upload(String filename, String extName, NameValuePair[] metas){try {return storageClient.upload_file1(filename, extName, metas);} catch (IOException e) {e.printStackTrace();} catch (MyException e) {e.printStackTrace();}return null;}public String upload(String filename,String exName){return this.upload(filename, exName,null);}/*** *根据文件的内容上传** @paramcontent文件内容byte[]** @paramextName文件扩展名* *@parammetas参数*@return*/public String upload(byte[] content,String extNAme,NameValuePair[] metas){try {return storageClient.upload_file1(content, extNAme, metas);} catch (IOException e) {e.printStackTrace();} catch (MyException e) {e.printStackTrace();}return null;}public String upload(byte[] content,String extName){return this.upload(content, extName,null);}public static void main(String[] args) {// 外部普通类System.out.println("方法名 类名");System.out.println("getName " + FastDfsClient.class.getName());System.out.println("getCanonicalName " + FastDfsClient.class.getCanonicalName());System.out.println("getSimpleName " + FastDfsClient.class.getSimpleName());System.out.println();//用代码实现:得到类路径的真实路径String path = FastDfsClient.class.getClassLoader().getResource("").getPath();System.out.println("path = " + path);}}
7.3.client.properties
fastdfs.tracker_servers=192.168.58.128:22122
7.4.application.yml
fastdfs: http://192.168.58.128/
dubbo:application:name: dubbo-consumerregistry:address: zookeeper://192.168.58.128:2181protocol:name: dubbo #使用dubbo协议port: 20880 #协议端口为20880server:port: 8082
spring:servlet:multipart:# 设置 上传文件的大小max-file-size: 20MB# 设置 整个请求的大小max-request-size: 20MB
7.5.list.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title><style type="text/css">table{width: 700px;border-collapse: collapse;text-align: center;}th,td{border: 1px solid #CCCCCC;}</style><script type="text/javascript">function fenye(pageNum) {alert(document.getElementById("pageSize").value)location.href="/product/list?pageNum="+pageNum+"&name="+document.getElementById("name").value;}function findById(id) {location.href="/product/findById?id="+id;}function del(id) {location.href="/product/del?id="+id;}</script>
</head>
<body>
<div><input type="text" id="name" th:value="${name}" placeholder="请输入商品名称"><button th:onclick="fenye(1)">查询</button>
</div>
<table><tr><th>编号</th><th>名称</th><th>单价</th><th>时间</th><th>美照</th><th>操作</th></tr><tr th:each="p:${list}"><td th:text="${p.id}"></td><td th:text="${p.name}"></td><td th:text="${p.price}"></td><td th:text="${#dates.format(p.time)}"></td><td><img th:src="${p.photopath}" width="100px"></td><td><button th:onclick="|findById(${p.id})|">编辑</button><button th:onclick="|del(${p.id})|">删除</button></td></tr><tr><td colspan="10"><button th:onclick="|fenye(1)|">首页</button><button th:onclick="|fenye(${page.prePage})|">上一页</button>当前页<span th:text="${page.pageNum}"></span>/<span th:text="${page.pages}"></span><button th:onclick="|fenye(${page.nextPage})|">下一页</button><button th:onclick="|fenye(${page.pages})|">尾页</button>每页<select id="pageSize" th:onclick="fenye(1)"><option value="3">3</option><option value="6">6</option><option value="9">9</option></select>条数据总记录数:<span th:text="${page.total}"></span></td></tr>
</table>
</body>
</html>
效果截图



相关文章:
Dubbo分布式服务框架,springboot+dubbo+zookeeper
一Dubbo的简易介绍 1.Dubbo是什么? Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。 简单的说,dubbo就是个服务框架,如果没有分布式的需求,其实是不需…...
网络:UDP out of order;SIP;CPU out-of-order 执行
文章目录 问题SIP如果使用UDP出现乱序网络CPU问题 最近遇到虚拟机收到的UDP包发生乱序。从协议上说,这个乱序是标准,及特性所允许的,期望的。所以上层应用需要适应这种乱序,如果不能适应,可能需要做协议转换,专用TCP,让TCP来处理这种乱序的可能。 产生乱序的原因: 是网…...
我心中的TOP1编程语言—JavaScript
作为一名研发工程师(程序员),平时工作中肯定会接触或了解很多编程语言。每个人都会有自己工作中常用的语言,也会有偏爱的一些编程语言。而我心中的最爱,毫无疑问,就是 JavaScript。 JavaScript 是一门编程…...
CentOS环境下的Maven安装
CentOS 安装 Maven 镜像地址 镜像地址:https://mirrors.tuna.tsinghua.edu.cn/apache/maven/ 下载地址:https://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.8.8/binaries/ 下载maven 将下载好的压缩包拷贝到根目录下 解压 tar -zxvf ap…...
表的增删改查
1、创建表 mysql> create table employee ( -> id int(1) comment 员工编号, -> name varchar(6) comment 员工名字, -> gender varchar(2) comment 员工性别, -> salary int (4) comment 员工薪资); Query OK, 0 rows affected (0.01 sec) 2、…...
Tauri 应用中发送 http 请求
最近基于 Tauri 和 React 开发一个用于 http/https 接口测试的工具 Get Tools,其中使用了 tauri 提供的 fetch API,在开发调试过程中遇到了一些权限和参数问题,在此记录下来。 权限配置 在 tauri 应用中,如果想要使用 http 或 fe…...
基于霍夫变换的航迹起始算法研究(Matlab代码实现)
目录 💥1 概述 📚2 运行结果 🎉3 参考文献 👨💻4 Matlab代码 💥1 概述 一、设计内容 利用Hough变换处理量测得到的含杂波的二维坐标,解决多目标航迹起始问题。使用Matlab进行仿真&#x…...
如何使用Excel公式将(d:1,a:4,c:2,b:3)快速分割成8列并按顺序排列
Excel是一款功能强大的电子表格软件,可以帮助我们处理各种数据。在处理数据时,有时候需要将一列数据按照特定的格式进行分割和重新排列。本文将介绍如何使用Excel公式将"(d:1,a:4,c:2,b:3)"快速分割成8列,并按照指定顺序排列为&quo…...
遥控泊车系统技术规范
目 录 1. 版本履历... 3 2. 文档使用范围... 3 3. 术语缩写... 3 4. 系统架构... 4 5. 功能需求... 4 5.1 功能清单... 4 6.2 功能关系描述(如有)... 4 5.3 功能1. 4 5.3.1 功能总体状态动态说…...
qt 线程状态机实现并发自动任务
一、状态机类 头文件 MyStateMachine.h#ifndef MYSTATEMACHINE_H #define MYSTATEMACHINE_H#include <QStateMachine> #include "ActionTask.h" #include...
社交机器人培育
论文: 自我繁殖的假新闻:机器人和人工智能使印度冲突地区的社会两极分化永久化 Self-Breeding Fake News: Bots and Artificial Intelligence Perpetuate Social Polarization in India’s Conflict Zones 论文链接:https://jps.library.ut…...
CUnit在ARM平台上的离线搭建(让CUnit编译安装成功之后的可执行文件.so变成ARM下的—ARM aarch64)(实用篇)
前言:1 CUint-2.1-3.tar.bz2压缩安装包下载并解压2 进入CUint-2.1-3目录并且通过指令./bootstrap*产生configure *执行文件3 执行./configure*命令4 make编译5 make install 安装 前言: 在X86架构上的Linux操作系统上面进行cmake编译(Cyclon…...
整数序列(山东大学考研机试题)
水仙花数(中南考研机试题) 链接:3644. 水仙花数 - AcWing题库 /* 暴力枚举罢了 */ #include<iostream> using namespace std; const int N1e3100; int book[N]; int pow3(int k){return k*k*k; } int main() {int m,n;for(int i100;i<999;i){int t1,t2,t3;t1 i%10;t…...
k8s集群安装
目录 一 主机准备 1.1 设备配置 ⚠️注意1 ⚠️注意2 1.2 环境准备 1.3docker安装 二 安装kubeadm、kubectl、kubelet 2.1 添加镜像源 2.2 安装 三 master节点部署 四 node节点加入集群 五 CNI网络插件calico 六 其他节点使用kubectl 1.拷贝文件 2.添加到环境变量…...
【webrtc】ProcessThreadAttached
RegisterModule 调用所在的线程指针传递给ProcessThreadAttached ProcessThreadAttached 调用不是在worker thread 而是在 registers/deregister 这个module或者 start stop 这个module的时候 ** ** pacedsender是一个moudle -实现了...
Orange pi3初调试
因为树莓派沦为理财产品1年前出手殆尽后,现在唯一一个B性能不足一直没动力调试,沦为吃灰工具。 偶然之间多多给推了个orange产品预售,看了下pi3的参数,这不和赚了差价的3B一个性能吗?果断定了个预售款,在差…...
手机里的视频怎么转换成MP4格式?简单的转换方法分享
MP4格式是一种广泛使用的视频格式,几乎所有设备和操作系统都支持MP4格式的视频播放。无论是使用 iPhone、iPad、安卓手机、电视等各种设备,都可以播放 MP4 格式的视频。这种广泛的兼容性使得 MP4 成为一种非常方便的视频格式,我们可以随时随地…...
Matlab数学建模实战——(Lokta-Volterra掠食者-猎物方程)
1.题目 问题1 该数学建模的第一问和第二问主要是用Matlab求解微分方程组,直接编程即可。 求解 Step1改写 y(1)ry(2)f Step2得y的导数 y(1).2y(1)-ay(1)*y(2)y(2).-y(2)a*y(1)*y(2) Step3编程 clear; a0.01; F(t,y)[2*y(1)-a*y(1)*y(2);-y(2)a*y(1)*y(2)]; […...
windows下软件推荐
起源与目的 选择任何一个系统作为主力系统都是要好好考虑的。 在去年新买了一块1T的SSD后,就好好想了想这个问题。 Arch Linux, Ubuntu, Windows, macOS, deepin都是在考虑范围的。 不过我考虑到使用体验,最终还是选择了windows。 不选择macOS主要是不喜…...
SQlite数据库
SQlite数据库 1.SQLite简介 轻量化,易用的嵌入式数据库,用于设备端的数据管理,可以理解成单点的数据库。传统服务器型数据库用于管理多端设备,更加复杂 SQLite是一个无服务器的数据库,是自包含的。这也称为嵌入式数…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...
React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...
html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...
