C#系列-C#微服务框架(12)

在C#中,有多个微服务框架可供选择,每个框架都提供了构建、部署和管理微服务的不同方法和工具。以下是一些流行的C#微服务框架: Steeltoe Steeltoe 是一个用于.NET Core的微服务工具集,它提供了在云原生环境中运行微服务所需的服务发现和配置管理功能。Steeltoe 与Spring Cloud兼容,因此它可以帮助.NET开发人员更容易地迁移到微服务架构。MassTransit MassTransit 是一个用于.NET的微服务消息传递框架,它支持多种消息传递协议(如RabbitMQ, Azure Service Bus, Amazon SQS等)。使用MassTransit,开发人员可以构建分布式系统,通过消息传递来解耦服务之间的通信。Orchard Core Orchard Core 是一个开源的、模块化的、多租户CMS(内容管理系统)和Web应用程序框架,使用.NET Core构建。虽然它主要用于构建Web应用程序,但也可以用作微服务架构中的一部分,尤其是当需要快速构建和部署模块化服务时。ASP.NET Core ASP.NET Core 是一个高性能、开源的Web框架,用于构建现代化、云优化的Web应用程序。ASP.NET Core 提供了轻量级、模块化的设计,以及对微服务架构的支持,包括服务发现、健康检查、配置管理等。Ocelot Ocelot 是一个用.NET Core构建的API网关,它允许开发人员管理微服务架构中的HTTP请求路由、限流、熔断、认证和授权等功能。Polly Polly 是一个弹性和瞬态故障处理库,用于.NET应用程序。它可以帮助开发人员实现重试、熔断、超时、故障处理策略等,从而提高微服务的可靠性和韧性。Microservices.AspNetCore.Template 这是一个基于ASP.NET Core的微服务模板,它提供了一套完整的微服务基础设施,包括服务发现、配置管理、健康检查、分布式跟踪等。 在选择C#微服务框架时,您应该考虑您的具体需求,如服务的复杂性、对特定云平台的依赖、团队的技术栈和经验,以及框架的社区支持和维护情况。同时,也要确保所选框架能够与您的CI/CD流程、监控和日志记录工具集成。

Excel·VBA收益最大的运输路线

看到一个帖子《excel吧-找出运输收益最大的路线》,根据表中的起点和终点构成的路线,在一定的本金和时间限制下,获取收益最大的运输路线 采用类似《Excel·VBA数组排列函数》,尾数循环结束后,对之前的位置进位的方式,获取遍历所有可能路线,最终得到收益最大的运输路线 以下代码中内层第1个do循环的作用是,路线一直向前延伸,直到剩余时间不足;内层第2个do循环的作用是,在一条路线延伸到底后,对最后一个起点的其他终点进行计算,判断是否为收益更大的路线;内层第3个do循环的作用是,当一条路线延伸到底后,且路线的最后一个终点是其起点的最后一个终点时,对其起点进行递增为下一个起点,且如果路线上的终点都为其起点的最后一个终点时,一直向前递增 以下代码运用了Match函数《Excel·VBA多行多列数据简单汇总》,可查找数值在数组中的位置,返回的index从1开始计数,而在以下代码中查找的都是字典键数组从0开始计数,因此代码中For i = y To UBound(dk)就是从被查找的字符的下一个位置开始循环(VBA字典键顺序为写入字典的顺序) Sub 运输收益最大路线() 'res数组记录输出结果共100行3列(总收益,剩余时间,路线),b记录当前路线,mrr记录每次终点的金额,trr记录剩余时间 Dim arr, mm, tt, min_t, dict As Object, res(1 To 100, 1 To 3), r&, i&, j&, x&, y&, s$, m, t arr = [a1].CurrentRegion: mm = 50000: tt = 1200 '初始总本金、总耗时 min_t = WorksheetFunction.Min(Application.index(arr, , 5)) '最小耗时 Set dict = CreateObject("scripting.dictionary"): tm = Timer res(1, 1) = "总收益": res(1, 2) = "剩余时间": res(1, 3) = "路线": res(2, 1) = 0 For i = 2 To UBound(arr) '字典嵌套字典,记录起止点对应(单位成本,单位收益,耗时) If Not dict.

VS2022 C++ MFC LINK2005 LINK1169

VS2022 C++ MFC LINK2005 LINK1169 简单地说就是重定义,相同的东西定义/编译了多次 我参考了下面的,但是都不行: https://blog.csdn.net/zhaoyong26/article/details/84635383 https://blog.csdn.net/Xiuhua2017/article/details/109728879 https://blog.csdn.net/qq_40674300/article/details/115337002 https://blog.csdn.net/qq_64319050/article/details/122931804 后来发现,把有问题的include放到cpp而不是h文件,并且放在其中所有include的最后就好了,很玄学 想明白了一点点,似乎是因为我新加的include有#pragma once声明,所以放到后面没问题,反过来就不行了,其他头文件不一定有#pragma once 所以建议所有头文件开头加上#pragma once,或者善用#ifndef、#define和#endif

Blazor Wasm 身份验证和授权之 OpenID 与 OAuth2

目录: OpenID 与 OAuth2 基础知识Blazor wasm Google 登录Blazor wasm Gitee 码云登录Blazor SSR/WASM IDS/OIDC 单点登录授权实例1-建立和配置IDS身份验证服务Blazor SSR/WASM IDS/OIDC 单点登录授权实例2-登录信息组件wasmBlazor SSR/WASM IDS/OIDC 单点登录授权实例3-服务端管理组件Blazor SSR/WASM IDS/OIDC 单点登录授权实例4 - 部署服务端/独立WASM端授权Blazor SSR/WASM IDS/OIDC 单点登录授权实例5 - Blazor hybird app 端授权Blazor SSR/WASM IDS/OIDC 单点登录授权实例5 - Winform 端授权 源码 b21_OAuth_Gitee 相关基础知识 OpenID 与 OAuth2 参考阅读 https://auth0.com/docs/authenticate/protocols/openid-connect-protocol#what-is-openid-connect-oidc- OpenID 连接协议 什么是 OpenID Connect (OIDC)? OpenID Connect (OIDC) 是构建在OAuth 2.0框架之上的身份层。它允许第三方应用程序验证最终用户的身份并获取基本的用户配置文件信息。OIDC 使用JSON Web 令牌(JWT),您可以使用符合 OAuth 2.0 规范的流获取该令牌。看看我们的 OIDC 手册 更多细节。 OpenID 与 OAuth2

