2023年12月

Spring Framework 是一种流行的开源企业级框架,用于创建在 Java Virtual Machine (JVM) 上运行的独立、生产级应用程序。而Spring Boot 是一个工具,可以让使用 Spring 框架更快、更轻松地开发 Web 应用程序和微服务。随着 Spring Boot 的不断发展,开发人员必须跟上最新的升级和变化。

最近,Spring Boot 宣布发布 3.2.x 版本,该版本带来了多项新功能、错误修复和增强功能,鉴于对 Spring Boot 2.7.x 版本的支持已于 2023 年 11 月 18 日结束,这是一个非常重要且强制性的关注用于将 Spring Boot 应用程序升级到最新的 3.x 版本。

因此,在本文中,我们将讨论如何从 Spring Boot 2.x 迁移到 3.x,以及升级的优势以及开发人员在此过程中可能遇到的潜在困难。

升级指南

1. 升级 JDK 17

Spring Boot 3.0 需要 Java 17 作为最低版本。

如果您当前使用的是 Java 8 或 Java 11,则需要在 Spring Boot 迁移之前升级 JDK。

2. 升级到 Spring Boot 3

查看项目及其依赖项的状态后,请升级到 Spring Boot 3.0 的最新维护版本。

我们将使用 Spring Boot 3.2.0 进行升级。

打开项目的
pom.xml
并更新 Spring Boot 的版本,如下所示。

<parent>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-parent</artifactId>
     <version>3.2.0</version>
</parent>

3. 配置属性迁移

在 Spring Boot 3.0 中,一些配置属性被重命名/删除,开发人员需要相应地更新其
application.properties/application.yml

为了帮助您实现这一点,Spring Boot 提供了一个
spring-boot-properties-migrator
模块。

我们可以通过将以下内容添加到 Maven
pom.xml
来添加迁移器:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-properties-migrator</artifactId>
  <scope>runtime</scope>
</dependency>

4. 升级到 Jakarta EE

由于 Java EE 已更改为 Jakarta EE,Spring Boot 3.x 的所有依赖项 API 也从 Java EE 升级为 Jakarta EE。

简单来说,您需要将所有
javax
的 imports 都替换为
jakarta
。具体如下:

javax.persistence.*   -> jakarta.persistence.*
javax.validation.*    -> jakarta.validation.*
javax.servlet.*       -> jakarta.servlet.*
javax.annotation.*    -> jakarta.annotation.*
javax.transaction.*   -> jakarta.transaction.*

5. 调整
@ConstructorBinding
注解

@ConstructorBinding

@ConfigurationProperties
类的类型级别不再需要,应将其删除。

当一个类或记录有多个构造函数时,它仍然可以在构造函数上使用,以指示应使用哪一个构造函数进行属性绑定。

6. Spring MVC 和 WebFlux的URL匹配更改

从 Spring Framework 6.0 开始,尾部斜杠匹配配置选项已为 deprecated,其默认值设置为 false。

这意味着以前,以下控制器将匹配
GET /health

GET /health/

@RestController
public class HealthController {

  @GetMapping("/health")
  public String health() {
    return "Application is Working";
  }

}

@RestController
public class HealthController {

  @GetMapping("/health")
  public Mono<String> health() {
    return Mono.just("Application is Working");
  }

}

7. RestTemplate 中的 Apache HttpClient

Spring Framework 6.0 中已删除对 Apache HttpClient 的支持,现在由
org.apache.httpcomponents.client5:httpclient5
取代(注意:此依赖项具有不同的 groupId)。

如果您注意到 HTTP 客户端行为存在问题,则
RestTemplate
可能会回退到 JDK 客户端。

org.apache.httpcomponents:httpclient
可以由其他依赖项传递传递,因此您的应用程序可能依赖此依赖项而不声明它。

下面是迁移后的
RestTemplate
示例:

@Configuration
public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate(){

        final SSLConnectionSocketFactory sslConnectionSocketFactory = SSLConnectionSocketFactoryBuilder.create()
                .build();
        final PoolingHttpClientConnectionManager manager = PoolingHttpClientConnectionManagerBuilder.create()
                .setSSLSocketFactory(sslConnectionSocketFactory)
                .build();
        
        final CloseableHttpClient closeableHttpClient = HttpClients.custom().setConnectionManager(manager)
                .build();
        
        final HttpComponentsClientHttpRequestFactory componentsClientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        componentsClientHttpRequestFactory.setHttpClient(closeableHttpClient);
        
        final RestTemplate restTemplate = new RestTemplate(componentsClientHttpRequestFactory);
        return  restTemplate;
        
    }
}

