国产高性能java网关–神禹shenyu(原名soul)


国产高性能java网关–神禹shenyu(原名soul)


其实从18年开始就已经在关注soul网关了,因为当时公司在做微服务转型,时间比较急,还是基于springcloud gateway搭建了网关。虽然没有使用,但还是在关注,果不其然,这个优秀的项目成功进入了Apache社区,并改名为神禹(shenyu),在这两年微妙的大环境下,再次为我们果然的努力而自豪。

神禹网关的文档很全,对于初学者很友好,今天将我这边的搭建经验分享给大家。

源码模块介绍

推荐大家优先阅读数据同步原理和客户端接入原理,可以帮助更好的使用。

  • shenyu-admin : 插件和其他信息配置的管理后台
  • shenyu-bootstrap : 用于启动项目,用户可以参考   初始化好的一个网关demo
  • shenyu-client : 用户可以使用 Spring MVC,Dubbo,Spring Cloud 快速访问
  • shenyu-disruptor : 基于disruptor的封装
  • shenyu-register-center : shenyu-client提供各种rpc接入注册中心的支持
  • shenyu-common : 框架的通用类
  • shenyu-dist : 构建项目
  • shenyu-metrics : prometheus(普罗米修斯)实现的 metrics
  • shenyu-plugin : ShenYu 支持的插件集合
  • shenyu-spi : 定义 ShenYu spi
  • shenyu-spring-boot-starter : 支持 spring boot starter
  • shenyu-sync-data-center : 提供 ZooKeeper,HTTP,WebSocket,Nacos 的方式同步数据
  • shenyu-examples : RPC 示例项目
  • shenyu-web : 包括插件、请求路由和转发等的核心处理包

数据同步

数据同步是指在 shenyu-admin 后台操作数据以后,使用何种策略将数据同步到 Apache ShenYu 网关。Apache ShenYu 网关当前支持ZooKeeperWebSocketHttp长轮询NacosEtcdConsul进行数据同步。

建议配置之前先学习数据同步原理 ,方便日后使用了解底层逻辑和阅读源码。

国产高性能java网关--神禹shenyu(原名soul)
image-20210908082630057

官方的文档比较全,参照逐步配置即可,这里列出我这边采用的方式——官方推荐的websocket方式

首先在 pom.xml 文件中引入以下依赖:

    <!-- apache shenyu data sync start use websocket-->    
<dependency>        
    <groupId>org.apache.shenyu</groupId>        
    <artifactId>shenyu-spring-boot-starter-sync-data-websocket</artifactId>          
    <version>${project.version}</version>    
</dependency>

然后在 yml 文件中进行如下配置:

shenyu:  
 sync:    
  websocket :      
   urls: ws://localhost:9095/websocket      # urls:是指 shenyu-admin的地址,如果有多个,请使用(,)分割。  

shenyu-admin 配置

yml 文件中进行如下配置:

shenyu:  
 sync:    
  websocket:      
   enabled: true

当建立连接以后会全量获取一次数据,以后的数据都是增量的更新与新增,性能好。而且也支持断线重连 (默认30秒)。推荐使用此方式进行数据同步,也是Apache ShenYu默认的数据同步策略。

快速打造shenyu网关实例

maven依赖

<dependencies>
   <!--        官方有要求添加这部分,但是实际没效果--> 