Unity入门学习

目录 Unity环境搭建Unity引擎是什么软件下载和安装工程文件夹 Unity界面基础Scene场景和Hierarchy层级窗口Game游戏和Project工程Inspector和Console工具栏和父子关系 Unity工作原理反射机制和游戏场景预设体和资源包的导入导出 Unity脚本基础脚本基本规则生命周期函数Inspector窗口可编辑的变量MonoBehavior中的重要内容 Unity重要组件和API最小单位GameObjectGameObject中的成员变量GameObject静态方法GameObject中的成员方法 时间相关Time必不可少的Transform--位置和位移Vector3基础位置 角度和旋转缩放和看向父子关系坐标转换输入相关Input鼠标键盘输入触摸手柄陀螺仪 屏幕相关Screen必不可少的摄像机CameraCamera可编辑参数Camera代码相关 核心系统光源系统基础光源组件光面板相关 物理系统之碰撞检测刚体碰撞器物理材质碰撞检测函数刚体加力 音效系统音频文件导入音频源和音频监听脚本代码控制音频源麦克风输入相关 Unity环境搭建 Unity编辑器使用中文语言包/汉化流程演示 Unity引擎是什么 什么时游戏引擎? 游戏引擎是指一些已编写好的可编辑电脑游戏系统或者一些交互式实时图像应用程序的核心组件。这些系统为游戏设计者提供各种编写游戏所需的各种工具,其目的在于让游戏设计者能容易和快速地做出游戏程序而不用从零开始。 游戏引擎对于我们的意义 1、降低做游戏的门槛 2、提升游戏开发的效率 如何降低开发门槛? 以前做游戏:物理、数学、计算机图形学、计算机原理、操作系统等等与多种程序语言。 现在做游戏:游戏引擎的使用和一种程序语言。 如何提升开发效率? 以前做游戏:图形渲染、物理系统、离子系统、寻路系统、多平台开发等等与上层逻辑。 现在做游戏:游戏引擎和上层逻辑。 如何学习游戏引擎? 1、学习引擎用于开发的主要语言。 2、学习引擎的软件操作。 3、学习引擎提供的API和核心系统 如何学习Unity? Unity相当于就是一个游戏开发工具包,我们只要学会使用工具包中的各个工具即可,而使用这些工具的媒介就是我们已经学习完毕的C#程序语言。 软件下载和安装 软件下载 Unity官网(访问较慢) 中国官网 注册一个账号,然后下载。 版本选择 1、长期支持版:又称LTS版,适用于希望长时间保持稳定版本的用户。 2、补丁程序版:bug修复版本。 3、Beta版本:包含还未正式发布的新功能。 最新的不是最好的!不管是学习还是开发,都建议使用最稳定的版本。 注意: 一般情况下,Unity版本向下兼容,高版本开低版本工程,问题不大,低版本开高版本工程,会出现兼容问题。 关于版本号: 大版本号.小版本号.bug处理版本号(版本类型后缀) 例如: 2019.4.17f1 2017.2.4p1 2020.2.0b14 软件安装 1、点击“从Unity Hub下载” 2、获取许可证 ①打开“偏好设置” ②点击“许可证”–>“添加许可证”–>“获取免费的个人版许可证”。 ③在项目中为自己的项目选择合适位置。 ④安装编辑器 勾选 工程文件夹 Assets: 工程资源文件夹(美术资源,脚本等) Library: 库文件夹(Unity自动生成管理) Logs: 日志文件夹,记录特殊信息(Unity自动生成管理) obj: 编译产生中间文件(Unity自动生成管理) Packages: 包配置信息(Unity自动生成管理)

K8S之运用亲和性设置Pod的调度约束

亲和性 Node节点亲和性硬亲和实践软亲和性实践 Pod节点亲和性和反亲和性pod亲和性硬亲和实践 pod反亲和性 Pod 的yaml文件里 spec 字段中包含一个 affinity 字段,使用一组亲和性调度规则,指定pod的调度约束。 kubectl explain pods.spec.affinity 配置说明 nodeAffinity: node节点亲和性,pod倾向于哪个nodepodAffinity: pod亲和性,pod倾向于哪个podpodAntiAffinity: pod的反亲和性,pod排斥于哪个pod Node节点亲和性 Node节点亲和性 是针对 pod和node 的关系,Pod调度到node节点的时候匹配的条件 node节点亲和性调度字段:nodeAffinity 看nodeAffinity下的配置字段 kubectl explain pods.spec.affinity.nodeAffinity preferredDuringSchedulingIgnoredDuringExecution 表示有节点尽量满足这个位置定义的亲和性,这不是一个必须的条件,软亲和性requiredDuringSchedulingIgnoredDuringExecution 表示必须有节点满足这个位置定义的亲和性,这是个硬性条件,硬亲和性 硬亲和实践 使用requiredDuringSchedulingIgnoredDuringExecution硬亲和性 Node节点硬亲和性选择匹配方式有2种: matchFields: 匹配字段的matchExpressions:匹配表达式的 (用的多) 对matchExpressions做进一步解读 matchExpressions——匹配表达式的写法: kubectl explain pods.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms.matchExpressions 字段配置: key:匹配节点标签的KEY(必填)operator:表示键与一组值的关系(必填),可选的枚举值如下: In (包含)NotIn(不包含)Exists (存在)DoesNotExist (不存在)Gt (大于)Lt (小于) values:给定值 示例 :把pod调度到集群中 拥有zone标签 并且值是foo或者bar的node节点上 创建pod资源文件 vim pod-nodeaffinity-demo.yaml apiVersion: v1 kind: Pod metadata: name: pod-node-affinity-demo namespace: default spec: affinity: # 设置亲和性调度规则 nodeAffinity: # 设置node亲和性 requiredDuringSchedulingIgnoredDuringExecution: # 使用硬亲和性 nodeSelectorTerms: # 配置节点选择器规则 - matchExpressions: # 匹配表达式的 - key: zone # 节点标签的key operator: In # 使用表达式为包含 values: # 包含的值有(foo或者bar) - foo - bar containers: - name: myapp image: docker.