8. 升级 Spring Security

Spring Boot 3.0 已升级到 Spring Security 6.0。

因此,
WebSecurityConfigurerAdapter
已被弃用。 Spring鼓励用户转向基于组件的安全配置。

为了演示新的配置风格,我们使用 Spring Security lambda DSL 和方法
HttpSecurity#authorizeHttpRequests
来定义我们的授权规则。

下面是使用
WebSecurityConfigurerAdapter
的示例配置,它通过 HTTP Basic 保护所有端点:

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((authz) -> authz
                .anyRequest().authenticated()
            )
            .httpBasic(withDefaults());
    }

}

展望未来,推荐的方法是注册一个
SecurityFilterChain
bean:

@Configuration
public class SecurityConfiguration {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((authz) -> authz
                .anyRequest().authenticated()
            )
            .httpBasic(withDefaults());
        return http.build();
    }

}

9. Spring Kafka 模板升级

KafkaTemplate
方法现在返回
CompleteableFuture
而不是
ListenableFuture
,后者已被弃用。

Spring Boot 2.x 中带有
ListenableFuture
的 Kafka 模板:

private RoutingKafkaTemplate routingKafkaTemplate;

public void send(){
    ListenableFuture<SendResult<Object,Object>> future = routingKafkaTemplate.send("Message","topic");

    future.addCallback(new ListenableFutureCallback<>() {
        @Override
        public void onFailure(Throwable ex) {
            log.error(ex);
        }

        @Override
        public void onSuccess(SendResult<Object, Object> result) {
            log.info("success");
        }
    });
}

Spring Boot 3.x 中带有
CompletableFuture
的 Kafka 模板:

private RoutingKafkaTemplate routingKafkaTemplate;

public void send() {
    CompletableFuture<SendResult<Object, Object>> future = routingKafkaTemplate.send("Message", "topic");
    future.thenAccept(log::info)
            .exceptionally(exception -> {
                log.error(exception);
                return null;
            });
}

10. Spring Doc OpenAPI 升级

springdoc-openapi
用于为Spring Boot 项目自动生成 API 文档。

springdoc-openapi
的工作原理是在运行时检查应用程序,以根据 spring 配置、类结构和各种注释推断 API 语义。

对于 spring-boot 3 支持,请确保使用 springdoc-openapi v2。

WebMVC 项目的 Spring Doc OpenAPI 升级

对于 WebMVC 项目,您需要在
pom.xml
. 文件中包含以下依赖项。

<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
    <version>2.3.0</version>
</dependency>

WebFlux 项目的 Spring Doc OpenAPI 升级

对于 WebFlux 项目,您需要在
pom.xml
. 文件中包含以下依赖项。

<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-starter-webflux-ui</artifactId>
    <version>2.3.0</version>
</dependency>

今日分享就到这里,感谢阅读!如果您学习过程中如遇困难?可以加入我们超高质量的
Spring技术交流群
,参与交流与讨论,更好的学习与进步!更多
Spring Boot教程可以点击直达!
,欢迎收藏与转发支持!

欢迎关注我的公众号:程序猿DD。第一时间了解前沿行业消息、分享深度技术干货、获取优质学习资源

从Demo入手,了解Paimon/Flink项目搭建的全过程。记录下采坑之旅。

创建Flink项目

在IDEA中创建Flink项目,由于没有Flink的archetype,因此需要手动创建一下。
参考:
idea快速创建flink项目
,至此Flink的项目框架就搭建起来了。
注意:必须注释掉pom文件中的
provided
;否则运行时会报错:
Error: A JNI error has occurred, please check your installation and try again
image.png

搭建Flink伪集群


Flink包地址
中,选择对应的版本,下载文件
image.png
解压后,其文件内容,如下
image.png
在bin目录下,运行start-cluster.bat脚本即可。打开浏览器访问:localhost:8081,就可以查看Flink的webui
image.png

高版本的Flink中已经没有bat脚本,可参考
flink新版本无bat启动文件的解决办法

补充缺失的依赖

Flink的框架搭建好之后,参考
新一代数据湖存储技术Apache Paimon入门Demo
写一个简单的Paimon程序。但在这个过程中,必须补充 缺失的POM依赖。而这些依赖在编译时并不会报错,一旦运行,各种各样的抛错:
java.lang.ClassNotFoundException: org.apache.hadoop.conf.Configuration
Unable to create catalog xxx
Unsupported SQL query! executeSql()
如下是所有需要的pom依赖:

<dependency>
  <groupId>org.apache.flink</groupId>
  <artifactId>flink-streaming-java</artifactId>
  <version>${flink.version}</version>
  <!--			<scope>provided</scope>-->
