首页
关于
Search
1
SteamOS安装paru和yay
170 阅读
2
欢迎使用 Typecho
127 阅读
3
徕卡X | 冬日漫步
127 阅读
4
https自动跳转问题终极解决方案
116 阅读
5
Spark3中的Catalog组件设计
104 阅读
默认
摄影
后端开发
大数据
Spark
Flink
登录
Search
标签搜索
转载
ArlenDu
累计撰写
18
篇文章
累计收到
10
条评论
首页
栏目
默认
摄影
后端开发
大数据
Spark
Flink
页面
关于
搜索到
3
篇与
的结果
2025-05-10
【转载】用certbot申请Let's Encrypt泛域名证书
转载来源:https://www.cnblogs.com/oboth-zl/p/14330854.html正文什么是Let's Encrypt?目前世界上就只有为数不多的几家域名证书签发机构得到浏览器的认可,而Let‘s Encrypt就是其中一家,并且你可以申请到免费的证书,当然你如果想要付费也行,很多机构证书动辄几千几万一年。如果我们只想搭建个测试环境有需要https,我们肯定不会去花这个冤枉钱,当然免费的午餐并没有那么好吃,Let's Encrypt申请的证书只有90天有效期,所以到期你得进行续期操作。并且还有各种各样得条件限制,比如一周你只能申请多少次,同一个ip一天只能操作多少次之类,详见https://letsencrypt.org/docs/rate-limits/假如你使用jdk生成的自签证书能不能用呢?当然是可以用的,只不过浏览器会告诉你这个证书我不承认。也就是左上角会给你挂个不安全的警告。什么是泛域名证书?例如:*.xxx.cn 也就是这个证书可以给某个域名的所有二级域名使用,就叫做泛域名证书(也称作通配符证书)。Let's Encrypt 官方推荐我们使用certbot 脚本申请证书(当然也可以使用acme.sh等方式),以下是申请步骤基于Debian10 python3.7.3如果你在操作过程中遇到什么报错,请多考虑python工具包的版本问题之类的。Let's Encrypt自2018年开始支持申请泛域名证书,相比于单域名证书,泛域名证书更利于日常的维护。准备工作下载 certbot,这个很多发行版的源中都已经自带了。比如Debian的:sudo apt install certbot需要有域名的管理权限,因为申请泛解析证书需要使用 DNS 验证,这就需要你能够根据要求操作 DNS 解析记录,以此证明你对域名的权限。开始申请泛域名证书certbot certonly --preferred-challenges dns --manual -d *.xx.cn --server https://acme-v02.api.letsencrypt.org/directorySaving debug log to /var/log/letsencrypt/letsencrypt.logPlugins selected: Authenticator manual, Installer NoneObtaining a new certificatePerforming the following challenges:dns-01 challenge for xx.cn- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -NOTE: The IP of this machine will be publicly logged as having requested thiscertificate. If you're running certbot in manual mode on a machine that is notyour server, please ensure you're okay with that.Are you OK with your IP being logged?- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -(Y)es/(N)o: y- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Please deploy a DNS TXT record under the name_acme-challenge.xx.cn with the following value:nI0DhzH-vn0W7STVuLi2O-oIKuFNlqQx5EnjB-zewvsBefore continuing, verify the record is deployed.- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Press Enter to Continue #让你的二级域名_acme-challenge.xx.cn用TXT方式解析到nI0DhzH-vn0W7STVuLi2O-oIKuFNlqQx5EnjB-zewvs#可用dig -t txt _acme-challenge.xx.cn验证解析是否生效,然后按下Enter通过验证。 debian可用apt install dnsutils来安装dig命令。 #也可以用nslookup命令来验证。Waiting for verification...Cleaning up challengesIMPORTANT NOTES:- Congratulations! Your certificate and chain have been saved at:/etc/letsencrypt/live/xx.cn/fullchain.pemYour key file has been saved at:/etc/letsencrypt/live/xx.cn/privkey.pemYour cert will expire on 2021-04-26. To obtain a new or tweakedversion of this certificate in the future, simply run certbotagain. To non-interactively renew all of your certificates, run"certbot renew"- If you like Certbot, please consider supporting our work by:Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donateDonating to EFF: https://eff.org/donate-le\#至此证书申请成功参数说明:certonly 表示只申请证书。--no-bootstrap 需要用户同意的系统级操作直接选N。--manual 表示交互式申请。-d 为那些主机申请证书如 *.xxx.cn(此处为泛域名)--preferred-challenges dns,使用 DNS 方式校验域名所有权,可以配置多个--server Let's Encrypt ACME v2 版本使用的服务器不同于 v1 版本(V2版本才支持泛域名解析),需要显示指定。证书签发成功后去Nginx或Apache配置新生成的证书文件即可。撤销证书倘若有不需要的证书了,可撤销删除。sudo certbot revoke --cert-path /etc/letsencrypt/archive/xx.cn/cert1.pemSaving debug log to /var/log/letsencrypt/letsencrypt.log- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Would you like to delete the cert(s) you just revoked, along with all earlierand later versions of the cert?- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -(Y)es (recommended)/(N)o: y #是否删除证书自动验证的方式申请证书上面的方式需要手动去到DNS解析服务商更改解析通过验证,其实通过Certbot 官方的插件可以实现自动更新DNS通过验证。https://certbot.eff.org/docs/using.html#manual支持上面这些服务商。准备安装对应的DNS插件sudo apt install python3-certbot-dns-cloudflare #sudo apt install python2-certbot-dns-cloudflare#我用到的服务商是Cloudflare*配置 DNS 插件*在cloudflare获取KEY/TOKEN****两种方式均可,只是token的方式需要2.3.1版本以上的python*-certbot-dns-cloudflare插件。出于安全因素,推荐前者的方式。# Cloudflare API credentials used by Certbot dns_cloudflare_email = cloudflare@example.com dns_cloudflare_api_key = 0123456789abcdef0123456789abcdef01234567将上面的配置信息写入~/cloudflare.ini。申请sudo certbot certonly --dns-cloudflare --dns-cloudflare-credentials ~/cloudflare.ini --dns-cloudflare-propagation-seconds 60 --preferred-challenges dns -d *.example.win --server https://acme-v02.api.letsencrypt.org/directory #--dns-cloudflare-propagation-seconds 60 #等待60秒, 等DNS解析生效由于这里的泛域名证书之前已申请过,且存在于服务器,Certbot自动进行了续期操作。至此,泛域名证书申请完成。续期若是通过手动更改DNS解析的方式申请的域名,我们执行certbot renew时会报错。此时只有重新按照申请证书的步骤再来一遍。certbot certonly --preferred-challenges dns --manual -d *.xx.cn --server https://acme-v02.api.letsencrypt.org/directory若是通过API自动验证的方式申请的,则可以直接用cerbot renew的方式更新证书!
2025年05月10日
12 阅读
0 评论
0 点赞
2024-10-22
Redis学习笔记
Redis核心原理与实战Redis执行流程:当用户输入一条命令之后,客户端会以 socket 的方式把数据转换成 Redis 协议,并发送至服务器端,服务器端在接受到数据之后,会先将协议转换为真正的执行命令,在经过各种验证以保证命令能够正确并安全的执行,但验证处理完之后,会调用具体的方法执行此条命令,执行完成之后会进行相关的统计和记录,然后再把执行结果返回给客户端,整个执行流程,1.输入命令2.将命令转换成成Redis的协议,通过socket发送到服务器3.服务器接收到后对Redis协议进行解析,变成可以执行的redis命令4.服务端鉴权5.执行最终命令,调用 redisCommand 中的 proc 函数执行命令。6.执行完进行相关记录和统计7.将执行的结果通过socket返回给客户端2.Redis的容错RDB: 二进制文件,性能好,但是可能会丢数据AOF:日志文件,可以设置always, everyseconds, no;能最大限度的保证数据不丢失,但是恢复的性能比较慢,虽然AOF也提供了优化机制:AOF重写RDB和AOF混部: 其实还是读的AOF文件,因为当AOF开启时,不管有没有开启RDB,都会使用AOF。混合部署时,其实是将RBD文件写入到了AOF文件的开头。这样恢复时,就可以通过RDB+AOF的方式进行恢复了。混合持久化的加载流程如下:判断是否开启 AOF 持久化,开启继续执行后续流程,未开启执行加载 RDB 文件的流程;判断 appendonly.aof 文件是否存在,文件存在则执行后续流程;判断 AOF 文件开头是 RDB 的格式, 先加载 RDB 内容再加载剩余的 AOF 内容;判断 AOF 文件开头不是 RDB 的格式,直接以 AOF 格式加载整个文件。3.Redis基本类型和原理 1.字符串 实现原理:SDS,包含了三种不同的数据类型:int、embstr 和 raw。int 类型很好理解,整数类型对应的就是 int 类型,而字符串则对应是 embstr 类型,当字符串长度大于 44 字节时,会变为 raw 类型存储。 2.Hash 字典类型本质上是由数组和链表结构组成的。来看字典类型的源码实现:typedef struct dictEntry { // dict.h void *key; union { void *val; uint64_t u64; int64_t s64; double d; } v; struct dictEntry *next; // 下一个 entry } dictEntry;通常情况下字典类型会使用数组的方式来存储相关的数据,但发生哈希冲突时才会使用链表的结构来存储数据。Redis 为了保证应用的高性能运行,提供了一个重要的机制——渐进式 rehash。 渐进式 rehash 是用来保证字典缩放效率的,也就是说在字典进行扩容或者缩容是会采取渐进式 rehash 的机制。 3.List 列表类型 (List) 是一个使用链表结构存储的有序结构,它的元素插入会按照先后顺序存储到链表结构中,因此它的元素操作 (插入\删除) 时间复杂度为 O(1),所以相对来说速度还是比较快的,但它的查询时间复杂度为 O(n),因此查询可能会比较慢。底层:列表类型并不是简单的双向链表,而是采用了 quicklist 的数据结构对数据进行存取,quicklist 是 Redis 3.2 新增的数据类型,它的底层采取的是压缩列表加双向链表的存储结构,quicklist 为了存储更多的数据,会对每个 quicklistNode 节点进行压缩,这样就可以有效的存储更多的消息队列或者文章的数据 4.Set 集合类型是由整数集合 (intset) 或者是哈希表 (hashtable) 组成的,集合类型比较适合用来数据去重和保障数据的唯一性,除此之外,集合类型还可以用来统计多个集合的交集、错集和并集 (见附录)。当我们存储的数据是无序并且需要去重的情况下,比较适合使用集合类型进行存储。当元素都为整数并且元素的个数没有到达设置的最大值时,键值的存储使用的是 intset 的数据结构,反之到元素超过了一定的范围,又或者是存储的元素为非整数时,集合会选择使用 hashtable 的数据结构进行存储。 5.Sorted Set 有序集合是由 ziplist (压缩列表) 或 skiplist (跳跃表) 组成的。 为什么是跳跃表?而非红黑树? 因为跳跃表的性能和红黑树基本相近,但却比红黑树更好实现,所有 Redis 的有序集合会选用跳跃表来实现存储。4.Redis事务Redis 中的事务从开始到结束也是要经历三个阶段:开启事务命令入列执行事务/放弃事务其中,开启事务使用 multi 命令,事务执行使用 exec 命令,放弃事务使用 discard 命令。5.Redis键值过期的操作Redis 中设置过期时间主要通过以下四种方式:expire key seconds:设置 key 在 n 秒后过期;pexpire key milliseconds:设置 key 在 n 毫秒后过期;expireat key timestamp:设置 key 在某个时间戳(精确到秒)之后过期;pexpireat key millisecondsTimestamp:设置 key 在某个时间戳(精确到毫秒)之后过期;字符串中的过期操作字符串中几个直接操作过期时间的方法,如下列表:set key value ex seconds:设置键值对的同时指定过期时间(精确到秒);set key value px milliseconds:设置键值对的同时指定过期时间(精确到毫秒);setex key seconds valule:设置键值对的同时指定过期时间(精确到秒)。6.过期策略Redis 会删除已过期的键值,以此来减少 Redis 的空间占用,但因为 Redis 本身是单线的,如果因为删除操作而影响主业务的执行就得不偿失了,为此 Redis 需要制定多个(过期)删除策略来保证糟糕的事情不会发生。常见的过期策略有以下三种:定时删除惰性删除定期删除Redis 使用的是惰性删除加定期删除的过期策略。7.Redis 管道技术—Pipeline管道技术是将任务一次性批量发送到服务端处理,然后批量返回结果的一种的技术,主要是为了解决每条命令执行后需要等待的情况,从而有效的提高了程序的执行效率。但是使用管道技术也要注意避免发送的命令过大,或者管道内的数据太多而导致的网络阻塞。8.游标迭代器(过滤器)——ScanScan 是一个系列指令,除了 Scan 之外,还有以下 3 个命令:HScan 遍历字典游标迭代器SScan 遍历集合的游标迭代器ZScan 遍历有序集合的游标迭代器Scan 具备以下几个特点:Scan 可以实现 keys 的匹配功能;Scan 是通过游标进行查询的不会导致 Redis 假死;Scan 提供了 count 参数,可以规定遍历的数量;Scan 会把游标返回给客户端,用户客户端继续遍历查询;Scan 返回的结果可能会有重复数据,需要客户端去重;单次返回空值且游标不为 0,说明遍历还没结束;Scan 可以保证在开始检索之前,被删除的元素一定不会被查询出来;在迭代过程中如果有元素被修改, Scan 不保证能查询出相关的元素。9.HyperLogLog类似集合的效果,用于快速的统计count的算法,可以用极小的空间占用实现,但是由于是基于hash,可能会有一定的误差(0.83%)。HyperLogLog的算法:相当于把存储的值经过 hash 之后,再将 hash 值转换为二进制,存入到不同的桶中,这样就可以用很小的空间存储很多的数据,统计时再去相应的位置进行对比很快就能得出结论,这就是 HLL 算法的基本原理,想要更深入的了解算法及其推理过程,可以看去原版的论文,链接地址在文末。10.内存淘汰机制算法Redis 内存淘汰策略和过期回收策略是完全不同的概念,内存淘汰策略是解决 Redis 运行内存过大的问题的,通过与 maxmemory 比较,决定要不要淘汰数据,根据 maxmemory-policy 参数,决定使用何种淘汰策略,在 Redis 4.0 之后已经有 8 种淘汰策略了,默认的策略是 noeviction 当内存超出时不淘汰任何键值,只是新增操作会报错。
2024年10月22日
40 阅读
0 评论
0 点赞
2024-01-10
<转载>解决jar包冲突新思路 - maven-shade-plugin
转载自知乎专栏:https://zhuanlan.zhihu.com/p/62796806前言:发生jar包冲突通常是因为,项目中依赖了同一个jar包的多个版本。一般的思路是只保留一个版本,删除掉不需要的版本。最近遇到了一个下图这样的例子:排掉d1的话a会报错,排掉d2的话b会报错,所以希望在项目中同时使用d1和d2。最开始同事说可以用maven-shade-plugin这个插件实现这个需求的时候,我的内心是这样的:后来听他解释完以后才恍然大悟,感觉世界观再一次被刷新了,居然还有这种操作。。。下面就简单描述一下具体怎么用shade插件解决这个问题的吧。正文:首先介绍一下具体测试代码: (下载链接:package-test)与前言中的图相对应,项目总共分3个模块:a\b\c,其中a和b分别依赖了guava的19.0(d1)和26.0.jre(d2),然后c同时引用了a和b。其中guava的两个版本有下边两个不兼容的方法,用来测试:public static Objects.ToStringHelper toStringHelper(Object self) { //该方法 19.0有,26.0.jre没有}public static String lenientFormat(@Nullable String template, @Nullable Object @Nullable... args) { //该方法 19.0没有,26.0.jre有}直接执行com.zhaohui.C的main方法,会报如下错误:Exception in thread "main" java.lang.NoSuchMethodError: com.google.common.base.Strings.lenientFormat(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;接下来就介绍一下解决问题的工具maven-shade-plugin。(源码地址:github) 这里使用3.2.1的tag。为了更简单的了解maven-shade-plugin这个插件到底做了什么,可以直接打断点调试一下,跟着源码走一遍打包流程。首先,下载源码,然后添加到package-test的module中,具体操作如下图:然后package-test-c项目的pom文件增加这个插件:<plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.2.1</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>com.zhaohui.C</mainClass> </transformer> </transformers> </configuration> </execution> </executions> </plugin> </plugins>mvn插件的代码入口是@Mojo注解类的execute方法,在该方法入口(org.apache.maven.plugins.shade.mojo.ShadeMojo line385)打个断点,如下图:最后一步按照下图操作:增加一个run/debug configuration 最后点击debug按钮就可以调试了。具体生成jar包的代码org.apache.maven.plugins.shade.DefaultShader line151 shadeJars方法。打断点发现,打包的时候,解析pom文件总共获取了4个jar包,其中guava只有19.0,没有26.0.jre,所以执行的时候才会报错找不到26.0.jre中的方法。调试中,在org.apache.maven.plugins.shade.DefaultShader line539 有下面代码:sourceContent = relocator.applyToSourceContent( sourceContent );这个relocator会在打包过程中,修改类的包名。这个就是解决这个问题的关键。具体解决思路如下图:在项目中新增一个模块b-shade,里边什么代码都没有,只有一个dependency b,然后配置maven-shade-plugin 如下: <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.2.1</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <relocations> <relocation> <pattern>com.google.common</pattern> <shadedPattern>zhaohui.com.google.common</shadedPattern> </relocation> </relocations> </configuration> </execution> </executions> </plugin> </plugins> </build>要求b-shade使用maven-shade-plugin打包,同时打包的时候规定将com.google.common包名改为zhaohui.com.google.common。然后在c的pom文件中删除b的依赖,改为依赖b-shade.然后在根目录执行mvn package。最后,在c的target目录中执行java -jar package-test-c-1.0-SNAPSHOT.jar,输出如下:开始执行A的代码Object{test=test}A的代码,执行完了,没报错开始执行A的代码 [java.lang.Object@330bedb4]B的代码,执行完了,没报错这样问题就圆满解决了。最后的最后,使用luyten-0.5.3打开package-test-c-1.0-SNAPSHOT.jar,发现b中的import语句已经被修改为import zhaohui.com.google.common.base.*;总结:我只想说:新技能get√最后,让我们保持独立思考,不卑不亢。长成自己想要的样子! (引用自 我非常喜欢的B站up主 ”独立菌儿“->猛戳链接<-的口头禅)
2024年01月10日
53 阅读
0 评论
0 点赞