Spinnaker多云持续交付平台: 部署Minio存储服务

目录 一、实验 1.环境 2.K8S storage节点部署NFS 3.K8S 动态创建PV 4.K8S master节点部署HELM3 4.K8S master节点部署Minio存储服务(第一种方式安装) 5.Minio客户端安装MC命令 6.K8S master节点使用Docker 部署Minio存储服务(第二种方式安装) 二、问题 1.K8S无法删除pv,pvc问题 2.minio 部署模式有哪些 3.pod Readiness探针与Liveness探针失败 4. 添加 MinIO服务失败 5.docker创建容器失败 6.K8S如何快速创建Minio存储 一、实验 1.环境 (1)主机 表1 主机 主机架构版本IP备注master1K8S master节点1.20.6192.168.204.180 node1K8S node节点1.20.6192.168.204.181node2K8S node节点1.20.6192.168.204.182stor01 nfs存储节点 192.168.204.177 (2)查看集群状态 2.K8S storage节点部署NFS (1)安装配置nfs服务 #在stor01(192.168.204.183)节点上安装nfs,并配置nfs服务 mkdir /opt/k8s chmod 777 /opt/k8s/ yum -y install nfs-utils rpcbind #给204网段用户赋予读写权限、同步内容、不压缩共享对象root用户权限 vim /etc/exports /opt/k8s 192.168.204.0/24(rw,sync,no_root_squash) #首次安装 systemctl start rpcbind nfs #非首次安装 systemctl restart rpcbind systemctl restart nfs #监听服务 ss -antp | grep rpcbind #查看共享 exportfs -arv showmount -e #所有节点配置hosts映射,或者配置DNS解析 echo '192.

Spark MLlib

目录 一、Spark MLlib简介 (一)什么是机器学习 (二)基于大数据的机器学习 (三)Spark机器学习库MLlib 二、机器学习流水线 (一)机器学习流水线概念 (二)流水线工作过程 (三)构建一个机器学习流水线 三、特征提取和转换 (一)特征提取:TF-IDF (二)特征转换:标签和索引的转化 四、分类与回归 (一)逻辑斯蒂回归分类器 (二)决策树分类器 一、Spark MLlib简介 (一)什么是机器学习 机器学习可以看做是一门人工智能的科学,该领域的主要研究对象是人工智能。机器学习利用数据或以往的经验,以此优化计算机程序的性能标准。 机器学习强调三个关键词:算法、经验、性能,其处理过程如上图所示。在数据的基础上,通过算法构建出模型并对模型进行评估。评估的性能如果达到要求,就用该模型来测试其他的数据;如果达不到要求,就要调整算法来重新建立模型,再次进行评估。如此循环往复,最终获得满意的经验来处理其他的数据。 (二)基于大数据的机器学习 传统的机器学习算法,由于技术和单机存储的限制,只能在少量数据上使用,因此,传统的统计、机器学习算法依赖于数据抽样。但是在实际应用中,往往很难做到样本随机,导致学习的模型不是很准确,测试数据的效果也不太好。随着HDFS等分布式文件系统的出现,我们可以对海量数据进行存储和管理,并利用MapReduce框架在全量数据上进行机器学习,这在一定程度上解决了统计随机性的问题,提高了机器学习的精度。但是,MapReduce自身存在缺陷,延迟高,磁盘开销大,无法高效支持迭代计算,这使MapReduce无法很好地实现分布式机器学习算法。这是因为在通常情况下,机器学习算法参数学习的过程都是迭代计算,本次计算的结果要作为下- 次迭代的输入。在这个过程中,MapReduce只能把中间结果存储到磁盘中,然后在下一次计算的时候重新从磁盘读取数据;对于迭代频发的算法,这是制约其性能的瓶颈。相比而言,Spark 立足于内存计算,天然地适用于迭代式计算,能很好地与机器学习算法相匹配。这也是近年来Spark平台流行的重要原因之一,业界的很多业务纷纷从Hadoop平台转向Spark平台。 基于大数据的机器学习,需要处理全量数据并进行大量的迭代计算,这就要求机器学习平台具备强大的处理能力和分布式计算能力。然而,对于普通开发者来说,实现一个分布式机器学习算法,仍然是一件极具挑战性的工作。为此,Spark提供了一个基于海量数据的机器学习库,它提供了常用机器学习算法的分布式实现,对于开发者而言,只需要具有Spark编程基础,并且了解机器学习算法的基本原理和方法中相关参数的含义,就可以轻松地通过调用相应的API,来实现基于海量数据的机器学习过程。同时,spark-shell也提供即席(Ad Hoc)查询的功能,算法工程师可以边编写代码、边运行、边看结果。Spark提供的各种高效的工具,使机器学习过程更加直观和便捷,比如,可以通过sample函数非常方便地进行抽样。 Spark发展到今天,已经拥有了实时批计算、批处理、算法库、SQL流计算等模块,成了一个全平台系统,把机器学习作为关键模块加入Spark中也是大势所趋。 (三)Spark机器学习库MLlib 需要注意的是,MLlib中只包含能够在集群上运行良好的并行算法,这一点很重要 有些经典的机器学习算法没有包含在其中,就是因为它们不能并行执行 相反地,一些较新的研究得出的算法因为适用于集群,也被包含在MLlib中,例如分布式随机森林算法、最小交替二乘算法。这样的选择使得MLlib中的每一个算法都适用于大规模数据集 如果是小规模数据集上训练各机器学习模型,最好还是在各个节点上使用单节点的机器学习算法库(比如Weka) MLlib是Spark的机器学习(Machine Learning)库,旨在简化机器学习的工程实践工作 MLlib由一些通用的学习算法和工具组成,包括分类、回归、聚类、协同过滤、降维等,同时还包括底层的优化原语和高层的流水线(Pipeline)API,具体如下: (1)算法工具:常用的学习算法,如分类、回归、聚类和协同过滤; (2)特征化工具:特征提取、转化、降维和选择工具; (3)流水线(Pipeline):用于构建、评估和调整机器学习工作流的工具; (4)持久性:保存和加载算法、模型和管道; (5)实用工具:线性代数、统计、数据处理等工具。 Spark在机器学习方面的发展非常快,已经支持了主流的统计和机器学习算法。纵观所有基于分布式架构的升源机器学习库,MLlib以计算效率高而著称。MLlib目前支持常见的机器学习算法,包括分类、回归、聚类和协同过滤等。如下表列出了目前MLlib支持的主要的机器学习算法。 Spark 机器学习库从1.2 版本以后被分为两个包: (1)spark.mllib 包含基于RDD的原始算法API。Spark MLlib 历史比较长,在1.0 以前的版本即已经包含了,提供的算法实现都是基于原始的RDD。 (2)spark.ml 则提供了基于DataFrames 高层次的API,可以用来构建机器学习工作流(PipeLine)。ML Pipeline 弥补了原始 MLlib 库的不足,向用户提供了一个基于 DataFrame 的机器学习工作流式 API 套件。 MLlib目前支持4种常见的机器学习问题:分类、回归、聚类和协同过滤。 Spark MLlib架构由底层基础、算法库和应用程序三部分构成。基层基础包括Spark运行库、进行线性代数相关技术的矩阵库和向量库。算法库包括Spark Mllib实现的具体机器学习算法,以及为这些算法提供的各类评估方法。应用程序包括测试数据的生成以及外部数据的加载等。 二、机器学习流水线 (一)机器学习流水线概念 在介绍流水线之前,先来了解几个重要概念: DataFrame:使用Spark SQL中的DataFrame作为数据集,它可以容纳各种数据类型。较之RDD,DataFrame包含了schema 信息,更类似传统数据库中的二维表格。它被ML Pipeline用来存储源数据。例如,DataFrame中的列可以是存储的文本、特征向量、真实标签和预测的标签等。