</dependency>
<dependency>
  <groupId>org.apache.flink</groupId>
  <artifactId>flink-clients</artifactId>
  <version>${flink.version}</version>
  <!--			<scope>provided</scope>-->
</dependency>
<dependency>
  <groupId>org.apache.flink</groupId>
  <artifactId>flink-table-api-java-bridge</artifactId>
  <version>1.18.0</version>
</dependency>
<dependency>
  <groupId>org.apache.paimon</groupId>
  <artifactId>paimon-flink-1.18</artifactId>
  <version>0.6.0-incubating</version>
</dependency>
<dependency>
  <groupId>org.apache.flink</groupId>
  <artifactId>flink-table-planner-loader</artifactId>
  <version>${flink.version}</version>
</dependency>
<dependency>
  <groupId>org.apache.flink</groupId>
  <artifactId>flink-table-runtime</artifactId>
  <version>1.18.0</version>
</dependency>
<dependency>
  <groupId>org.apache.flink</groupId>
  <artifactId>flink-connector-base</artifactId>
  <version>${flink.version}</version>
</dependency>

<!-- Add connector dependencies here. They must be in the default scope (compile). -->

<!-- Example:

<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-connector-kafka</artifactId>
<version>3.0.0-1.17</version>
</dependency>
-->

<!-- Add logging framework, to produce console output when running in the IDE. -->
<!-- These dependencies are excluded from the application JAR by default. -->
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-slf4j-impl</artifactId>
  <version>${log4j.version}</version>
  <scope>runtime</scope>
</dependency>
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-api</artifactId>
  <version>${log4j.version}</version>
  <scope>runtime</scope>
</dependency>
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-core</artifactId>
  <version>${log4j.version}</version>
  <scope>runtime</scope>
</dependency>
<dependency>
  <groupId>org.apache.hadoop</groupId>
  <artifactId>hadoop-common</artifactId>
  <version>3.2.3</version>
</dependency>
<dependency>
  <groupId>org.apache.hadoop</groupId>
  <artifactId>hadoop-hdfs-client</artifactId>
  <version>3.2.3</version>
</dependency>

摘要:MacOS下免密登录的一些注意事项。

系统环境
操作系统:macOS Sonoma 14.2.1

SSH免密登录
ssh免密登录的原理是在本机生成本机的ssh公钥和私钥,将公钥上传至待连接的主机,本机通过私钥进行ssh连接实现免密登录。

# ssh密钥生成命令
ssh-keygen
# ssh上传(复制)命令
# ssh-copy-id格式:ssh-copy-id -i 私钥 远程主机用户名@远程主机IP
# ssh-copy-id命令示例
ssh-copy-id -i ~/.ssh/id_liupp root@192.168.8.187
# ssh登录
# 命令格式: ssh -i 私钥 远程主机用户名@远程主机IP
# ssh登录示例:
ssh -i ~/.ssh/id_liupp root@192.168.8.187

关于这两个命令的具体用法可以通过搜索引擎查询.

# ssh免密连接命令
ssh root@IP

回车后仍然提示输入密码,通过搜索引擎查询,得出的结果是mac系统下需要使用“ssh-add”命令将私钥添加至ssh-agent高速缓存:

# ssh-add 命令格式
# ssh -add -K 私钥
# 示例:
ssh -add -K ~/.ssh/id_liupp
但输入后提示:

WARNING: The -K and -A flags are deprecated and have been replaced
         by the --apple-use-keychain and --apple-load-keychain
         flags, respectively.  To suppress this warning, set the
         environment variable APPLE_SSH_ADD_BEHAVIOR as described in
         the ssh-add(1) manual page.

释义为-K参数对于Mac来说已经过期,需要将“-K”参数换成“–apple-use-keychain”:

# ssh-add 命令格式
# ssh -add -K 私钥
# 示例:
ssh-add --apple-use-keychain ~/.ssh/id_liupp

添加成功后再在终端执行 “ssh root@IP”即可实现免密登录。

存在问题及解决方案
经过使用发现一个问题,即是在本机重启后,免密登录会失效,经查询得知,ssh-add将私钥添加到高速缓存,但缓存在重启后会失效,需要每次重启后重新添加,在mac下的解决方案是:

1.在“应用程序”中的找到“自动操作”应用(或CTRL+SPACE)搜索自动操作
2.打开后默认弹出选择文件对话框,点击“取消”,点击启动栏的自动操作图标,“选取文稿类型”中选择“应用程序”:
3.左侧“资源库”选择“实用工具”,双击右侧的“运行shell脚本”将ssh-add命令复制至运行脚本脚本中,点击标题栏左侧的“未命名”,起个名字(这里命名为add-ssh-key)并保存至指定位置。
4.打开“系统设置”,左侧搜索栏搜索“登录项”,在“登录项”的“登录时打开”中将保存的自动执行程序(add-ssh-key)添加进来.
5.重启后验证,至此配置完毕。
6.操作步骤图示见下方:



本文作者: Mr Liu
本文链接:
https://it-liupp.gitee.io/2023/12/25/mac-ssh-autologin/
博客园链接:
https://www.cnblogs.com/boyliupan/p/17934079.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

00后程序员,2023年终总结

作为一个00后程序员,我回顾了过去三年的工作经历。我来自湖南衡阳,虽然互联网上常常开玩笑说我们00后炒主管、炒老板,但实际上我们也在不断努力变得更强。最近两年我没有写博客,不是因为懒,而是我荣升为了一位爸爸,肩上的责任更重了,工作上也需要积极主动承担自己的职责,顺便开发一个练手的物联网项目。

工作的三年

2020年中旬,我还在深圳的一家公司从事机房环境动力监控的工作。当时我在翻看手机时偶然看见了深圳房价,这让我望而却步,经过长时间的思考和斟酌,最后还是决定回长沙买房定居。长沙之前需要有两年的社保缴纳才有资格进行购房,在2023年9月之后政策放宽了(而且现在首付只需用20%,无需社保就可以进行购房)。在深圳的这几年中我也感受到了城市带来的热血和快节奏的生活,工资相对来说也比较高(但我记得自己当时在深圳实习时的工资也只有3.5k),经过一次跳槽,我的工资涨到了以w为单位。我第一时间给妈妈打电话,颠覆了她对我的认知。

开始打工
刚开始工作时,我经常浏览博客园,渴望获取知识。我盲目地追求技术,经常看到大佬们在群里讨论某个技术,我就立即去学习,但只是学会了如何使用,对技术原理一无所知。我像一只无头苍蝇一样,刚刚毕业时看到别人在讨论微服务网关(Ocelot),就参考别人的博客写了一个Demo,觉得自己可以了。现在回想起来,我当时有点幼稚。实习半年后,我意识到高大上的东西并不实用,工作中更需要关注业务理解和编码基础。于是我在B站学习了C#的基础知识,才发现学校没有教过的特性、反射、拦截器、委托、表达式目录树等等。实习后半年,我一直在加强基础知识,每学会一个知识点,都感到非常清爽。原来这才是我渴望的知识。在工作中遇到一些技术难题时,我也能游刃有余。后来,我开始学习C#内置方法和一些优秀的项目的源码。我将学到的知识点写成博客,以防忘记,并养成了编写博客的良好习惯。

我跳槽
在那里实习了一年结束实现期。我还记得技术总监找我谈话,说我表现很好,公司对我的能力非常认可,将我的工资从之前的3.2k涨到了6k。但是告诉我实习期结束后会有三个月的试用期,工资只有80%。我对此感到不高兴,但没有说出来,而是去外面面试。在准备简历的这几天里,公司突然提前给我转正了,但已经晚了,我的简历都已经准备好了。于是我出去面试,当时我拿到了4个offer,最低的工资都达到了8k,我还干个毛,上午签完转正合同,下午提离职 光速离职进行中,南山西丽报道去。

新公司
在新的公司,我结识了新朋友,至今我们仍保持联系。我的领导非常好,经常与我保持联系,帮助我解答困惑。我们使用的技术非常新颖,我第一次接触到了微服务。我们为XX银行开发了一套机房环境动力监控系统,学习了很多新技术,如Redis、CAP、Kafka等微服务架构。我们编写了xshell脚本,实现了一键部署,因为我们需要将系统部署到全国各地的XX银行机房,这样实施人员只需要拷贝安装包,执行安装脚本,就可以下班了。在这里,我学到了很多东西,特别感谢我的领导。说实话,我也不清楚为什么最后离职了。公司在西丽有宿舍,不用支付水电费,基本上只需要自己负责吃饭,基本上没有什么花销。领导对我也非常好,现在回想起来还有点迷茫。最后,我只能归结为我想回长沙买房,本来我计划买房后回深圳,但现在有了孩子,所以不舍得哈哈。

回长沙打工
回到长沙后,我加入了一家加班很严重的公司。基本上每天工作时间都在11个小时左右,整个部门的开发人员都是如此。由于与直接领导
理念不合
,我在这家公司工作了8个月后最终选择离开。实际上,我理解大家都想向上爬,追求更高的收入。我们很多人也知道这种加班的状态不可持续,但没有人能够改变这种环境,最后大家都随波逐流,被加班文化卷走。