<!--        <dependency>-->
<!--            <groupId>org.springframework.boot</groupId>-->
<!--            <artifactId>spring-boot-starter-webflux</artifactId>-->
<!--            <version>2.2.2.RELEASE</version>-->
<!--        </dependency>-->
<!--        <dependency>-->
<!--            <groupId>org.springframework.boot</groupId>-->
<!--            <artifactId>spring-boot</artifactId>-->
<!--            <version>2.2.2.RELEASE</version>-->
<!--        </dependency>-->
        <!--shenyu gateway start-->
        <dependency>
            <groupId>org.apache.shenyu</groupId>
            <artifactId>shenyu-spring-boot-starter-gateway</artifactId>
            <version>${shenyu.version}</version>
        </dependency>

        <!--shenyu data sync start use websocket-->
        <dependency>
            <groupId>org.apache.shenyu</groupId>
            <artifactId>shenyu-spring-boot-starter-sync-data-websocket</artifactId>
            <version>${shenyu.version}</version>
        </dependency>

        <!--if you use http proxy start this-->
        <dependency>
            <groupId>org.apache.shenyu</groupId>
            <artifactId>shenyu-spring-boot-starter-plugin-divide</artifactId>
            <version>${shenyu.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.shenyu</groupId>
            <artifactId>shenyu-spring-boot-starter-plugin-httpclient</artifactId>
            <version>${shenyu.version}</version>
        </dependency>

    </dependencies>
<!--  我主项目的springboot项目已经到2.5.3,但是shenyu需要的是2.2.2的版本,所以需要特别处理下-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.2.2.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

配置文件

spring:
  main:
    allow-bean-definition-overriding: true

management:
  health:
    defaults:
      enabled: false
shenyu:
  sync:
    websocket :
      urls: ws://localhost:9095/websocket  #设置成你的 shenyu-admin 地址
server:
  port: 9999

启动类

@SpringBootApplication
public class GatewayStarter {
    public static void main(String[] args) {
        SpringApplication.run(GatewayStarter.class, args);
    }
}

客户端接入

对于网关来说 实际的服务提供方或者服务调用方都是客户端。

http方式

shenyu网关默认就是http方式接入,因此几乎不需要改什么配置即可运行

maven依赖

<dependencies>
        <!--必备: spring boot web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--undertow容器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-undertow</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-models</artifactId>
        </dependency>
        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-annotations</artifactId>
        </dependency>
        <!--hutool-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>${hutool.version}</version>
        </dependency>
<!--        shenyu sometings 重点在这里  -->
        <dependency>
            <groupId>org.apache.shenyu</groupId>
            <artifactId>shenyu-spring-boot-starter-client-springmvc</artifactId>
            <version>${shenyu.version}</version>
        </dependency>
    </dependencies>

测试类

@RestController
@RequestMapping("/hello")
@ShenyuSpringMvcClient(path = "/hello")
public class HelloController {
    @GetMapping("/index")
    @ShenyuSpringMvcClient(path="/index")
    public String hello(){
        return "hello world";
    }
    @GetMapping("/haha")
    public String haha(){
        return "O(∩_∩)O哈哈~ world";
    }
}

启动类

@SpringBootApplication
public class CmsStarter {
    public static void main(String[] args) throws JsonProcessingException {
        SpringApplication.run(CmsStarter.classargs);
    }
}

nacos注册方式配置

实际项目中用的比较多的是nacos

修改网关管理平台配置的注册方式为nacos

shenyu:
  register:
    registerType: nacos #http #zookeeper #etcd #nacos #consul
    serverLists: localhost:8848 #localhost:2181 #http://localhost:2379 #localhost:8848
    props:
      sessionTimeout: 5000
      connectionTimeout: 2000
      checked: true
      zombieCheckTimes: 5
      scheduledTime: 10
      nacosNameSpace: ShenyuRegisterCenter

shenyu客户端补充如下依赖:

        <dependency>
            <groupId>org.apache.shenyu</groupId>
            <artifactId>shenyu-register-client-nacos</artifactId>
            <version>${shenyu.version}</version>
        </dependency>

shenyu客户端修改配置文件:

shenyu:
  client:
    registerType: nacos
    serverLists: localhost:8848
    props:
      contextPath: /http
      appName: http
      port: 8188  
      isFull: false
      nacosNameSpace: ShenyuRegisterCenter
# registerType : 服务注册类型,填写 nacos
# serverList: 为nacos注册类型时,填写nacos地址,多个地址用英文逗号分隔
# port: 你本项目的启动端口,目前springmvc/tars/grpc需要进行填写
# contextPath: 为你的这个mvc项目在shenyu网关的路由前缀,比如/order ,/product 等等,网关会根据你的这个前缀来进行路由.
# appName:你的应用名称,不配置的话,会默认取 `spring.application.name` 的值
# isFull: 设置true 代表代理你的整个服务,false表示代理你其中某几个controller;目前适用于springmvc/springcloud
# nacosNameSpace: nacos的命名空间xxxxxxxxxx shenyu:  client:    registerType: nacos    serverLists: localhost:8848    props:      contextPath: /http      appName: http      port: 8188        isFull: false      nacosNameSpace: ShenyuRegisterCenter# registerType : 服务注册类型,填写 nacos# serverList: 为nacos注册类型时,填写nacos地址,多个地址用英文逗号分隔# port: 你本项目的启动端口,目前springmvc/tars/grpc需要进行填写# contextPath: 为你的这个mvc项目在shenyu网关的路由前缀,比如/order ,/product 等等,网关会根据你的这个前缀来进行路由.# appName:你的应用名称,不配置的话,会默认取 `spring.application.name` 的值# isFull: 设置true 代表代理你的整个服务,false表示代理你其中某几个controller;目前适用于springmvc/springcloud# nacosNameSpace: nacos的命名空间shenyu:  client:    registerType: nacos #zookeeper #etcd #nacos #consul    serverLists: localhost:8848 #localhost:2181 #http://localhost:2379 #localhost:8848    props:      contextPath: /cms      appName: cms      port: 7001      nacosNameSpace: ShenyuRegisterCenter

SpringCloud接入

首先要在网关管理后台中开启springcloud插件

国产高性能java网关--神禹shenyu(原名soul)
image-20210908163621246

在网关中引入相关依赖:

<!-- apache shenyu springCloud plugin start-->
        <dependency>
            <groupId>org.apache.shenyu</groupId>
            <artifactId>shenyu-spring-boot-starter-plugin-springcloud</artifactId>
            <version>${shenyu.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.shenyu</groupId>
            <artifactId>shenyu-spring-boot-starter-plugin-httpclient</artifactId>
            <version>${shenyu.version}</version>
        </dependency>
        <!-- apache shenyu springCloud plugin end-->

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-commons</artifactId>
            <version>2.2.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
            <version>2.2.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <version>2.1.0.RELEASE</version>
        </dependency>

补充nacos的配置:

  spring:
     cloud:
       nacos:
         discovery:
            server-addr: 127.0.0.1:8848 # 你的nacos地址

在SpringCloud项目中引入依赖:

 <dependency>
      <groupId>org.apache.shenyu</groupId>
      <artifactId>shenyu-spring-boot-starter-client-springcloud</artifactId>
      <version>${shenyu.version}</version>
 </dependency>

具体实例代码

@RestController
@RequestMapping("/helloS")
@ShenyuSpringCloudClient(path = "/helloS")
public class HelloController {
    @GetMapping("/index")
    @ShenyuSpringCloudClient(path="/index")
    public String hello(){
        return "hello world";
    }
    @GetMapping("/haha")
    public String haha(){
        return "O(∩_∩)O哈哈~ world";
    }
}

原先访问localhost:7001/helloS/index,现在可以通过localhost:9999/cms/helloS/index进行访问,实现网关的统一代理。

至此完成SpringCloud服务的接入,但是也有几点问题

由于依赖shenyu的jar包,因此必须要考虑到依赖版本问题,比如shenyu的SpringBoot版本低于业务项目版本时怎么办?

是否应该将业务项目的依赖版本尽可能的与网关的依赖版本独立开来。

SpringCloud与Http融合

全部调整为HTTP注册方式,然后需要手动设置选择器和规则,这样会比较麻烦,但是后端的服务之间没有依赖。

后端的服务间调用则采用任意方式都可以。

运行

启动shenyu网关后端管理项目

run ShenyuAdminBootstrap。

修改对应数据库的配置信息

server:
  port: 9095
  address: 0.0.0.0

spring:
#  profiles:
#    active: h2
  thymeleaf:
    cache: true
    encoding: utf-8
    enabled: true
    prefix: classpath:/static/
    suffix: .html
  datasource:
    url: jdbc:mysql://yunho-mysql:3306/shenyu?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver

mybatis:
  config-location: classpath:/mybatis/mybatis-config.xml
  mapper-locations: classpath:/mappers/*.xml

shenyu:
  register:
    registerType: nacos #http #zookeeper #etcd #nacos #consul 这里采用nacos接入
    serverLists: localhost:8848 #localhost:2181 #http://localhost:2379 #localhost:8848
    props:
      sessionTimeout: 5000
      connectionTimeout: 2000
      checked: true
      zombieCheckTimes: 5
      scheduledTime: 10
      nacosNameSpace: ShenyuRegisterCenter
  database:
    dialect: mysql
    init_script: "META-INF/schema.sql"
    #custom_init_script: "/opt/schema.sql"
    init_enable: true
  sync:
    websocket:
      enabled: true  #采用推荐的websocket方式实现数据同步
  aes:
    secret:
      key: 2095132720951327
  ldap:
    enabled: false
    url: ldap://xxxx:xxx
    bind-dn: cn=xxx,dc=xxx,dc=xxx
    password: xxxx
    base-dn: ou=xxx,dc=xxx,dc=xxx
    object-class: person
    login-field: cn
  jwt:
    key: 2095132720951327
  shiro:
    white-list:
      - /
      - /favicon.*
      - /static/**
      - /index**
      - /plugin
      - /platform/**
      - /websocket
      - /configs/**
      - /shenyu-client/**
      - /error
      - /actuator/health
      - /swagger-ui.html
      - /webjars/**
      - /swagger-resources/**
      - /v2/api-docs
      - /csrf
  swagger:
    enable: true

logging:
  level:
    root: info
    org.springframework.boot: info
    org.apache.ibatis: info
    org.apache.shenyu.bonuspoint: info
    org.apache.shenyu.lottery: info
    org.apache.shenyu: info

启动shenyu网关后端管理项目ShenyuAdminBootstrap,访问http://localhost:9095/,用户名密码:admin/123456

启动网关

启动GatewayStarter

3.3.1.RELEASE.jar;D:mylocalreporgprojectlomboklombok1.16.18lombok-1.16.18.jar" io.yunho.hudn.gateway.GatewayStarter
2021-09-08 16:02:48.733  INFO 55632 --- [           main] org.apache.shenyu.web.logo.ShenyuLogo    : 


   _____ _                            
  / ____| |                           
 | (___ | |__   ___ _ __  _   _ _   _ 
  ___ | '_  / _  '_ | | | | | | |
  ____) | | | |  __/ | | | |_| | |_| |
 |_____/|_| |_|___|_| |_|__, |__,_|
                           __/ |      
                          |___/       
 :: Shenyu :: (v2.4.0-SNAPSHOT)


  .   ____          _            __ _ _
 /\ / ___'_ __ _ _(_)_ __  __ _    
( ( )___ | '_ | '_| | '_ / _` |    
 \/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |___, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.2.2.RELEASE)

2021-09-08 16:02:48.918  INFO 55632 --- [           main] io.yunho.hudn.gateway.GatewayStarter     : Starting GatewayStarter on Jason-Think with PID 55632 (D:myideahundunhudn-gatewaytargetclasses started by Jason in D:myideahundun)
2021-09-08 16:02:48.919  INFO 55632 --- [           main] io.yunho.hudn.gateway.GatewayStarter     : No active profile set, falling back to default profiles: default
2021-09-08 16:02:50.930  INFO 55632 --- [           main] o.a.s.w.c.ShenyuConfiguration            : load plugin:[global] [org.apache.shenyu.plugin.global.GlobalPlugin]
2021-09-08 16:02:50.931  INFO 55632 --- [           main] o.a.s.w.c.ShenyuConfiguration            : load plugin:[context_path] [org.apache.shenyu.plugin.context.path.ContextPathPlugin]
2021-09-08 16:02:50.931  INFO 55632 --- [           main] o.a.s.w.c.ShenyuConfiguration            : load plugin:[divide] [org.apache.shenyu.plugin.divide.DividePlugin]
2021-09-08 16:02:50.931  INFO 55632 --- [           main] o.a.s.w.c.ShenyuConfiguration            : load plugin:[webClient] [org.apache.shenyu.plugin.httpclient.WebClientPlugin]
2021-09-08 16:02:50.931  INFO 55632 --- [           main] o.a.s.w.c.ShenyuConfiguration            : load plugin:[divide] [org.apache.shenyu.plugin.divide.websocket.WebSocketPlugin]
2021-09-08 16:02:50.931  INFO 55632 --- [           main] o.a.s.w.c.ShenyuConfiguration            : load plugin:[paramTransform] [org.apache.shenyu.plugin.base.ParamTransformPlugin]
2021-09-08 16:02:50.931  INFO 55632 --- [           main] o.a.s.w.c.ShenyuConfiguration            : load plugin:[response] [org.apache.shenyu.plugin.response.ResponsePlugin]
2021-09-08 16:02:50.996  INFO 55632 --- [           main] s.s.s.d.w.WebsocketSyncDataConfiguration : you use websocket sync shenyu data.......
2021-09-08 16:02:51.015  INFO 55632 --- [           main] o.a.s.p.s.d.w.WebsocketSyncDataService   : websocket connection is successful.....
2021-09-08 16:02:51.998  INFO 55632 --- [           main] o.s.b.web.embedded.netty.NettyWebServer  : Netty started on port(s): 9999
2021-09-08 16:02:52.001  INFO 55632 --- [           main] io.yunho.hudn.gateway.GatewayStarter     : Started GatewayStarter in 3.685 seconds (JVM running for 6.083)

到此已完成自定义网关的启动。


原文始发于微信公众号(云户):国产高性能java网关–神禹shenyu(原名soul)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/35273.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!