Lambda常用

查找类 获取某个实体记录 LambdaQueryWrapper<Entry> activitiesQuery = Wrappers.<Entry>lambdaQuery() .eq(Entry::getId, id) .eq(Entry::getDelFlag, "0") .last(" limit 1 "); 以实体里某个属性为KEY,实体为Value。 (v1, v2) -> v1):有重复的key,取第一个实体为Value。 Map<String, Entry> entryMap = entryList.stream().collect(Collectors.toMap(Entry::getId, v -> v, (v1, v2) -> v1)); 以实体某个属性为KEY,另一个属性为Value Map<String, String> entryMap = entryList.stream().collect(Collectors.toMap(Entry::getId, Entry::getName)); 收集实体的某个属性的集合,去重 Set<String> fieldSet = entryList.stream().map(Entry::getType).collect(Collectors.toSet()); List转Set Set<String> fieldSet = fieldList.stream().collect(Collectors.toSet()); 数量去重 long count = entryList.stream().map(Entry::getName).distinct().count(); 删除 entryService.remove(Wrappers.<Entry>lambdaQuery().eq(Entry::getId, id)); 更新 LambdaUpdateWrapper<Entry> updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper.eq(Entry::getId, id).set(Entry::getNum, num).set(Entry::getUpdateTime, LocalDateTime.now()); entryService.update(null, updateWrapper );

获取客户端真实IP的方法

获取客户端IP的问题 获取请求的IP很简单,可以直接使用request.getRemoteAddr()直接获取。但由于请求在转发到接口前,会经过大量的反向代理,例如流程图中,至少要经过Nginx后,请求才会转发到接口,因此需要对请求接口的IP做处理,提取客户端真实IP地址。 获取客户端IP的步骤 1、编写Nginx配置文件,让Nginx可以携带客户端真实IP的地址 配置Nginx的配置文件,需要反向代理服务器可以携带真实的客户端IP地址,放在请求头中。 核心参数解读: $remote_addr: 如果未使用代理,配置的输出结果为客户端IP。如果使用了代理,配置的输出结果为最后一个代理服务器的IP。$proxy_add_x_forwarded_for: 代表请求链。每经过一个反向代理就在请求头X-Forwarded-For后追加反向代理IP,用逗号+空格分隔。标准格式如下:X-Forwarded-For: clientIP, proxyIP1, proxyIP2(ps. 最左边的clientIp即为客户端真实IP) server { listen 80; server_name localhost; location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://192.168.11.1:10001/; } } 2、将请求头信息维护到Nacos 如果将请求头信息和一些unknow都是写死在代码中的,不方便后期的维护,这里将可能涉及到请求头基于优先级顺序写在Nacos的配置文件中。 # 维护获取客户端IP地址的请求头信息 header: x-forwarded-for,x-real-ip,proxy-client-ip,wl-proxy-client-ip,http-client-ip 相关参数解读: proxy-client-ip:兼容Apache的服务器,请求头中携带真实IP的名称。wl-proxy-client-ip:WebLogic请求头中携带真实IP的名称。http-client-ip:基于其他的代理服务器的方式获取请求头的IP地址 3、编写Java代码,基于请求头获取真实IP地址 以下代码片段为: 获取Nacos配置文件中的请求头信息,基于循环的方式获取真实IP地址。 /** * 客户端IP地址的请求头信息,多个用','隔开。 */ @Value("${headers}") private String headers; /** * 基于请求头获取信息时,可能获取到的未知信息 */ private final String UNKNOW = "unknow"; /** * 如果是当前请求头获取IP地址,需要截取到第一个','未知 */ private final String X_FORWARDED_FOR = "

MyBatisPlus使用指南

MyBatisPlus MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window) 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。 官网地址:https://baomidou.com/ 一、使用前准备 1.准备表结构和数据 准备如下的表结构 DROP TABLE IF EXISTS `t_user`; CREATE TABLE `t_user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID', `name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '姓名', `age` int(11) NULL DEFAULT NULL COMMENT '年龄', `phone` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '手机号', `is_deleted` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT '0' COMMENT '是否删除(0:否,1:是)', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Dynamic; 2.