结婚&生子

2022年6月23日和我老婆办理了结婚手续,2022年11月19日迎接了可爱的女儿的诞生

是的,我是奉子成婚的。实话实说,当我得知自己即将成为父亲时,我真的很迷茫。我曾经想过要不要做人流,因为我担心自己无法承担起一个家庭的重任。但是,经过深思熟虑,我决定承担起这份责任,成为一个父亲。在2022年11月19号,我迎来了自己的小棉袄。那天,我一直守在老婆的床边,看着她和孩子睡觉,直到凌晨4点才想起来自己还没吃晚饭。那一天,我真的很开心,也很激动。

买房&装修

因为我买的是二手房,装修我是自己找人装修的,就结合我自身理解,讲一些个人建议。

买房

我一直关注着长沙的房价,平均价格在1w左右,我自己回长沙租住在荣盛的一个小区,三房两卫一厅一车位每月2330元,居住了一年多对这个小区还是比较满意的。我在安居客上查看小区均价在8.5k左右,当时我觉得这个价格还算低的,我原本计划着存30w首付,买一个100平的房子,看到这个价格我就有提前买房的冲动了(首付还没有存够)。我联系了一位中介带我去看房,我们小区的房子有的人挂8k/8.5k/1w/1.1w,其实这些价格都是他们自己高估值,都可以砍价。开始时我这个房子113平90w,挂了几个月都没有成交,后来减少到85w,但是卖家想尽快回款,让我使用商贷少一万,就是84w,当时我们就去中介公司谈了一下,我觉得这个价格还可以再少一些,我就直接说83w,如果可以就现在签合同(房子的户型是我和我老婆很喜欢的),从看房子到签合同只用了一周时间就成功上车了。

我们小区我经常看法拍房有一次我没有钱97平 65w被别人一拍拿下了。买二手房需要关注房子是不是满五唯一,满五唯一不需要个税,可以省1w多。
不过现在看来我卖这个房子并没有优惠多少,买的还是比较急了,现在长沙放开了房产证满4年就可以交易,我们小区最近120+多套挂牌销售,之前只有一期的房子满五年了。买完房之后也听我老婆说小区有人因为缺钱,把自己装修好的房子按照购房时候的价格出售了,现在我们小区挂牌价也到了8k左右了,说明小区急卖的多了,卖方着急用钱,就不会对自己的房子抱有一个高估值。可以看看法拍房的估值价格,知道这个小区市场低价是多少,根据自己谈判增加金额,我感觉我这个房子当时说80w也可以买到,因为房东缺钱,急需回款。房子成交价格是83w 中介公司收取2%手续费,还想收我金融手续费就是帮忙贷款的费用2%,我当时就不愿意了,我们可以自己找银行进行贷款,为啥你帮我贷款还要收我1w多,中介一直说防止征信最后贷款下不来,定金就收不回了,我的征信这么好,我发泡反正就是不听。最后就是我自己在招商银行进行贷款的,省了1w多,其实中介收取的2%手续费也可以谈,我不懂吃了亏,因为这个房子其实在很多中介都挂了,那家给我更低找那家签就好了,还有就是其实如果可以自己找到一手卖方,就不要走中介公司省掉手续费,如果你足够勤快,中介其实都不用,中介只是利用信息差赚钱。一开始我自己找了一手卖家相同的户型110平二期送车位,房产证满4年,没有满5年不能过户,只需要83.8w,我不敢买,但是最近放开正常房产证满4年就可以过户了,不然我自己找的才是最好的选择。

为什么大家都是买房买房,没说要装修呀(装修花费可以再付一套首付了)
我刚刚买完房子,也是想找装修公司,装修但是报价全包都是20W+ ,本来想半包给装修公司但是一般别人不愿意接半包利润太少,不愿意做,我就自己就没日没夜的在抖音,B站查看清包(自己找装修工人),周末的时候就和老婆在小区溜达,留意别人装修工人信息,最后磕磕绊绊的花了17w把房子的事情弄好了。

幸福时刻

日请求量1亿+的物联网项目

这个已经是已经很成熟的行业了,我只是因为朋友自己的公司不喜欢用别人公司系统,而开发的。2022年正式立项一共开发了两个版本V1版本,V2版本。从一开始投入100个用户进行测试,到现在100w用户,30w+在线用户,前端&后端都是我一个人编写,两年的时间我呼吸过无数个凌晨的空气,在不同用户体量级别,我也遇到过多次挑战。

技术栈(Mysql & ES & Redis & Minio 都是自建服务)

