graalvm+spring-cloud-gateway打造又快又小的类nginx本地网关

news2024/11/19 13:30:12

前言

网关是微服务架构的入口,外网请求通过网关转发到独立的微服务。项目一般会经过多个环境的测试,最终发布到生产。一个http请求,如:http://public_host/api/v1/some_service/some_path?a=b&c=d会先经过公网域名,然后通过nginx匹配路径/api/v1/**把请求转发到相应的网关,网关再转发给对应服务。

本地开发时,一般会采用idea的Tools->HTTP Client->Create Request in HTTP Client工具来调试本地接口(http://localhost:8080/some_path?a=b&c=d),发布测试环境后,用postman来调试测试环境接口(http://public_host/api/v1/some_service/some_path?a=b&c=d);也就是说,本地开发时在idea中写的接口测试文档,等发布到测试环境后,又要再写一遍。如果本地有一个网关,提供基本的转发功能,就能打通本地和测试环境的隔阂:一份接口测试文档,多个环境使用。

本地搭一个网关,方式有很多:

  1. idea起一个spring-cloud-gateway项目:优点是简单易操作,可定制,缺点启动速度慢,占用内存高;
  2. 下载一个nginx服务器,本地起一个nginx服务,用于转发请求:也比较简单,内存也不高,缺点要阅读文档,不能修改代码来自定义;
  3. 用graalvm把spring-cloud-gateway编译成本地exe:springcloud项目,学习成本低,转发逻辑可以自定义,按需修改;本地镜像,启动快,占用内存低。

实践环节

准备工作

  1. 安装graalvm以及native-image
  2. 安装Visual Studio 2022 Developer Command Prompt v17.4.3

创建spring-cloud-gateway项目

添加下面几个依赖项:

  1. GraalVM Native Support
  2. Spring Reactive Web
  3. Gateway
  4. Spring Boot Actuator(监控端点,可选)

完整的pom文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.0.1</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>io.github.xxx</groupId>
    <artifactId>cloudgateway</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>cloudgateway</name>
    <description>cloudgateway</description>
    <properties>
        <java.version>17</java.version>
        <spring-cloud.version>2022.0.0</spring-cloud.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.graalvm.buildtools</groupId>
                <artifactId>native-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

配置文件配置了跨域和一个路由,调整了日志级别,代码如下:

server:
  port: 9090
spring:
  application:
    name: cloudgateway
  cloud:
    gateway:
      globalcors:
        add-to-simple-url-handler-mapping: true
        cors-configurations:
          '[/**]':
            maxAge: 3600
            allowCredentials: false
            allowedOrigins: "*"
            allowedMethods: GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS,TRACE
            allowedHeaders: "*"
            exposedHeaders: Content-Length,content-disposition
      routes:
        - id: path_route
          uri: http://127.0.0.1:8080
          predicates:
            - Path=/api/v1/**
          filters:
            - StripPrefix=3
logging:
  level:
    org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory: trace

https://start.spring.io网站创建的项目模板有一个HELP.md,提供了很多有用的信息。

开始编译

打开Visual Studio 2022 Developer Command Prompt v17.4.3,切换到项目目录,执行:

 mvnw.cmd native:compile -Pnative -DskipTests

估计有10来分钟,先喝杯咖啡。

查看结果

项目target目录下,生成了一个cloudgateway.exe文件,双击打开,正常运行。

仿照上面流程又编译了一个普通的spring-boot项目(只包含一个接口和actutor端点),名叫demo.exe,双击打开,正常运行。

在浏览器输入一个请求发给网关转发,发现报错如下:

Caused by: java.lang.NullPointerException: null
        at java.base@17.0.5/sun.net.dns.ResolverConfigurationImpl.stringToList(ResolverConfigurationImpl.java:69) ~[na:na]
        at java.base@17.0.5/sun.net.dns.ResolverConfigurationImpl.loadConfig(ResolverConfigurationImpl.java:136) ~[na:na]
        at java.base@17.0.5/sun.net.dns.ResolverConfigurationImpl.nameservers(ResolverConfigurationImpl.java:159) ~[na:na]
        at jdk.naming.dns@17.0.5/com.sun.jndi.dns.DnsContextFactory.serversForUrls(DnsContextFactory.java:149) ~[cloudgateway2.exe:na]
        at jdk.naming.dns@17.0.5/com.sun.jndi.dns.DnsContextFactory.getContext(DnsContextFactory.java:81) ~[cloudgateway2.exe:na]
        at jdk.naming.dns@17.0.5/com.sun.jndi.dns.DnsContextFactory.urlToContext(DnsContextFactory.java:120) ~[cloudgateway2.exe:na]
        at jdk.naming.dns@17.0.5/com.sun.jndi.dns.DnsContextFactory.getInitialContext(DnsContextFactory.java:64) ~[cloudgateway2.exe:na]
        at java.naming@17.0.5/javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:732) ~[cloudgateway2.exe:na]
        at java.naming@17.0.5/javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:305) ~[cloudgateway2.exe:na]
        at java.naming@17.0.5/javax.naming.InitialContext.init(InitialContext.java:236) ~[cloudgateway2.exe:na]
        at java.naming@17.0.5/javax.naming.InitialContext.<init>(InitialContext.java:208) ~[cloudgateway2.exe:na]
        at java.naming@17.0.5/javax.naming.directory.InitialDirContext.<init>(InitialDirContext.java:130) ~[cloudgateway2.exe:na]
        at io.netty.resolver.dns.DirContextUtils.addNameServers(DirContextUtils.java:49) ~[na:na]
        at io.netty.resolver.dns.DefaultDnsServerAddressStreamProvider.<clinit>(DefaultDnsServerAddressStreamProvider.java:53) ~[na:na]
        ... 145 common frames omitted

百度了半天,找到了报错原因:原来是HttpClient没有配置默认的地址解析器。配置方法如下:

@Bean
public HttpClientCustomizer httpClientResolverCustomizer() {
    return httpClient -> httpClient.resolver(DefaultAddressResolverGroup.INSTANCE);
}

再次编译结束,双击运行正常,转发请求也正常。

内存对比

exe运行内存如下:
占用内存
idea运行内存如下:
idea占用内存

至此graalvm编译spring-cloud-gateway就算完成了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/163358.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ThinkPHP5.x未开启强制路由(s参数)RCE

官方公告&#xff1a;https://blog.thinkphp.cn/869075 由于框架对控制器名没有进行足够的检测会导致在没有开启强制路由的情况下可能的getshell漏洞&#xff0c;受影响的版本包括5.0和5.1版本 ThinkPHP5基础 环境搭建 官网直接下载完整包 https://www.thinkphp.cn/down/870.…

ElasticSearch集群架构及底层原理

前言ElasticSearch考虑到大数据量的情况&#xff0c;集群有很多的部署模式&#xff0c;本篇不会具体进行演示了&#xff0c;只是说明一下有哪些架构可以选&#xff0c;及一些原理的简单介绍&#xff0c;如果要看具体操作的那么可以自行进行搜索&#xff0c;这不是本篇博客要介绍…

OCR文字识别软件哪个好?7大文字识别软件

由于从各种文档中提取文本的需求非常普遍&#xff0c;许多办公软件或公司都提供了OCR工具。在本文中&#xff0c;我们为您推出了一系列功能强大且易于使用的最佳 OCR 软件。 什么是 OCR 软件&#xff1f; OCR 软件是一种程序或工具&#xff0c;可以使用光学字符识别技术识别数…

小红书数据分析网站:揭晓普通博主1个月涨粉百万的密码!

导语&#xff1a; 随着2023年的来临&#xff0c;回首小红书动态&#xff0c;行业热度依旧高涨&#xff0c;越来越多的达人涌入小红书。在时尚领域&#xff0c;更是出现了如氧化菊这样的大势变装博主&#xff01;短短一周涨粉13W的变装博主为何能突围&#xff0c;强势吸睛呢&am…

[LCTF]bestphp2022安洵杯 babyphp

目录 <1> [LCTF]bestphp‘s revenge SoapClient触发反序列化导致ssrf serialize_hander处理session方式不同导致session注入 crlf漏洞 <2> 安洵杯 babyphp SoapClient 触发ssrf session反序列化 利用文件操作原生类读取flag <3> XCTF Final Web1 解…

Spring Security 解析(六) —— 基于JWT的单点登陆(SSO)开发及原理解析

Spring Security 解析(六) —— 基于JWT的单点登陆(SSO)开发及原理解析 在学习Spring Cloud 时&#xff0c;遇到了授权服务oauth 相关内容时&#xff0c;总是一知半解&#xff0c;因此决定先把Spring Security 、Spring Security Oauth2 等权限、认证相关的内容、原理及设计学习…

[极客大挑战 2019]Secret File

目录 信息收集 解题思路 信息收集 先看源码&#xff0c;发现一个php文件 <a id"master" href"./Archive_room.php" style"background-color:#000000;height:70px;width:200px;color:black;left:44%;cursor:default;">Oh! You found me&…

9.2 容器库概览

文章目录所有容器的共性&#xff1a;迭代器迭代器的范围容器类型成员begin和end成员容器的定义和初始化与顺序容器大小相关的构造函数赋值和swapassignedswap容器大小操作关系运算符所有容器的共性&#xff1a; 表格一&#xff1a; 类型别名说明iterator迭代器const_iterator…

用R语言理解全微分

文章目录6 全微分梯度的概念全微分前情提要 R语言微积分极限π,e,γ\pi, e, \gammaπ,e,γ洛必达法则连续性和导数数值导数差商与牛顿插值方向导数 6 全微分 梯度的概念 对于任意函数f(x0,x1,⋯,xn)f(x_0,x_1,\cdots,x_n)f(x0​,x1​,⋯,xn​)&#xff0c;其梯度为 ∇f(∂f∂…

解决从BIOS选择从U盘启动但是系统仍然从硬盘启动的问题

我怀疑是BIOS失去了记忆能力&#xff0c;不能记住我的选择&#xff0c;所以仍然按默认从硬盘启动。 解决&#xff1a;重置BIOS即可 下面用物理方法重置BIOS。 在主板上找到这三根针&#xff0c;将上面的黑色套子拔出&#xff0c;然后插入旁边的另外两根针&#xff0c;例如开始…

基于python知识图谱医疗领域问答系统实现

直接上结果展示: “让人类永远保持理智,确实是一种奢求” ,机器人莫斯,《流浪地球》 项目概况 本项目为一个使用深度学习方法解析问题,知识图谱存储、查询知识点,基于医疗垂直领域的对话系统的后台程序 运行效果:

aws beanstalk 结合packer创建自定义平台

参考资料 https://github.com/aws-samples/eb-custom-platforms-samples#updating-packer-templateElastic Beanstalk 自定义平台 今天使用eb平台创建环境的时候&#xff0c;发现有名为packer的选项&#xff0c;查询文档发现aws beanstalk支持自定义平台&#xff0c;这功能几…

4. 使用预训练的PyTorch网络进行图像分类

4. 使用预训练的PyTorch网络进行图像分类 这篇博客将介绍如何使用PyTorch预先训练的网络执行图像分类。利用这些网络只需几行代码就可以准确地对1000个常见对象类别进行分类。这些图像分类网络是开创性的、最先进的图像分类网络&#xff0c;包括VGG16、VGG19、Inception、Dens…

windows下 pytorch的安装(gpu版本以及cpu版本)

一. 查看是否有gpu 打开cmd 输入nvidia-smi 是以下这种情况的就是有gpu 没有gpu的话就会报错 下载安装cuda以及cudnn&#xff08;安装cpu版本可以跳过此步骤直接进行pytorch的安装&#xff09; 下载cuda 看清楚两个箭头指的地方 一个是11.3.0 一个是日期 后面下载cudnn的时…

ProEssentials Pro 9.8.0.32 Crack

ProEssentials .Net图表组件用于对您的科学、工程和金融图表进行评估和选择&#xff01; Winforms 图表, WPF 图表, C/MFC/VCL 图表. Gigasoft拥有20多年帮助企业开发大型客户端和嵌入式图表项目的经验 为何选择ProEssentials&#xff1f; 我们真诚地希望您能针对您的具体实施…

day03 链表 | 203、移除链表元素 707、设计链表 206、反转链表

题目 203、移除链表元素 删除链表中等于给定值 val 的所有节点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,6,3,4,5,6], val 6 输出&#xff1a;[1,2,3,4,5] 示例 2&#xff1a; 输入&#xff1a;head [], val 1 输出&#xff1a;[] 示例 3&#xff1a; 输入&am…

Pytorch Kaggle实战:House Prices - Advanced Regression Techniques

通过Kaggle比赛&#xff0c;将所学知识付诸实践 目录 1、下载和缓存数据集 2、访问和读取数据集 3、数据预处理 3、训练 4、K折交叉验证 5、模型选择 6、提交Kaggle预测 1、下载和缓存数据集 建立字典DATA_HUB,它可以将数据集名称的字符串映射到数据集相关的二元组上&am…

网络抓包-抓包工具tcpdump的使用与数据分析

1.测试背景 本次测试选用两台不同的服务器&#xff0c;ip分别为.233和.246,233服务器为客户端&#xff0c;246服务器为服务端。利用tcp协议就行socket通信。socket网络编程部分示例代码为基本的通信代码&#xff0c;需要了解tcp网络通讯的基本协议与过程。服务器上采用tcpdump…

【学习笔记】【Pytorch】八、池化层

【学习笔记】【Pytorch】八、池化层学习地址主要内容一、最大池化操作示例二、nn.MaxPool2d类的使用1.使用说明2.代码实现三、池化公式学习地址 PyTorch深度学习快速入门教程【小土堆】. 主要内容 一、最大池化操作示例 二、nn.MaxPool2d类的使用 作用&#xff1a;对于输入信…

Min_25筛

概述 Min_25是日本一个ACM选手的ID&#xff0c;这个筛法是他发明的&#xff0c;所以称之为Min_25筛。它能在亚线性复杂度求出一类积性函数的 fff 的前缀和&#xff0c;前提 是这个积性函数在质数和质数的幂位置的函数值比较好求。借助埃拉托色尼筛的思想 将原问题转化成与质因…