自然人如何代开发票

1:登录国家税务总局深圳市电子税务局 地址:国家税务总局深圳市电子税务局 2:个人所得税APP 扫描登录 或 身份证登录 3:选择 自然人代开增值税电子普通发票 4:申请代开 5:人脸识别 6:画框的地方填写自己的信息,没画框的地方填写的表格中的信息,然后点击下一步 纳税人识别号91440300MA5HW8550G 纳税人名称 深圳市金马天成科技有限公司 地址 深圳市龙岗区坂田街道马蹄山新村3巷8号301联系电话15110448224开户银行识别中国工商银行银行营业网点名称中国工商银行股份有限公司深圳华为支行 银行账号 4000056009100436066 7:确认 购买方信息(第6步表格中的信息),销售方(自己),备注(自己)的信息 8:进行缴款 9:完成后 点击下载,将PDF 发票

基于javaweb+mysql的springboot就业管理系统设计和实现(java+springboot+ssm)

基于javaweb+mysql的springboot就业管理系统设计和实现(java+springboot+ssm) 私信源码获取及调试交流 运行环境 Java≥8、MySQL≥5.7 开发工具 eclipse/idea/myeclipse/sts等均可配置运行 适用 课程设计,大作业,毕业设计,项目练习,学习演示等 功能说明 基于javaweb的SpringBoot就业管理系统设计和实现(java+springboot+ssm) 就业管理系统: 该毕业设计采用了spring boot,spring,spring mvc,mybatis作为后端技术框架,这些组合稳定抗打,前端使用了layui,界面美观大方。 主要解决了各大高校统计应届毕业生就业的问题, 功能包括:登录,就业信息管理,就业统计管理,用户管理,就业信息管理中包含了专业,岗位,企业等多个搜索条件,对于打算寻找毕业设计或者找项目练手的同学来说,该系统相对功能简单,上手较快。 public CommonResult<List<EmploymentInfo>> getAllInfo(EmploymentInfo employmentInfo, @RequestParam("limit") int pageSize, @RequestParam("page") int pageNum){ List<EmploymentInfo> infoList = employmentInfoService.getAllEmploymentInfo(employmentInfo, pageNum, pageSize); CommonResult<List<EmploymentInfo>> rtInfoResult = CommonResult.generateSuccessResult(infoList.size(), infoList); return rtInfoResult; @ResponseBody @RequestMapping("/employment/getinfo") public CommonResult<List<EmploymentInfo>> getinfo(EmploymentInfo info, @RequestParam("limit") int pageSize, @RequestParam("page") int pageNum){ List<EmploymentInfo> infoList = employmentInfoService.getEmploymentInfo(info, pageNum, pageSize); CommonResult<List<EmploymentInfo>> rtInfoResult = CommonResult.generateSuccessResult(infoList.size(), infoList); return rtInfoResult; @ResponseBody @RequestMapping("/employment/addinfo") CommonResult<List<EmploymentInfo>> rtInfoResult = CommonResult.

FPGA通信——USB2.0(CY7C68013)使用记录

一、CY7C68013简介 CY7C68013是Cypress公司的FX2系列芯片,是一款USB2.0芯片,最大传输速度60MByte/S ,半双工通信方式。属于高速USB2.0芯片。 功能引脚说明FD0~FD718~25数据线低字节FD8~FD1545~52数据线高字节 FIFOADDR0 FIFOADDR1 37 38 地址线,接收:2'b00 发送:2'b10 SLRD1 读控制信号,低电平有效 SLWR2 写控制信号,低电平有效 FLAGA FLAGB FLAGC FLAGD 31 30 29 40 可通过程序配置,映射到不同功能,一般用于指示fifo的空、满状态SLCS40片选信号,拉低即可,与FLAGD复用,一般程序设计尽量避免FLAGD的使用PKTEND39 数据包结束标志信号 ,一般拉高即可 SLOE35输出使能,低电平有效(接收USB数据时使用) 1.1 Cy7C68013的Slave FIFO模式 Cy7C68013内嵌一个8051处理器,将芯片Slave FIFO 相关的寄存器修改,控制芯片工作在Slave FIFO模式下。外部逻辑(如FPGA)即可按照SlaveFIFO的传输时序,高速与主机进行通讯,而在通讯过程中不需要8051固件的参与。 1.2、Slave FIFO模式相关寄存器 FLAGA、FLAGB、FLAGC、FLAGD功能配置 二、硬件设计 芯片高速模式下最大传输速度60MByte/S ,全速模式下最大传输速度12MByte/S方式。所以电路布局时要考虑一下因素对信号的影响 2.1、振荡器、晶振 在电路设计阶段踩过的坑,根据官方手册建议,振荡器要满足一下要求: 频率24MHZ并联谐振电容基本模式驱动电平为500uw12pf(容差5%)的负载电容精度 +/-50PPM 晶振不宜与芯片距离较大,尽可能缩短晶振到芯片的走线晶振走线原理 应D+ 和D-的走线 2.2、D+ 与D-信号 采用差分走线,两根线等长、等宽、间距相等,保持在同一层根据电路板生产厂家,计算走线,控制90欧姆阻抗在电路板上的走线不得过长不得超过75mm尽量保证两根线周围的250mil空间没有铺铜、走线避免使用过孔,如果 使用较小的过孔(25mil焊盘、10mil过孔) 2.3、VBUS、GND、屏蔽信号 电源线尽量走粗 三、使用过程中记录 芯片的Slave FIFO模式,可将EP2、EP4、EP6、EP8配置成上图几种存储方式,在通信的数据格式上要考虑512字节的基础存储单位。

Python处理图片生成天际线(2024.1.29)

引言 小的时候,自己有一个大大的梦想——让我们生活的世界变得更加美丽、干净和整洁!当我第一次在中学食堂的电视机上看到航天员们登上太空时,内心无比兴奋和向往,从太空回传的影像画面让人不由震惊,印象深刻! 曾经感慨浩瀚无垠的宇宙不知有多么宽广,流星为何会从夜空滑落,陨石又不知何时从天空坠落地坑,古人也在抬头夜观天象、探讨天圆地方的过程中,也能启发思维、浮现灵感、激发创造力,作为来者的我们在现代化社会更应该学会深入思考,学思结合。正所谓:学而不思则罔,思而不学则怠。 潮涨潮落,云卷云舒,黑夜白昼,四季交替,世间万物,自然更新,在规律中暗含不确定性,在不规律中似有玄机。人类在探索真理、改造和利用自然的过程中,逐渐认识自己、认识外物、认识自然、认识世界,在认识的过程中坚持走出去与引进来相结合,说者容易做者困难。 1、天际线简介 天际线(SkyLine)顾名思义就是天空与地面的边界线,人站在不同的高度,会看到不同的景色和地平线,天空与地面建筑物分离的标记线,不得不说,每天抬头仰望天空,相信大家都可以看到,它的的确确客观存在,美丽值得欣赏。 2、Python代码 #-*- coding:utf-8 -*- import sys from os.path import exists import cv2 import numpy as np def getImage(height, width, channels): image = np.zeros([height, width, 3], np.uint8) # 三通道顺序是BGR # 三层循环逐个修改像素点 for row in range(height): for col in range(width): for c in range(channels): image[row, col, c] = 0 return image def isWhite(pixel_value, threshold): #阈值可以取10、20、30、50、100 res = False if pixel_value[0] > threshold and pixel_value[1] > threshold and pixel_value[2] > threshold: # 10、10、10 50、50、50 这里是天空和地面楼山的分界线,需要调参 res = True return res def isPureWhite(pixel_value): res = False if pixel_value[0] == 255 and pixel_value[1] == 255 and pixel_value[2] == 255: # >3|>3|>3 10、10、10 res = True return res def getRowNumberSpecificCol(image, col): res_row = -1 height, width = image.

vtkSliderWidget动态调整vtkCellLocator空间单元切分level

开发环境: Windows 11 家庭中文版Microsoft Visual Studio Community 2019VTK-9.3.0.rc0vtk-example demo解决问题:使用 VTK 创建一个交互式的可视化场景,并通过滑块部件动态调整单元定位器的参数,调整定位器空间单元切分的层次 关键点: 创建单元定位器,构建level=0的搜索空间,并locatorTreeActor->GetProperty()->SetRepresentationToWireframe()显示空间边框 // Create the tree. vtkNew<vtkCellLocator> cellLocator; cellLocator->SetDataSet(inputSource->GetOutput()); cellLocator->BuildLocator(); // Initialize the representation. vtkNew<vtkPolyData> polydata; cellLocator->GenerateRepresentation(0, polydata); 回调中动态调整空间构建的level,标识x y z分别切分2的level次方,等分(可以参考八叉树的概念),这里截图中我*2,>0.5时向上取整,就是1 *2,所以x y z等分4份,就有了截图中的效果 vtkSliderWidget* sliderWidget = reinterpret_cast<vtkSliderWidget*>(caller); this->Level = vtkMath::Round( static_cast<vtkSliderRepresentation*>(sliderWidget->GetRepresentation()) ->GetValue()); this->CellLocator->GenerateRepresentation(this->Level, this->PolyData); this->Renderer->Render(); 注意:vtkCellLocator 是 Visualization Toolkit(VTK)中的一个类,它提供了空间搜索功能,用于根据空间查询定位数据集中的单元格。它可以用于查找距离给定点最近的单元格,或在三维数据集中执行射线投射和碰撞检测等操作。 prj name: CellLocatorVisualization #include <vtkActor.h> #include <vtkCallbackCommand.h> #include <vtkCellLocator.h> #include <vtkMath.h> #include <vtkNamedColors.h> #include <vtkNew.h> #include <vtkPolyData.h> #include <vtkPolyDataMapper.

一图窥探RAG技术发展现状

2023年除了大语言模型,听到最多的当属RAG(检索增强生成技术了),在实际业务场景落地过程中,由于大模型目前的一定局限和能力现状以及Token限制、训练成本等多种因素的影响下,RAG不得不成为大家选择快速试错、落地的一种选择和方案。 RAG技术通过查询处理、数据检索、文档优化、增强生成、语义理解、文档结构化和自我增强等多步骤,实现了对用户问题的深度理解和高效回答。🔍📈 从自然语言到数据库查询,再到精准答案,RAG技术让AI的每一步都更加智能和人性化,让我们从这一张图来了解RAG技术体系的全貌。#RAG #人工智能 #自然语言处理 #技术前沿" 一、在RAG技术体系中将用户的问题路由到最合适的数据源或处理路径 一般有语义路由和逻辑路由两种方式。语义路由和逻辑路由可能结合使用,以实现更高效和准确的信息检索。语义路由帮助系统理解查询的深层含义,而逻辑路由确保查询按照正确的逻辑被处理。这种结合可以提高系统对复杂查询的处理能力,尤其是在需要理解用户意图和执行复杂逻辑操作的场景中。 语义路由(Semantic Routing): 语义路由侧重于理解查询的语义内容,即查询的实际含义和意图。在RAG系统中,语义路由可能涉及到自然语言处理(NLP)技术,如语义分析、实体识别和意图识别,以确保系统能够准确理解用户的问题。语义路由的目标是将用户的查询映射到最相关的数据源或处理路径,即使这些路径可能不是直观的或直接的。例如,如果用户询问“最近的天气如何?”,语义路由会识别出这是一个关于天气查询的问题,并将其路由到提供天气信息的服务或数据库。 逻辑路由(Logical Routing): 逻辑路由则更侧重于查询的结构和形式,它根据查询的逻辑结构来确定处理路径。在RAG系统中,逻辑路由可能涉及到对查询语句的解析,识别出查询中的逻辑关系,如AND、OR、NOT等操作。逻辑路由的目标是确保查询按照既定的规则和顺序被正确处理,以便系统能够生成准确的回答。例如,如果用户提出一个复杂的SQL查询,逻辑路由会确保查询中的各个部分按照正确的逻辑顺序被执行。 二、RAG技术涉及的以下几个关键过程 查询处理: 用户提出问题后,系统首先需要构建一个有效的查询(Query Construction)。系统将自然语言查询转换为数据库查询语言,如SQL或Cypher(Text-to-SQL, Text-to-Cypher)。 数据检索与排名: 系统从多种数据源(如关系型数据库、图数据库、向量数据库)检索相关文档(Retrieval)。对检索到的文档进行排名(Ranking),以确定哪些文档最相关。 文档处理与优化: 对文档进行精炼(Refinement),可能包括重新排名、过滤或压缩,以提高相关性。自动生成元数据(Auto-generate metadata)以辅助检索。对文档进行分块优化(Chunk Optimization),以便于处理和生成回答。 检索增强与生成: 使用RAG-Fusion等技术将检索到的信息与生成的回答结合起来。主动检索(Active Retrieval)确保在初始检索不相关时能够重新检索或从新数据源获取信息。 语义理解和微调: 使用语义分割器(Semantic Splitter)来处理文档,提高理解的准确性。对模型进行微调(Fine-tuning),如使用ColBERT等先进的嵌入模型,以提高检索和生成的质量。 文档摘要与结构化: 构建文档摘要的树状结构(Tree of document summarization),以便于在不同抽象层次上理解和回答。优化文档转换为紧凑形式的工具(如RAPTOR),提高检索效率。 自我增强与迭代: 自我增强的RAG(Self-RAG)和重复回答检索(RRR)允许系统自我改进其检索和生成过程。

Nexus3之在Window中搭建Maven私服

Nexus3之在Window中搭建Maven私服 文章目录 Nexus3之在Window中搭建Maven私服1. 下载2. 安装3. 创建用户及仓库4. maven的setting.xml文件修改5. POM.xml文件修改 1. 下载 官网: https://www.sonatype.com/download-oss-sonatype 下载OSS免费版,如下载版本为:Nexus-3.16.0-latest-win64.zip 2. 安装 先将Nexus-3.16.0-latest-win64.zip文件解压到指定目录,如:D:\Nexus-3.16.0目录下将D:\Nexus-3.16.0\nexus-3.16.2-01\bin 添加到环境变量的path路径后面以管理员身份打开cmd窗口,输入下面命令安装 # 注册服务 nexus /install Nexus3 #此命令直接注册到服务中,名称为Nexus3 # 启动服务 net start Nexus3 浏览器总输入 http://localhost:8081 进行访问,第一次访问时间稍微有些长 3. 创建用户及仓库 浏览器中打开Nexus图形界面后,输入管理员密码登录,默认账户/密码为 admin/admin123 注意:最新版本的admin会在安装目录下的admin.password文件中,首次登陆后修改admin密码接口,如:3.39.0-01的admin密码位置如下 Your admin user password is located in E:\warehouse\nexus-3.39.0-01\sonatype-work\nexus3\admin.password on the server. 创建一个用户,比如 yuan/yuan123配置一个代理(proxy)仓库,如使用阿里云的maven仓库,URL: http://maven.aliyun.com/nexus/content/groups/public/创建两个hosted(宿主)类型的仓库 #名称为yuan-releases的hosted仓库 http://localhost:8081/repository/yuan-releases/ #名称yuan-sanpshots的hosted仓库 http://localhost:8081/repository/yuan-snapshots/ 创建一个group类型的仓库 #名称为yuan-public的group类型仓库 http://localhost:8081/repository/yuan-public/ 将yuan-releases 与 yuan-snapshots 添加到仓库组 yuan-public中 4. maven的setting.xml文件修改 server配置 <servers> <!--发布版--> <server> <id>yuan-releases</id> <username>yuan</username> <password>yuan123</password> </server> <!

【AI大模型应用开发】【LangChain系列】3. 一文了解LangChain的记忆模块(理论实战+细节)

大家好,我是【同学小张】。持续学习,持续干货输出,关注我,跟我一起学AI大模型技能。 大多数LLM应用程序都有一个会话接口。会话的一个重要组成部分是能够参考会话早期的信息(上文信息)。这种存储过去互动信息的能力就称为“记忆(Memory)”。LangChain提供了许多用于向系统添加Memory的封装。 目前 LangChain 中大多数的Memory封装还都是测试版本。成熟的Memory主要是ChatMessageHistory。 0. 认识Memory Memory,通俗的讲,就是记录对话的上下文信息,在有需要的时候补充到用户的提问中去。看上图,简单说下Memory的使用流程: 当用户输入一个问题,首先从Memory中读取相关的上文信息(历史对话信息),然后组装成一个Prompt,调用大模型,大模型的回复作为历史对话信息保存在Memory中,供之后的对话使用。 下面让我们来看一看LangChain的Memory到底长什么样。 0. 对话上下文ConversationBufferMemory 这是最简单的Memory形式,保存形式类似是chat message的数组。 使用方法如下: save_context 可以保存信息到memory中load_memory_variables 获取memory中的信息chat_memory.add_user_message和chat_memory.add_ai_message 也可以用来保存信息到memory中 from langchain.memory import ConversationBufferMemory, ConversationBufferWindowMemory history = ConversationBufferMemory() history.save_context({"input": "你好啊"}, {"output": "你也好啊"}) print(history.load_memory_variables({})) history.save_context({"input": "你再好啊"}, {"output": "你又好啊"}) print(history.load_memory_variables({})) history.chat_memory.add_user_message("你在干嘛") history.chat_memory.add_ai_message("我在学习") print(history.load_memory_variables({})) ## 或者直接使用 ChatMessageHistory 添加memory,效果一样 # from langchain.memory import ChatMessageHistory # chat_history = ChatMessageHistory() # chat_history.add_user_message("你在干嘛") # chat_history.add_ai_message("我在学习") # print(history.load_memory_variables({})) 运行结果: 上面的结果,可以看到返回的信息永远都是以“history”开头的,怎么修改这个key呢?只需要修改下面一句,填入 memory_key 参数。 history = ConversationBufferMemory(memory_key="chat_history_with_同学小张") 运行结果: 返回的结果还有一点值得注意,那就是它目前返回的是一个json字符串,这是可以直接给LLMs对话输入的。但对于ChatModels对话,它接收的参数是Chat Messages数组。我们可以通过改变参数return_messages=True,让这个memory的返回变成Chat Messages数组。

Unix五种I/O模型(阻塞、非阻塞、多路复用、信号驱动、异步)

文章目录 概要一、I/O基础二、阻塞式I/O三、非阻塞式I/O三、I/O多路复用四、信号驱动I/O五、异步I/O六、小结 概要 在工作中,经常使用Nginx、Redis等开源组件,常提到其高性能的原因是网络I/O的实现是基于epoll(多路复用)。这次呢就基于Unix网络编程卷1的第6章【I/O复用:select和poll函数】,总结下Unix五种I/O模型(阻塞、非阻塞、多路复用、信号驱动、异步)。 一、I/O基础 我们在Linux下进行网络编写时,一般是通过Glibc库的Socket API(socket、bind、listen、accept、read、write、connect、close等API)来完成的,如下图: 这只是表面的使用,那socket之下的OSI五层模型是如何体现的呢?见下图: 二、阻塞式I/O 阻塞式I/O是最基本的I/O模型,很好理解,就是每次系统调用(以read、waite API为例)时,如果此时不可读或写,那么调用会被阻塞,让后进程被挂起,直到内核通知进程可读或可写时,进程被唤醒,进行读写操作。 如下图: ps:以recvfrom函数作为系统调用的代表,其他章节也如此。 阻塞式I/O实战(多进程模型) 三、非阻塞式I/O 非阻塞式I/O模型如下图: 可以明显感觉到阻塞是I/O模型很低效,于是非阻塞式I/O模型诞生了,其进行系统调用(以read、waite API为例)时,如果此时不可读或写,那么就返回一个错误码(EAGAIN或EWOULDBLOCK),而不是阻塞当前进程,这样进程可以处理其他任务后再进行系统调用。 非阻塞式I/O模型实战。 三、I/O多路复用 不管是阻塞I/O还是非阻塞I/O,其同一时刻只能以一个客户端建立连接,如果要同时与多个客户端维持连接,即管理多个socket连接,分化出了两种编程模型: 1)多线程或进程;2)通过数组等方式保存socket fd,不断轮询; 在没有多路复用之前,实现与多个客户端维持连接的传统方法是多线程或进程,但是起一个子线程或进程的系统开销过大,所以可同时维持的客户端连接数量非常有限。 之所以传统维持多个客户端连接不常用第二种方式,主要是实现过于复杂,由于社会发展,基于阻塞or非阻塞模型的多进程/线程技术不足以支撑如此多的客户端,于是引入了I/O多路复用,即第二种方式来管理多个socket连接。 I/O多路复用解释如下: 多路:多个socket连接(即多个客户端连接); 复用:允许内核监听多个socket描述符,一旦发现进程指定的一个或多个I/O事件就绪(TCP三次握手成功、可读,可写),就通知该进程。 其模型图如下: I/O多路复用的API依次有三个select、poll、epoll。其中epoll性能最高,往往与Reactor编程模式结合,是目前常用的高效搭配模式。 select实战; poll实战; epoll实战。 本人研究Redis相关源码时,观察到其在Linux下就是通过epoll+非阻塞I/O+Reactor组合来处理I/O事件,是其高性能的一个关键点。 四、信号驱动I/O 信号驱动IO模型,顾名思义,其是通过信号来完成的,即当socket描述符准备就绪时,内核发送SIGIO通知进程。 信号驱动IO模型实战。 这种模型的优势在于等待socket就绪期间进程不会被阻塞,主循环依旧可以执行,只需关注来自信号函数的通知即可。但是该模型在实际项目中很少使用,了解理解即可。 五、异步I/O 异步I/O由POSIX规范定义。一般来说其工作机制:告知内核启动某个动作,并让内核将整个动作(包括将数据从内核复制到用户缓冲区)完成后通知进程。 该机制与信号驱动I/O模型的区别是:信号驱动I/O模型是由内核通知进程何时可以开始一个I/O操作,但异步I/O是由内核通知进程I/O操作何时完成。 进程调用系统函数aio_read(POSIX规范下异步I/O函数以aio_或lio_开头)之后,无论内核数据是否准备好,都会立即,然后进程可以去做别的事情。内核会自动处理I/O数据,并将内核直接复制数据给进程,然后向进程发送信号,进程收到信号后直接处理数据即可。 异步I/O模型是最理想的模型,但是自诞生之日起的具体实现方式(glibc aio、libaio、libeio…)就有这样或那样的缺点,2019 年 Linux 5.1 内核首次引入的高性能 异步 I/O 框架io_uring ,能显著加速 I/O 密集型应用的性能,并且使用简单,适应度广,足够稳定,但诞生的太晚了,远没有epoll应用的范围广。 异步I/O模型实战。 六、小结 通过对五种I/O模型的描述,可以发现前四种模型的区别主要在于第一阶段的处理方式(阻塞I/O和多路复用是阻塞的,非阻塞I/O【轮询】和信号驱动【通知】是非阻塞的),第二阶段形同:将数据从内核区复制到用户区,都进程都会阻塞于recvfrom函数。但异步I/O的两个阶段内核都帮我们做了,这与前四种模型是截然不同的。 五种I/O模型比较如下: 最后聊一下阻塞、非阻塞、同步、异步在Unix网络编程语境下的概念: 阻塞:指调用结果返回之前,当前进程会被挂起,只有得到结果之后才会返回。 非阻塞:指如果不能立刻得到结果,当前进程不会被挂起。Unix下是通过立即返回规定错误码来实现的。 同步:I/O操作会阻塞当前进程,直至操作完成。由此可知前四种模型都是同步的(非阻塞I/O如果有数据时依旧需等待数据从内核区复制到用户区,或阻塞当前进程)。 异步:I/O操作不会阻塞当前进程。 我们可以举这样一个场景,小明要喝开水,客厅有其他事情,而烧水壶在卧室。 小明打开热水壶,站在热水壶面前一直等待水开 => 阻塞 小明打开热水壶后回到客厅做其他事情,一会去卧室检查一下水是否烧开,烧开再使用 => 非阻塞