1.前端: Uniapp 编写H5 Vue3 编写管理后端
2.后端: .Net 6 .Net 7 Java
3.数据库: Mysql + FreeSql
4.网关: ApiSix + Nginx
5.缓存: Redis + FreeRedis
6.大数据存储: Elasticsearch
7.APM:Skywalking
8.消息中间件:Kafka
9.部署环境:Linux + Docker
10.自动发布:Shell 脚本
11.定时任务:Quartz
12.设备交互协议:Mqtt Http
13.文件存储:Minio

遇到过的问题

Http协议设备通讯5秒一次交互击溃服务

一开始我们上线的设备是http 协议进行设备信息交互,这个厂家默认心跳是5秒一次,一开始上线10,100,1000个用户就发现问题,服务假死,Swagger 页面都打不开。这个问题差点的就击溃了我的道心,解决方案是控制设备心跳时间设置为3分钟,但是厂家的程序员有点傻,自己的文档写了设置心跳指令,最后自己居然没有实现,最后使用MemoryCache 缓存针对设备进行限流,3分钟之内只能通过一个请求,最后这家厂商上线5k设备,我就要商家换厂家了哈哈。换成支持Mqtt协议的厂家

MQTT设备流量服务内存激增

当用户日活体量到W级别的时候,出现服务器内存报警,我发现32G内存占用99%,我所有服务全部容器化了,使用
docker stats
命令查看到
设备流量服务
占用20G内存,我直接重启了该服务内存占用马上就下来了,但是过了一个晚上,我再看
设备流量服务
内存又到13G了,之前在园子里也经常看,别人定位某个服务假死&内存&CPU飙升案例。
Dockerfile文件
添加安装 dotnet-dump&dotnet-trace

RUN dotnet tool install -g dotnet-dump \
    && dotnet tool install -g dotnet-trace

进入容器内部
docker exec -it {容器Id} /bin/bash
查看容器内部运行进程Id
dotnet-dump ps
通过指定的进程id创建dump文件
dotnet-dump collect --type heap --process-id <ProcessId>
我将dump 包放在本地,直接使用VS 打开分析,发现MQTT消息持有了10G占用,也就是说我的内存都是被MQTT 消息吃掉了,查看kibana面板发现设备消息消费出现了延迟了几个小时。
优化之前的代码:

          _mqttClient.ApplicationMessageReceivedAsync += arg =>
          {
            // .....消息消费代码....
          }

单个线程排队消费消息,那我肯定是加线程呀,直接冲就完了。
优化之后的代码:

        _mqttClient.ApplicationMessageReceivedAsync += async arg =>
        {
            await semaphore.WaitAsync();
            _ = Task.Run(async () =>
            {
                  // .....消息消费代码....
            }).ConfigureAwait(false);
            return;
        };

确实在这一段时间内,解决了内存激增的问题了。

学习链接:
https://www.cnblogs.com/huangxincheng/p/17865096.html

Redis 服务不可用

好景不长,我看商家一天几千单的卖,日活用户很快突破10w大关,端午节的一个中午,我收到了系统服务告警通知,
设备流量服务
挂了,服务心跳接口访问卡死,kibana面板没有日志输出了,我进入docker 容器内部一直提示
【XXX】Next recovery time: 05/20/2023 15:14:41 (Connect to redis-server(XXX) timeout)
【XXX】Next recovery time: 05/20/2023 15:15:06 (Connect to redis-server(XXX) timeout)
【XXX】Next recovery time: 05/20/2023 15:15:31 (Connect to redis-server(XXX) timeout)
【XXX】Next recovery time: 05/20/2023 15:14:56 (Connect to redis-server(XXX) timeout)

直接痛苦面具出来了,重启服务都没有用,进行了很多测试,一直怀疑是Csredis 的问题,各种连接参数调整,都没有作用,后面讲CsRedis全部换成FreeRedis,还是不行裂开(StackExchange.Redis 也尝试过),最后删除
Task.Run(()=>{})
单线程执行,启动多个
设备流量服务
,修改设备上送时间为10分钟一次。这个问题尝试了半个月的测试,最后定位为线程开启过多了,最后代码修改为

        // 开始一个80个线程信号量,控制可以进入多少个线程
        var semaphore = new SemaphoreSlim(80);
        _mqttClient.ApplicationMessageReceivedAsync += async arg =>
        {
            await semaphore.WaitAsync();
            _ = Task.Run(async () =>
            {
                try
                {
                   // 处理代码
                }
                catch (Exception e)
                {
                  // 处理代码
                }
                finally
                {
                    // 归还线程
                    semaphore.Release();
                }
            }).ConfigureAwait(false);
            return;
        };

