go-micro
一,课程介绍
1,主讲老师: 大地
2,合作网站: www.itying.com
3,我的专栏: https://www.itying.com/category_Z9-b0.html
4,必备基础:学习本教程要有golang和go web基础
5,大地老师Golang入门实战系列教程地址:
Golang教程_IT营
二,微服务架构(micro services)
2.1 微服务架构和微服务
微服务架构:微服务架构是一种具体的设计实现或者设计方案,是将复杂的系统使用组件化的方式进行撤分,并使用轻量级通讯方式进行整合的一种设计方法。
微服务:微服务是微服务架构具体的实现方案,是通过微服务架构设计方法撤分出来的一个独立的组件化的小应用。
微服务架构定义的精髓,可以用一句话来描述,那就是"分而治之,合而用之"。将复杂的系统进行撤分的方法,就是"分而治之"。分而治之,可以让复杂的事情变的简单,这很符合我们平时处理问题的方法,使用轻量级通讯等方式进行整合的设计,就是"合而用之"的方法,合而用之可以让微小的力量变动强大。
2.2 什么是微服务架构
微服务架构是将一个单一应用程序开发为一组小型服务的方法,每个服务运行在自己的进程中,服务间通信采用的轻量级通信机制(通常用HTTP资源API),这些服务围绕业务能力构建并且可通过全自动部署机制独立部署。这些服务公用一个最小型的集中式的管理,服务可用不同的语言进行开发,使用不同的数据存储技术。
在了解微服务之前首先看看单体架构。
单体架构在中小企业内部用的是非常多的,当业务部复杂,团对规模不大的时候,单体架构比微服务架构具有更高的生产率。我们给大家讲的《golang仿小米商城项目》以及2017年前的淘宝都是单体架构。
注意 :下面示例中的服务器和数据库也可以使用docker容器实现
2.2.1 单体架构的程序部署在单台服务器 每天五万下访问量
这样的架构能轻松的应对每天五万以下的访问量
这种架构是目前中小企业用的最多的架构。其中web服务(nginx),网站程序,静态资源(图片),数据库(Mysql,Redis)都在一台服务器上面。如果每天网站的访问ip在5w以下这种架构完全可以应付(服务器配置也有关系)
2.2.2 单体架构的程序部署在多台服务器(负载均衡) 每天几十万的访问量
这样的架构能轻松的应对每天几十万的访问量
把我们的程序部署到多台服务器上面,然后通过nginx配置负载均衡,当客户访问我们的项目的时候随机的分配给不同的服务器处理响应,这样可以防止宕机,提升系统运行稳定性。
2.2.3 单体架构的程序部署在多台服务器(负载均衡+主从数据库)
这样的架构能轻松的应对每天几百万,上千万的访问量
当每天有上亿访问量,或者更高并发量的时候,什么的方法就有点力不从心了,这个时候我们就可以使用微服务架构。
2.2.4 , 微服务架构
微服务架构:通俗的讲就是把单体架构项目抽离成多个项目(服务),部署到多台服务器。
如果用"茶壶煮饺子"来打比方发话,原来我们是在一个茶壶煮很多个饺子,现在(微服务化之后)则基本上是在一个茶壶煮一个饺子,而这些饺子就是服务的功能,茶壶则是将这些服务功能打包交付的服务单元。
2.3 微服务这个概念的由来
据说,早在2011年5月,在威尼斯附近的软件架构师讨论会上,就有人提出了微服务架构设计的概念,用它来描述与会者所见的一种通用的架构设计风格。时隔一年之后,在同一个讨论会上,大家决定将这种架构设计风格用微服务架构来表示。
起初,对微服务的概念,没有一个明确的定义,大家只能从各自的角度说出了微服务的理解和看法。
在2014年3月,詹姆斯.刘易斯(James Lewis)与马丁福勒(Martin Fowler)所发表的一篇博客中,总结了微服务架构设计的一些共同特点,这应该是一个对微服务比较全面的描述。
原文链接:https://martinfowler.com/articlers/microservices.html
2.4 微服务架构和单体式架构区别
2.4.1 单体架构服务
单体架构的优点:
1,部署简单: 由于是完整的结构体,可以直接部署在一个服务器上即可
2,技术单一:项目不需要复杂的技术栈,往往一套熟悉的技术栈就可以完成开发
3,用人成本低:单个程序员可以完成接口到数据库的整个流程
4,项目管理相对较易
5,测试相对简单直观
6,应用开发相对简单
7,横向扩展容易
单体架构的缺点:
1,系统启动慢,一个进程包含了所有的业务逻辑,涉及到启动模块过多,导致系统的启动,重启周期变长
2,系统错误隔离性差,可用性差,任何一个模块的错误可能导致整个系统的宕机
3,可伸缩性差,系统的扩容只能对整个应用扩容,不能做到对整个功能点进行扩容
4,线上问题修复时间长,任何一个线上问题修复需要对整个应用系统进行全面升级
5,交付周期长(需求-->设计-->开发-->测试-->现场实施部署,就传统性质的企业而言)
2.4.2 微服务
微服务的优点:
1,易于开发和维护:一个服务只关注一个特定的业务功能,所以他业务清晰,代码量少,开发和维护单个微服务相当简单。而整个应用是若干个微服务构建而成的,所以整个应用在被维持在一个可控的状态;
2,单个服务启动快:单个服务代码量少,所以启动快;
3,局部修改易部署:单个应用只要有修改,就得重新部署整个应用,微服务解决了这个问题,一般来说,对某个微服务进行修改,只需要重新部署这个服务即可;
4,技术栈不受限:在微服务架构中,可以结合业务和团队的特点,合理选用技术栈。例如有些服务可以使用关系型数据库Mysql,有的服务可以使用非关系型数据库redis,甚至可根据需求,部分服务使用JAVA开发,部分微服务使用Node.js开发。
5,按需收缩:可根据需求,实现细粒度的扩展。例如,系统中某个微服务遇到了瓶颈,可以结合微服务的特点,增加内存,升级CPU或增加节点。
微服务的缺点:
1,运维成本高
2,分布式复杂度高
3,
2.5 为什么要学微服务
1,会单体架构学习微服务非常简单
2,微服务是非常热门的话题,企业招聘中越来越多的要求有委屈开发,架构能力的人才
3,提升技术实力,增加职业转型的可能性
4,微服务解决工作中软件研发难题,比如高并发
5,微服务技术栈不受限,可以发布的和其他语言实现通信
6,如果你是架构师或者项目管理人员微服务是必备技能
三,RPC架构
简单了解微服务定义和优缺点之后,在我们正式学习微服务框架之前,需要首先了解一下RPC架构,通过RPC我们可以形象了解微服务的工作流程。
3.1 RPC的概念
RPC(Remote Procedure Call Protocoll),是远程过程调用的缩写,通俗的说就是调用远处的一个函数。与之相对应的是本地函数调用,我们先来看一下本地函数调用。当我们写下如下代码的时候:
规则
result := Add(1,2)
我们知道,我们传入了1,2两个参数,调用了本地代码中的一个Add函数,得到result这个返回值。这个时参数,返回值,代码段都在一个进程空间内,这是本地函数调用。
那有没有办法,我们能够调用一个跨进程(所以叫"远程",典型的实例,这个进程部署在另一台服务器上)的函数呢?
微服务的目的:就是让我们在本地可以调用远程服务端里面的函数或者方法,所以首先要定义一个远程调用的方法。 比如Add()这个方法。
这就是RPC主要实现的功能,也是微服务的主要功能。
3.2 RPC入门
我们使用微服务化的一个好处就是:
1,不限定服务的提供方使用什么技术选型,能够实现公司跨团队的技术解耦,
2,每个服务都被封装成进程。彼此"独立"。
3,使用微服务可以跨进程通信
下图表示:
go语言内置了RPC,通过RPC我们可以实现跨语言的调用,比如说我们在go语言里面写的微服务,接下来,我们可以在java或者C++调用我们go语言写的微服务,同理,java写的微服务,我们也可以在go语言里面或者C++语言里面来调用java写的微服务。
RPC协议可以让我们实现不同语言的直接相互调用。在互联网时代,RPC已经和IPC(进程间通信)一样成为不可或缺的基础构件。
IPC:进程间通信
RPC:远程进程间通信--应用层协议(http协议同层)。底层使用TCP实现。
在 golang 中实现RPC非常简单,有封装好的官方库和一些第三方库提供支持。Go RPC可以利用 tcp 或http来传递数据,可以对要传递的数据使用多种类型的编解码方式。golang官方的 net/rpc 库使用 encoding/gob进行编解码,支持tcp或http数据传输方式,由于其他语言不支持gob编解码方式,所以使用 net/rpc 库实现的RPC方法没办法进行跨语言调用。
golang官方还提供了net/rpc/jsonrpc库实现RPC方法,JSON RPC采用JSON进行数据编解码,因而支持跨语言调用。但目前的jsonrpc库是基于tcp协议实现的,暂不支持使用http进行数据传输。
除了 golang 官方提供的rpc库,还有许多第三方库为在golang中实现RPC提供支持,大部分第三方rpc库的实现都是使用protobuf进行数据编解码,根据protobuf声明文件自动生成rpc方法定义域服务注册代码,在 golang 中可以很方便的进行RPC服务调用。
3.3 net/rpc库 使用 http 作为 RPC 的载体实现远程调用(了解)
下面的例子演示一下如何使用 golang 官方的 net/rpc 库实现 RPC 方法,使用 http 作为 RPC 的载体,通过 net/http 包监听客户端连接请求。
http基于tcp,多一层封包和几次握手校验,性能自然比直接用tcp实现网络传输要差一些,所以 RPC 微服务中一般使用的都是tcp
3.3.1 创建RPC微服务端
新建 rpc_demo_http/server/main.go
package main import ("fmt""log""net""net/http""net/rpc""os"
)// 定义类对象
type world struct {}// 绑定类方法
func (this *world) Helloworld(rep string,res *string) error {*res = req + "您好!"return nil// return errors.New("未知的错误!")
}
3.4.1 创建RPC微服务端
新建 rpc_demo_tcp/server/main.go
package main
import ("fmt""net""net/rpc"
)
// 定义类对象
type World struct {}// 绑定类方法
func (this *world) Helloworld(req string,res *string) error {*res = req + "您好!"return nil
}func main() {// 1. 注册RPC服务err := rpc.RegisterName("hello",new(world))if err != nil {fmt.Println("注册 rpc 服务失败!",err)return }// 2,设置监听listener,err := net.Listen("tcp","127.0.0.1:8080")if err != nil {fmt.Println("net.Listen err:",err)return}defer listener.Close()fmt.Println("开始监听 ...")// 3,建立链接for {// 接收连接conn,err := listener.Accept()if err != nil {fmt.Println("Accept() err:",err)return}// 4, 绑定服务go rpc.ServeConn(conn)}
}
HelloWorld 方法必须满足Go语言的RPC规则:
1,方法只能有两个可序列化的参数,其中第二个参数是指针类型
2,方法要返回一个error类型,同时必须是公开的方法。
golang 中的类型比如:channel(通道),complex(复数类型),func(函数)均不能进行 序列化
3.4.2 创建RPC客户端
新建 rpc_demo_tcp/client/main.go
package mainimport ("fmt""net/rpc"
)
func main() {// 1,用 rpc 链接服务器 --Dial()conn, err := rpc.Dial("tcp","127.0.0.1:8800")if err != nil {fmt.Println("Dial err:",err)return}defer conn.Close()// 2,调用远程函数var reply string // 接受返回值---传出参数/*1,第一个参数 hello.SayHello hello表示服务名称 SayHello方法名称2,第二个参数 给服务端的req传递数据3,第三个参数 需要传入地址 获取微服务端返回的数据*/err = conn.Call("hello.Helloworld","张三",&reply)if err != nil {fmt.Println("Call:",err)return}fmt.Println(reply)
}
说明:首选是通过 rpc.Dial拨号RPC服务,然后通过client.Call调用具体的RPC方法。在调用client.Call时,第一个参数是用点号链接的RPC服务名字和方法名字,第二和第三个参数分别我们定义RPC方法的两个参数。
以下是一个实现简单RPC服务实践
1,服务端 server/hello/main.go
package mainimport ("fmt""net""net/rpc"
)// 定义一个远程调用的方法 服务器端程序
// 1,定义一个结构体
type Hello struct {
}/*定义一个方法 方法只能有两个序列化的参数 其中第二个参数必须是指针类型第一个参数是客户端传过来的数据,第二个参数是服务器端返回给客户端的数据该方法必须有一个error类型的返回值,用来表示是否调用成功request:表示获取客户端传过来的数据response:表示服务器端返回给客户端的数据req 和 res 中的类型比如:channel(通道),complex(复数类型),func(函数)均不能进行 序列化操作,所以不能作为rpc方法的参数类型*/func (Hello) SayHello(request string, response *string) error {fmt.Println("服务端收到客户端的数据:", request)*response = "Hello,我是服务端," + requestreturn nil
}func main() {// 1, 注册RPC服务err1 := rpc.RegisterName("Hello", new(Hello))if err1 != nil {fmt.Println("注册服务失败")}// 2,监听端口,等待客户端的连接Listener, err2 := net.Listen("tcp", "127.0.0.1:8080")if err2 != nil {fmt.Println("监听端口失败")}// 3,应用退出前关闭监听端口defer Listener.Close()// 4,建立链接 循环等待客户端的连接请求for { // 死循环等待客户端的连接请求 for循环等待客户端的连接请求fmt.Println("开始建立连接")// 4,建立一次链接conn, err3 := Listener.Accept()if err3 != nil {fmt.Println("接受客户端失败")}// 5,绑定服务 为当前链接提供服务rpc.ServeConn(conn)fmt.Println("服务端退出")}
}2,客户端 client/hello/main.go
package mainimport ("fmt""net/rpc"
)func main() {// 1,用 rpc.Dial和rpc 微服务端建立连接,然后调用 rpc 微服务端的方法。conn, err1 := rpc.Dial("tcp", "127.0.0.1:8080") // 这里的参数要和服务器端的一致if err1 != nil {fmt.Println(err1)}// 2, 当连接建立后,需要关闭它。否则会造成资源泄露。所以这里使用了 defer 关键字来延迟执行 Close 方法。defer conn.Close()// 3, 调用远程函数var reply string/*1,第一个参数 hello.SayHello hello表示服务名称 SayHello方法名称2,第二个参数 给服务端的req传递数据3,第三个参数 需要传入地址 获取微服务端返回的数据*/err2 := conn.Call("Hello.SayHello", "我是客户端的曾国清", &reply)if err2 != nil {fmt.Println(err2)}// 4, 获取微服务返回的数据 查看返回结果fmt.Println(reply)
}
以下是一个goods实现简单RPC服务实践
1, 服务端 server\goods\main.go
package mainimport ("fmt""net""net/rpc"
)// 创建远程调用的函数,函数一般是放在结构体里面的
type Goods struct{}// AddGoods 参数对应的结构体
// 定义一个结构体,用于接收客户端传递过来的参数
type AddGoodsReq struct {Id intTitle stringPrice float64Content string
}// 定义一个结构体,用于返回客户端的结果
type AddGoodsRes struct {Success boolMessage string
}// GetGoods 参数对应的结构体
// 定义一个结构体,用于接收客户端传递过来的参数
type GetGoodsReq struct {Id int
}// 定义一个结构体,用于返回客户端的结果
type GetGoodsRes struct {Id intTitle stringPrice float64Content string
}// 定义一个方法,该方法可以被远程调用
func (Goods) AddGoods(req AddGoodsReq, res *AddGoodsRes) error {// 1, 执行增加 模拟 商品的操作,这里就直接打印出来看看参数是什么样子的fmt.Printf("%#v\n", req)// 2, 返回增加的结果,这里直接返回nil表示成功*res = AddGoodsRes{Success: true,Message: "增加商品成功",}return nil
}// 定义一个获取数据的方法,该方法可以被远程调用
func (Goods) GetGoods(req GetGoodsReq, res *GetGoodsRes) error {// 1, 执行增加 模拟 商品的操作,这里就直接打印出来看看参数是什么样子的fmt.Printf("%#v\n", req)// 2, 返回增加的结果,这里直接返回nil表示成功*res = GetGoodsRes{Id: 11,Title: "小米手机",Price: 2888.0,Content: "小米手机真好用号漂亮的",}return nil
}
func main() {// 1, 注册 RPC 服务err1 := rpc.RegisterName("goods", new(Goods))if err1 != nil {fmt.Println("注册服务失败")}// 2, 监听端口Listener, err2 := net.Listen("tcp", "127.0.0.1:8020")if err2 != nil {fmt.Println("监听端口失败")}// 3, 关闭监听端口defer Listener.Close()for {// 4, 监听客户端连接,等待客户端的连接请求fmt.Println("准备接受客户端的连接请求...")conn, err3 := Listener.Accept()if err3 != nil {fmt.Println("接受客户端连接失败")}// 5, 处理客户端的连接请求rpc.ServeConn(conn) // 处理客户端的连接请求,阻塞等待下一个连接请求}
}2,客户端 client\goods\main.go
package mainimport ("fmt""net/rpc"
)// AddGoods 参数对应的结构体
// 定义一个结构体,用于接收客户端传递过来的参数
type AddGoodsReq struct {Id intTitle stringPrice float64Content string
}// 定义一个结构体,用于返回客户端的结果
type AddGoodsRes struct {Success boolMessage string
}// GetGoods 参数对应的结构体
// 定义一个结构体,用于接收客户端传递过来的参数
type GetGoodsReq struct {Id int
}// 定义一个结构体,用于返回客户端的结果
type GetGoodsRes struct {Id intTitle stringPrice float64Content string
}func main() {// 1,用 rpc.Dial和rpc 微服务端建立连接,然后调用 rpc 微服务端的方法。conn, err1 := rpc.Dial("tcp", "127.0.0.1:8020") // 这里的参数要和服务器端的一致if err1 != nil {fmt.Println(err1)}// 2, 当连接建立后,需要关闭它。否则会造成资源泄露。所以这里使用了 defer 关键字来延迟执行 Close 方法。defer conn.Close()// 注意:这里的 goods.AddGoods 指的是微服务端的方法名,要和微服务端的注册方法一致。// 3, 调用远程函数AddGoodsResvar reply AddGoodsRes/*1,第一个参数 hello.SayHello hello表示服务名称 SayHello方法名称2,第二个参数 给服务端的req传递数据3,第三个参数 需要传入地址 获取微服务端返回的数据*/err2 := conn.Call("goods.AddGoods", AddGoodsReq{Id: 1,Title: "小米手机",Price: 2999.0,Content: "小米手机真好用",}, &reply)if err2 != nil {fmt.Println(err2)}// 4, 获取微服务返回的数据 查看返回结果fmt.Printf("%#v\n", reply)// 5, 调用远程函数GetGoodsResvar goodsData GetGoodsReserr3 := conn.Call("goods.GetGoods", GetGoodsReq{Id: 11,}, &goodsData)if err3 != nil {fmt.Println(err3)}// 6, 获取微服务返回的数据 查看返回结果fmt.Printf("%#v\n", goodsData)
}
四,ProtoBuf认识与使用
4.1 protobuf简介
Protobuf是Protocol Buffers的简称,它是Google公司开发的一种数据描述语言,是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或RPC数据交换格式。可用于通讯协议,数据存储等领域的语言无关,平台无关,可扩展的序列化结构数据格式,他是一种灵活,高效,自动化的机制,用于序列化结构化数据,对比于XML和JSON,他更小,更快,更简单。总之他是微服务中需要使用的东西。
Protobuf刚开源时的定位类似于XML,JSON等数据描述语言,通过附带工具生成代码并实现将结构化数据序列化的功能。这里我们更关注的是Protobuf作为接口规范的描述语言,可以作为设计安全的跨语言RPC接口的基础工具。
需要了解两点
1,protobuf是类似与json一样的数据描述语言(数据格式)
2,protobuf非常适合于RPC数据交互格式
接着我们来看一下protobuf的优势和劣势:
优势:
1:序列化后体积相比json和XML很小,适合网络传输
相关文章:
go-micro
一,课程介绍 1,主讲老师: 大地 2,合作网站: www.itying.com 3,我的专栏: https://www.itying.com/category_Z9-b0.html 4,必备基础:学习本教程要有golang和go web基础 5,大地老师Golang入门实战系列教…...
SVN把英文换中文
原文链接:SVN设置成中文版本 都是英文,换中文 Tortoise SVN 安装汉化教程(乌龟SVN) https://pan.quark.cn/s/cb6f2eee3f90 下载中文包...
Ubuntu 下 nginx-1.24.0 源码分析 - ngx_atoi 函数
ngx_atoi 声明在 src/core/ngx_string.h ngx_int_t ngx_atoi(u_char *line, size_t n); 定义在 src/core/ngx_string.c ngx_int_t ngx_atoi(u_char *line, size_t n) {ngx_int_t value, cutoff, cutlim;if (n 0) {return NGX_ERROR;}cutoff NGX_MAX_INT_T_VALUE / 10;cutlim…...
DeepSeek R1/V3满血版——在线体验与API调用
前言:在人工智能的大模型发展进程中,每一次新模型的亮相都宛如一颗投入湖面的石子,激起层层波澜。如今,DeepSeek R1/V3 满血版强势登场,为大模型应用领域带来了全新的活力与变革。 本文不但介绍在线体验 DeepSeek R1/…...
深度学习技术文章质量提升指南(基于CSDN评分算法优化)
一、质量缺陷诊断(基于CSDN质量分V5.0算法) 根据1提供的评分框架,当前文章可能存在的质量短板: 技术深度不足:缺乏具体模型实现细节与数学推导结构完整性缺失:未形成"理论-实践-应用"完整闭环代…...
力扣-回溯-37 解数独
思路 双层递归,而且在传递参数使用&的好处是不用在复制一次样本,浪费时间 class Solution { public:bool isVaild(vector<vector<char>> &board, int row, int cal, char val){for(int i 0; i < 9;i){if(board[row][i] val) …...
极简入门,本地部署dify低代码平台构建AI Agent大模型全流程(使用教程、微案例、配置详解、架构图解析)
文章目录 一、环境搭建1.1 安装VMware-workstationCentOS7.91.2 安装宝塔1.3 安装docker及改镜像、安装dify1.4 配置模型供应商 二、dify快速上手体验2.1 知识库2.2 微案例:基于知识库的助手 三、dify知识库配置详解3.1 分片策略3.2 父子分段3.3 索引方法3.4 检索结…...
ssh与服务器
目录 前言: 一、密码连接 二、密钥对连接 1.将公钥放在服务器 2.ssh连接 三、禁用密码 1.进入服务器/etc/ssh文件夹 2.打开sshd_config文件,进行如下配置 3.有可能还需要更改其他文件夹 4.重启ssh服务 四、config 五.ssh与github 1.本地创建…...
C++ bind基本使用
std::bind 是 C11 引入的一个函数模板,用于创建一个新的可调用对象,该对象可以调用某个函数或成员函数,并将一些参数绑定为固定值。通过 std::bind,你可以创建一个新的函数对象,这个对象可以接受剩余的参数,…...
【GPT】从GPT1到GPT3
every blog every motto: Although the world is full of suffering, it is full also of the overcoming of it 0. 前言 从GPT1 到GPT3 1. GPT1 论文: https://s3-us-west-2.amazonaws.com/openai-assets/research-covers/language-unsupervised/lan…...
Java IO 设计模式总结
装饰器模式 装饰器(Decorator)模式 可以在不改变原有对象的情况下拓展其功能。 装饰器模式通过组合替代继承来扩展原始类的功能,在一些继承关系比较复杂的场景(IO 这一场景各种类的继承关系就比较复杂)更加实用。 对…...
js版本ES6、ES7、ES8、ES9、ES10、ES11、ES12、ES13、ES14[2023]新特性
ES全称ECMAScript,ECMAScript是ECMA制定的标准化脚本语言,本文讲述Javascript[ECMAScript]版本ES6、ES7、ES8、ES9、ES10、ES11、ES12、ES13、ES14[2023]的新特性,帮助朋友们更好的熟悉和使用Javascript ES5 1.严格模式 use strict2.Object getPrototypeOf,返回一个对象的原…...
基于ffmpeg+openGL ES实现的视频编辑工具-解码(四)
在开发视频编辑工具时,预览功能是基石,它涵盖视频、图片以及音频播放,而视频解码则是实现视频预览及后续编辑操作的关键环节。本文聚焦于基于 FFmpeg 实现视频解码的过程,详细阐述开发中遭遇的痛点、对应的解决方式,以及核心代码的运作原理。 一、开发背景与目标 视频编…...
机器学习:决策树
1. 初步概念 决策树是一种基于分裂特征的机器学习方法,用于分类和回归任务。它通过将数据按特征值进行分割,最终做出预测。与线性模型不同,决策树能够自动识别重要的特征,并根据数据情况生成复杂的决策规则。 2. 决策树的核心思想 决策树的核心思想在于选择一个特征作为…...
@media 的常用场景与示例
media 的常用场景与示例 1. 基本概念2. 常用场景2.1 不同屏幕宽度的布局调整2.2 隐藏或显示元素2.3 字体大小调整2.4 图片大小调整2.5 高度调整2.6 颜色调整2.7 鼠标悬停效果 3. 常用示例3.1 基本响应式布局3.2 隐藏侧边栏3.3 字体大小和图片大小 4. 总结 在现代网页设计中&…...
深入浅出:基于SpringBoot和JWT的后端鉴权系统设计与实现
文章目录 什么是鉴权系统定义与作用主要组成部分工作原理常用技术和框架 基于SpringBoot JWT的鉴权系统设计与实现指南前言技术对比令牌技术JWT令牌实现全流程1. **依赖引入**2. **JWT 工具类**3. **JWT 拦截器(Interceptor)** 4. **拦截器注册**5. **登…...
怎麼利用靜態ISP住宅代理在指紋流覽器中管理社媒帳號?
靜態ISP住宅代理是一種基於真實住宅IP的代理服務。這類代理IP通常由互聯網服務提供商(ISP)分配,具有非常高的真實性,與普通數據中心代理相比,更不容易被平臺檢測到為“虛假IP”或“代理IP”,靜態ISP住宅代理…...
DeepSeek掘金——SpringBoot 调用 DeepSeek API 快速实现应用开发
Spring Boot 实现 DeepSeek API 调用 1. 项目依赖 在 pom.xml 中添加以下依赖: <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency>&l…...
解决本地模拟IP的DHCP冲突问题
解决 DHCP 冲突导致的多 IP 绑定失效问题 前言 续接上一篇在本机上模拟IP地址。 在实际操作中,如果本机原有 IP(如 192.168.2.7)是通过 DHCP 自动获取的,直接添加新 IP(如 10.0.11.11)可能会导致 DHCP 服…...
Git LFS介绍(Large File Storage)大文件扩展,将大文件存储在外部存储,仓库中只记录文件的元数据(大文件的指针,类似一个小的占位符文件)
文章目录 LFS的功能?如何使用LFS?将大文件存储在外部系统是什么意思?具体是如何运作的?为什么要这样做? 对开发者的影响?1. **性能和效率**2. **协作体验**3. **版本管理差异**4. **额外的工具和配置** LFS…...
数据中心储能蓄电池状态监测管理系统 组成架构介绍
安科瑞刘鸿鹏 摘要 随着数据中心对供电可靠性要求的提高,蓄电池储能系统成为关键的后备电源。本文探讨了蓄电池监测系统在数据中心储能系统中的重要性,分析了ABAT系列蓄电池在线监测系统的功能、技术特点及其应用优势。通过蓄电池监测系统的实施&#…...
三甲医院网络架构与安全建设实战
一、设计目标 实现医疗业务网/卫生专网/互联网三网隔离 满足等保2.0三级合规要求 保障PACS影像系统低时延传输 实现医疗物联网统一接入管控 二、全网拓扑架构 三、网络分区与安全设计 IP/VLAN规划表 核心业务配置(华为CE6865) interface 100G…...
如何在 React 中测试高阶组件?
在 React 中测试高阶组件可以采用多种策略,以下是常见的测试方法: 1. 测试高阶组件返回的组件 高阶组件本身是一个函数,它返回一个新的组件。因此,可以通过测试这个返回的组件来间接测试高阶组件的功能。通常使用 Jest 作为测试…...
INA219电流、电压、功率测量芯片应用
INA219电流、电压、功率测量芯片应用 简述芯片引脚应用电路寄存器驱动代码 简述 INA219是一款由德州仪器(Texas Instruments)生产的高精度电流/功率监测芯片,广泛应用于电池监控、电源管理等需要精确电流和功率测量的应用中。该芯片通…...
深入解析设计模式之工厂模式
深入解析设计模式之工厂模式 在软件开发的复杂体系中,设计模式作为解决常见问题的有效方案,为开发者提供了强大的工具。工厂模式作为一种广泛应用的创建型设计模式,专注于对象的创建过程,通过巧妙的设计,将对象的创建…...
ollama修改监听ip: 0.0.0.0
确认Ollama绑定IP地址 默认情况下,Ollama可能仅监听本地回环地址(127.0.0.1)。要允许外部访问,需将其配置为监听所有IP(0.0.0.0)或指定IP(如10…19)。 修改启动命令(推荐…...
.NET MVC实现电影票管理
.NET MVC(Model-View-Controller)是微软推出的基于 Model-View-Controller 设计模式的 Web 应用框架,属于 ASP.NET Core 的重要组成部分。其核心目标是通过清晰的分层架构实现 高内聚、低耦合 的开发模式,适用于构建可扩展的企业级…...
FPGA DSP:Vivado 中带有 DDS 的 FIR 滤波器
本文使用 DDS 生成三个信号,并在 Vivado 中实现低通滤波器。低通滤波器将滤除相关信号。 介绍 用DDS生成三个信号,并在Vivado中实现低通滤波器。低通滤波器将滤除较快的信号。 本文分为几个主要部分: 信号生成:展示如何使用DDS&am…...
大数据组件(四)快速入门实时数据湖存储系统Apache Paimon(2)
Paimon的下载及安装,并且了解了主键表的引擎以及changelog-producer的含义参考: 大数据组件(四)快速入门实时数据湖存储系统Apache Paimon(1) 利用Paimon表做lookup join,集成mysql cdc等参考: 大数据组件(四)快速入门实时数据…...
vue3父子组件props传值,defineprops怎么用?(组合式)
目录 1.基础用法 2.使用解构赋值的方式定义props 3.使用toRefs的方式解构props (1).通过ref响应式变量,修改对象本身不会触发响应式 1.基础用法 父组件通过在子组件上绑定子组件中定义的props(:props“”)传递数据给子组件 <!-- 父组件…...
Linux /etc/fstab文件详解:自动挂载配置指南(中英双语)
Linux /etc/fstab 文件详解:自动挂载配置指南 在 Linux 系统中,/etc/fstab(File System Table)是一个至关重要的配置文件,它用于定义系统开机时自动挂载的文件系统。如果你想让磁盘分区、远程存储(如 NFS&…...
Test the complete case
Test the complete case python写的一段 由pytest测试框架/allure报告框架/parameters数据驱动组成的完整案例代码 目录结构 project/ ├── test_cases/ │ ├── __init__.py │ └── test_math_operations.py # 测试用例 ├── test_data/ │ └── math_dat…...
装win10系统提示“windows无法安装到这个磁盘,选中的磁盘采用GPT分区形式”解决方法
问题描述 我们在u盘安装原版win10 iso镜像时,发现在选择硬盘时提示了“windows无法安装到这个磁盘,选中的磁盘采用GPT分区形式”,直接导致了无法继续安装下去。出现这种情况要怎么解决呢? 原因分析: 当您在安装Windows操作系统…...
【pytest-jira】自动化用例结合jira初版集成思路
【pytest】编写自动化测试用例命名规范README 【python】连接Jira获取token以及jira对象 【python】解析自动化脚本文件并按照测试周期存储记录 【python】向Jira推送自动化用例执行成功 【python】向Jira测试计划下,附件中增加html测试报告 以下内容主要是介绍jira…...
PHP 会话(Session)实现用户登陆功能
Cookie是一种在客户端和服务器之间传递数据的机制。它是由服务器发送给客户端的小型文本文件,保存在客户端的浏览器中。每当浏览器向同一服务器发送请求时,它会自动将相关的Cookie信息包含在请求中,以便服务器可以使用这些信息来提供个性化的…...
大模型安全问题详解(攻击技术、红队测试与安全漏洞)
文章目录 大模型攻击技术提示注入攻击(Prompt Injection)数据投毒攻击(Data Poisoning)模型克隆攻击(Model Cloning)拒绝服务攻击(DoS)和拒绝钱包攻击(DoW)插…...
【愚公系列】《鸿蒙原生应用开发从零基础到多实战》002-TypeScript 类型系统详解
标题详情作者简介愚公搬代码头衔华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,CSDN商业化专家,阿里云专家博主,阿里云签约作者,腾讯云优秀博主&…...
C# 将非托管Dll嵌入exe中(一种实现方法)
一、环境准备 电脑系统:Windows 10 专业版 20H2 IDE:Microsoft Visual Studio Professional 2022 (64 位) - Current 版本 17.11.4 其他: 二、测试目的 将基于C++创建DLL库,封装到C#生成的exe中。 一般C++创建的库,在C#中使用,都是采用DllImport导入的,且要求库处…...
c sharp 特性详解
文章目录 一、特性基础用法二、常见的内置特性三、自定义特性四、通过反射读取特性五、实际应用场景六、练习 一、特性基础用法 什么是特性? 特性是一种继承System.Attribute类,用于标记代码元素 特性的语法: [AttributeName(Parameter1, P…...
Langchain vs. LlamaIndex:哪个在集成MongoDB并分析资产负债表时效果更好?
Langchain vs. LlamaIndex:哪个在集成MongoDB并分析资产负债表时效果更好? 随着大语言模型(LLM)在实际应用中的普及,许多开发者开始寻求能够帮助他们更高效地开发基于语言模型的应用框架。在众多框架中,La…...
MySQL日常维护工具------备份
MySQL日常维护工具-备份 一、MySQL字符集 (一)字符集介绍 字符(Character)是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。字符集(Character set)是多个字符的集合,字符集种类较多,每个字符集…...
硬核技术组合!用 DeepSeek R1、Ollama、Docker、RAGFlow 打造专属本地知识库
文章目录 一、引言二、安装Ollama部署DeepSeekR1三、安装Docker四、安装使用RAGFlow4.1 系统架构4.2 部署流程4.3 使用RAGFlow4.4 在RAGFlow中新增模型4.5 创建知识库4.6 创建私人助理使用RGA 一、引言 本地部署DeepSeek R1 Ollama RAGFlow构建个人知识库,通过将…...
[VSCode]彻底卸载和重装,并搭建Java开发环境
VSCode彻底卸载 由于当初是朋友帮忙装的,所以准备卸载,自己装一遍 从控制面板找到 vscode 将其卸载。 此时仅仅是删除了应用软件 删除安装插件 在图示路径中找到 .vscode 文件夹,将其删除,即可彻底清除安装的插件 C:\Users\user\.vscode …...
Scrum方法论指导下的Deepseek R1医疗AI部署开发
一、引言 1.1 研究背景与意义 在当今数智化时代,软件开发方法论对于项目的成功实施起着举足轻重的作用。Scrum 作为一种广泛应用的敏捷开发方法论,以其迭代式开发、快速反馈和高效协作的特点,在软件开发领域占据了重要地位。自 20 世纪 90 …...
政安晨的AI大模型训练实践 九 - 熟悉LLaMA Factory的详细参数含义-基本概念理解一下
政安晨的个人主页:政安晨 欢迎 👍点赞✍评论⭐收藏 希望政安晨的博客能够对您有所裨益,如有不足之处,欢迎在评论区提出指正! 小伙伴铁子们,上手先熟悉起来训练工具的每一个参数,很重要。 参照我…...
保姆级教程 | Office-Word中图目录制作及不显示图注引文的方法
背景 由于毕业论文的格式修改需要(没错,我终于要拿下PhD了。差不多四个月没更新,主要是①根据处理完的数据完成小论文撰写;②找工作...③完成学位论文的撰写。因而对建模和数据处理的需求不高,对有些时隔久远的博文具…...
Linux lsblk 命令详解:查看磁盘和分区信息 (中英双语)
Linux lsblk 命令详解:查看磁盘和分区信息 在 Linux 系统中,管理磁盘设备和分区是日常运维工作的重要部分。而 lsblk 命令是一个强大的工具,它用于列出系统中的块设备(block devices)信息,可以帮助我们快速…...
使用API有效率地管理Dynadot域名,为域名部署DNS安全拓展(DNSSEC)
关于Dynadot Dynadot是通过ICANN认证的域名注册商,自2002年成立以来,服务于全球108个国家和地区的客户,为数以万计的客户提供简洁,优惠,安全的域名注册以及管理服务。 Dynadot平台操作教程索引(包括域名邮…...
前后端项目部署服务器(传统部署和Docker部署)
内外网 开发环境连外网(8.140.26.187),测试/生产环境连内网(172.20.59.17) 内外网地址不同,但指定的库是同一个 内网IP地址范围包括: 10.0.0.0 到 10.255.255.255172.16.0.0 到 172.31.2551…...
深入HBase——核心组件
引入 通过上一篇对HBase核心算法和数据结构的梳理,我们对于其底层设计有了更多理解。现在我们从引入篇里面提到的HBase架构出发,去看看其中不同组件是如何设计与实现。 核心组件 首先,需要提到的就是HBase架构中会依赖到的Zookeeper和HDFS。…...