Csredis Issues
FreeRedis Issues

支付回调失效(查单补偿)

我们需要开启一个定时任务异步查询微信订单接口进行补偿。V1 版本系统主要依赖微信异步回调请求,接收到支付成功信息。但短板在于,如果微信没有支付成功的异步回调,订单就无法正常完成。之前客服反馈过,V1 版本过于依赖微信支付成功主动通知,如果异步回调通知
notify_url
不可用,支付通知将永远无法收到。

参考地址

Mysql 数据库连接耗尽

这个问题也是最开始自建mysql,当体量剧增出现的问题
Too many connections
mysql 默认最大链接数是151,允许的最大连接数是 16384,问题就是当前系统运行需要占用更多的链接数,处理这个问题我们只需要调整Mysql 最大链接数数量,设置服务链接字符串
Max pool size

max_connections 设置多少合适?

理想公式:

服务器响应的最大连接数值占服务器上限连接数值的比例值在10%以上,如果在10%以下,说明mysql服务器最大连接上限值设置过高。
查看服务器响应最大连接数
show global status like 'Max_used_connections';

验证最大连接数值是否合理
Max_used_connections / max_connections = 215/1000 ≈ 21.5%

Mysql 主从模式延迟过高【未解决】

我使用的是binglog 订阅进行主从同步的,目前这个问题没有解决,暂时先挖一个坑

Uniapp H5 提示网络不可用请刷新

当系统用户越来越多了,就有客服反馈h5出现,如下的错误页面,一般让客户刷新页面就可以正常显示,但也有客户死活不行,最后压力给到我这边。最后根据官方给出解释,我将前端协议改成Https 协议就好了

官方解决方案

ApiSix 无法使用Https协议

这个真的很坑人,因为之前的问题,我必须让前端使用https协议,但是我的网关协议是http,而且走的是9080端口。我按照官方文档尝试了很多方法,但都不行。后来我发现ApiSix的9443端口是https协议,我就配置了证书,但是一直不生效,这个问题困扰了我好几天。最后我在GitHub上提问,有个建议让我升级到最新版本,这样就解决好了。
Issues

展望未来工作的第六年

回想工作的这三年,从行业窥探者转变为行业前行者,从行业小白到行业大白,刚工作时曾经也幻想过,三年后的自己,技术是不是很厉害了,自己有没有买车,自己有没有买房,自己有没有月薪过W,自己有没有女朋友,自己有没有一夜暴富。

三年前的自己,看现在的自己,一定会感到自豪吧,从两袖清风,到裤带空空也是一种幸福,在这里我想对三年后的自己说,希望能够一直保持着热情&积极且主动,保持着一颗学习的心,对于技术保持一颗追求原理精神,自己也需要多学习关于技术以外的知识,自己多抽出一些时间陪伴家人。

三年后的自己立下Flag

  • 报考驾照
  • 买车
  • 看20本书(技术或者软实力)
  • 自己的技术更有深度
  • 保持运动(目前是每天自行车通勤)
  • 物联网卡系统能够盈利

随着 2024 年的到来,在不断进步的业务格局以及对高效、可扩张且可靠的数字平台日益增长的需求的推动下,平台工程领域不断发展。它塑造了组织构建、部署和管理其软件和基础设施的方式。在本文中,我们将深入探讨 2024 年平台工程这一动态领域的主要趋势和实践。

平台工程概述

平台工程能够支持软件应用程序的底层基础设施和服务的设计、开发和维护。它涵盖了一系列技术,包括云计算、容器化、微服务架构和自动化工具。平台工程的目标就是
创建一个强大而灵活的基础,以实现快速应用程序开发、无缝部署和高效运营

2024 年平台工程的关键组成部分

随着平台工程的演进,其组成部分也变得越来越完善和清晰。企业将根据自身业务目标和需求来选择关键组成元素。在2024年,平台工程的关键组成部分将包括但不限于:

  • 云原生技术
    :平台工程与云原生技术紧密结合,使组织能够
    利用云计算的优势
    ,例如可扩展性、弹性和成本效率。Kubernetes、Docker 和无服务器计算是现代平台工程不可或缺的组成部分。

  • 微服务架构
    :将应用程序分解为
    更小的、独立的
    微服务仍然是平台工程的基本原则。这种方法增强了敏捷性、可扩展性以及独立更新和扩展各个组件的能力。

  • DevOps 和持续集成/持续部署 (CI/CD)
    :自动化是平台工程的基石,DevOps 实践以及 CI/CD 流水线发挥着至关重要的作用。自动化
    简化了开发和部署流程,减少了人工干预并最大限度地降低了错误风险

  • 可观察性和监控
    :主动监控和可观察性对于维护平台的健康和性能至关重要。到 2024 年,先进的监控工具、人工智能驱动的分析和可观察性实践有助于更快地检测和解决问题。

  • 设计安全
    :随着数字生态系统日益复杂,安全性成为平台工程的重中之重。安全措施已集成到开发和部署管道中,DevSecOps 等实践
    可确保采用全面且持续的安全方法

趋势塑造平台工程

科技领域发展日新月异,更多技术被整合和应用到平台工程中。例如:

  • 边缘计算
    :随着组织努力减少延迟并提高性能,边缘计算在平台工程中越来越受到重视。将计算资源分布在更靠近网络边缘的位置可以增强应用程序的实时处理能力。

  • 人工智能和机器学习集成
    :平台越来越多地整合人工智能和机器学习功能,以优化资源分配、预测故障和自动化决策过程。

  • 多云和混合部署
    :平台工程师正在探索多云和混合部署策略,以避免供应商锁定、增加冗余并根据特定工作负载要求优化成本。

  • 不可变基础设施
    :不可变基础设施的概念正在获得关注,其中基础设施组件被替换而不是修改。这种方法增强了不同环境下的可靠性、再现性和一致性。

增强开发人员体验是核心重点

到 2024 年,平台工程师在弥合开发和运营之间的差距方面将发挥关键作用。他们负责设计可扩展且有弹性的架构、实施自动化、确保安全合规性并培育持续改进的文化。

同时,开发人员体验(DX)也将成为 2024 年的中心议题。重点正在从仅仅构建和部署软件转向使这些流程更加直观、高效,并让开发人员感到愉悦。
由于平台工程的核心是增强开发人员的能力
,提升他们的体验比以往任何时候都更加重要。这不仅与工具有关,还与创建一个让开发人员更加自主的生态系统有关。

在推动更好的 DX 的过程中,我们将看到更直观的界面、简化的工作流程以及工具之间更深入的集成。我们的目标是减少认知过载和上下文切换,使开发人员从构思到部署的过程更加顺畅。

IDP 将成为技术组织核心

并且,内部开发人员平台(IDP)将成为科技公司的中坚力量,提供一种自助服务模式,满足现代开发人员对自主性和效率的需求。这些平台囊括了最佳实践,使重复性任务自动化,并
提供了一种标准化的部署和管理应用程序的方式

IDP 不仅仅是工具,还代表着
组织文化的转变
。它们鼓励自主权和问责制,同时促进创新。据预测,到 2024 年,
IDP 将成为大多数技术组织的核心,大大缩短新功能和新产品的上市时间

Kubernetes 演变推动用户友好特性

Kubernetes 已成为现代基础设施的基石,其采用率在 2024 年将继续飙升。不过,重点将是使 Kubernetes 更便于用户使用。因为管理 Kubernetes 的复杂性一直是一个重大障碍,现在越来越需要为最终用户解决这种复杂性。

Kubernetes 工具的更多进步旨在
提供更简单的界面和更自动化的流程
,其目标是方便开发人员利用 Kubernetes 的强大功能。这种演进将使得更多开发人员更容易获得云原生技术方面至关重要的突破。

临时环境的采用

临时环境将可能在 2024 年改变游戏规则。这些临时、孤立的环境非常适合在新功能、错误修复或任何变更合并到主代码库之前对其进行测试。它们提供了一个安全的实验空间,不会影响生产环境。

临时环境能够
加快开发周期并提高代码质量
,这将推动短暂环境的采用。它们与持续集成和持续部署(CI/CD)的原则完美契合,能够实现更快的反馈循环和更高效的开发团队协作。

结论

随着技术不断进步,2024年的平台工程无疑仍将是 IT 领域创新和效率的关键驱动力。而且,它正朝着创建更加以开发人员为中心、高效和敏捷的环境方向发展。对增强开发人员体验的重视、内部开发人员平台的兴起、Kubernetes 的发展以及对短暂环境的采用都表明了这一趋势。

这些进步标志着我们构建和交付软件的方式发生了文化转变。现在的重点是增强开发人员的自主性和生产力,从而推动创新并加快业务增长。相信采用现代平台工程实践的组织也能够更好地应对数字环境的复杂性、缩短上市时间并提供卓越的用户体验。

参考链接

  1. https://ammarsuhail155.medium.com/defining-platform-engineering-in-2024-navigating-the-landscape-of-modern-it-c2eb293a62c5
  2. https://www.qovery.com/blog/platform-engineering-predictions-for-2024