原生cloud+netflix与alibaba cloud架构默

2020-12-04  本文已影响0人  机灵鬼鬼

pc电脑:4核 16G
cloud版本:Hoxton.SR9
boot版本:2.3.5.RELEASE
压测场景:间隔1ms,10000个请求
neftlix全套:hystrix、open feign、eureka、undertow
压测结果:内存持续上升gc间隔时长很长,cup利用率不高,线程数较高,跑完耗时36分钟


image.png

单调控制台

image.png

阿里全套:sentinel、open feign、nacos、undertow
压测结果:内存变化均匀gc间隔一分钟一次,cup利用率较好,线程数较低,跑完耗时5分钟。


nacos+feign+undertow(10000个请求间隔1ms访问).jpg

丰富控制台

更关键的是阿里的sentinel的多维度的监控控制台


image.png

因此我选择使用阿里的全套
下面开撸代码


image.png

父类takeout3-cloud的pom.xml

<?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>
    <packaging>pom</packaging>
    <modules>
        <module>takeout-api</module>
        <module>takeout-product-provider-8080</module>
        <module>takeout-consumer-feign-80</module>
    </modules>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.lppz.cloud</groupId>
    <artifactId>takeout3-cloud</artifactId>
    <version>1.0.1-SNAPSHOT</version>
    <name>takeout3-cloud</name>
    <description>takeout3 project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR9</spring-cloud.version>
        <com-alibaba-cloud.version>2.2.2.RELEASE</com-alibaba-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-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>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${com-alibaba-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

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

    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
        </repository>
        <repository>
            <id>alimaven</id>
            <name>aliyun maven</name>
            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
        </repository>
    </repositories>

</project>

takout-api

1、pom.xml

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>takeout3-cloud</artifactId>
        <groupId>com.lppz.cloud</groupId>
        <version>1.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.lppz.cloud</groupId>
    <artifactId>takout-api</artifactId>
    <packaging>jar</packaging>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!--undertow替换boot默认的tomcat内嵌容器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-undertow</artifactId>
        </dependency>
    </dependencies>
    <build>
        <finalName>takeout3-api</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <skip>true</skip>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

2、关键代码

package com.lppz.cloud.api.service;

import com.lppz.cloud.api.entities.DataChannel;
import com.lppz.cloud.api.entities.RespData;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * 使用Feign的注解+接口的形式来进行服务调用
 */
//feign与注册入Eureka的微服务建立连接, 每一个地址有异常都会调用fallback中的同名方法做兜底

@FeignClient(value="takeout3-provider-product",fallbackFactory = ApiServiceFallBackFactory.class)
public interface DataChannelClientService {
    //这里映射真正的业务DataChannelController入口地址:“/channel/{id}”
    @RequestMapping(method = RequestMethod.GET, value = "/channel/{id}")
    public RespData getDataChannelById(@PathVariable("id")int id);

    @RequestMapping(method = RequestMethod.POST, value = "/channel")
    public RespData insertDataChannel(DataChannel dataChannel) ;

    @RequestMapping(method = RequestMethod.POST, value = "/channel/update")
    public RespData updateDataChannel(DataChannel dataChannel) ;

    @RequestMapping(method = RequestMethod.POST, value = "/channel/delete")
    public RespData deleteDataChannel(DataChannel dataChannel) ;
}

takeout-consumer-feign-80

1.pom.xml配置

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>takeout3-cloud</artifactId>
        <groupId>com.lppz.cloud</groupId>
        <version>1.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>takeout-consumer-feign-80</artifactId>
    <dependencies>
        <dependency>
            <groupId>com.lppz.cloud</groupId>
            <artifactId>takout-api</artifactId>
            <version>1.0.1-SNAPSHOT</version>
        </dependency>

        <!-- alibaba nacos sentinel -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <!--openfeign客户端负载均衡引入-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>com.alibaba.nacos</groupId>
                    <artifactId>nacos-client</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-client</artifactId>
        </dependency>
    </dependencies>

</project>

2、application.yml配置

server:
  port: 80

spring:
  cloud:
    nacos:
      discovery:
        server-addr: 10.101.x.x:8848  #nacos注册中心地址
  application:
    name: comsumer_feign
feign:
  client:
    config:
      default:
        connectTimeout: 5000 #连接超时时间
        readTimeout: 5000    #请求与响应的时间间隔阈值
  okhttp:
    enabled: true  #开启 okhttp client代替feign的默认client
  sentinel:
    enabled: true #开启Fegin对sentinel的支持

3、关键代码

package com.lppz.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableDiscoveryClient  //告诉feign客户端,具体的微服务
@EnableFeignClients(basePackages = "com.lppz.cloud") //open Feign的客户端负载均衡
public class Consumer_App_Feign_80 {

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

}

package com.lppz.cloud.controller;

import com.lppz.cloud.api.entities.DataChannel;
import com.lppz.cloud.api.entities.RespData;
import com.lppz.cloud.api.service.DataChannelClientService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
public class DataChannelController_Feign {

    @Autowired
    private DataChannelClientService service;

    @RequestMapping(value = "/consumer/channel/{id}",method = RequestMethod.GET)
    public RespData getDataChannelById(@PathVariable("id") int id) {
        //去找微服务的入口地址,就是第二步里的@FeignClient(value="TAKEOUT3-PROVIDER-PRODUCT")的“/channel/{id}”
        return service.getDataChannelById(id);
    }
    @RequestMapping(value = "/consumer/channel",method = RequestMethod.POST)
    public RespData insertDataChannel(DataChannel dataChannel) throws Exception {
        return service.insertDataChannel(dataChannel);
    }
    @RequestMapping(value = "/consumer/channel/update",method = RequestMethod.POST)
    public RespData updateDataChannel(DataChannel dataChannel) throws Exception {

        return service.updateDataChannel(dataChannel);

    }
    @RequestMapping(value = "/consumer/channel/delete",method = RequestMethod.POST)
    public RespData deleteDataChannel(DataChannel dataChannel) throws Exception {

        return service.deleteDataChannel(dataChannel);

    }
}

takeout-product-provider-8080

1、pom.xml配置

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>takeout3-cloud</artifactId>
        <groupId>com.lppz.cloud</groupId>
        <version>1.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>takeout-product-provider-8080</artifactId>


    <dependencies>
        <dependency>
            <groupId>com.lppz.cloud</groupId>
            <artifactId>takout-api</artifactId>
            <version>1.0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.3</version>
        </dependency>
        <!--将provider注册进入nacos的配置-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>com.alibaba.nacos</groupId>
                    <artifactId>nacos-client</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <!--服务容错-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--配置文件书写提示-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

2、application.yml配置

server:
  port: 8080
  undertow:
    # 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
    # 每块buffer的空间大小,越小的空间被利用越充分
    buffer-size: 1024
    # 是否分配的直接内存
    direct-buffers: true
    threads:
      io: 4  # 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程
      worker: 20 # 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载
spring:
  application:
    name: takeout3-provider-product  #微服务对外暴露的名字
  datasource:
    url: jdbc:mysql://192.168.x.x:3306/omso2o
    username: xx1
    password: xx2
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    initialSize: 5
    maxActive: 100
    minIdle: 5
    maxWati: 60000
    minEvictableIdleTimeMillis: 300000
    maxPoolPreparedStatementPerConnectionSize: 100
    poolPreparedStatements: true
    validationQuery: select 1 for dual
    testOnBorrow: false
    testOnReturn: false
    testWhileIdle: true
    filters: stat,wall
    # sql合并,慢查询定义为5s
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
  cloud:
    nacos:
      discovery:
        server-addr: 10.101.x.x:8848  #nacos注册中心地址
    sentinel:
      transport:
        dashboard: 192.168.x.x:8080   #配置Sentinel DashBoard地址
        port: 8722                  #微服务向Sentinel控制台开发的端口
        clientIp: 10.28.x.x      #解析:暴露的微服务所在机器ip,该配置项多用于多网卡环境,如果多网卡环境必须制定clientIp,否则就会Sentinel控制台有可能找不到

mybatis:
  mapper-locations: classpath:mybatis/mapper/*.xml
  config-location: classpath:mybatis/mybatis-config.xml
info:
  app.name: lppz takeout version 3.0
  company.name: lppz.com
  build.artifactId: takeout3-cloud
  build.version: 1.0.1-SNAPSHOT

management:
  endpoints:
    web:
      exposure:
        include: "*"

3、关键代码

package com.lppz.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient  //该微服务的所有对外暴露的服务统一注册在nacos中
public class ProductApplication_8080 {
    public static void main(String[] args) {

        SpringApplication.run(ProductApplication_8080.class, args);
    }

}

package com.lppz.cloud.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.lppz.cloud.api.entities.RespData;
import com.lppz.cloud.service.DataChannelService;

import com.lppz.cloud.api.entities.DataChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 此入口就是我们当前微服务的统一入口
 * consumer-feign需要的商品数据,都要从该入口
 * 统一获取。
 */
@RestController
public class DataChannelController {
    private static final Logger logger= LoggerFactory.getLogger(DataChannelController.class);
    @Autowired
    DataChannelService dataChannelService;//此处只是服务的调用样例,未来这里会集中很多关于商品数据的service
    // 原函数
    @SentinelResource(value = "getDataChannelById")
    @GetMapping("/channel/{id}")
    public RespData getDataChannelById(@PathVariable("id") int id) {
        DataChannel dc= dataChannelService.getDataChannelById(id);
        RespData res=RespData.getDefaultSuccRespData();
        if(null!=dc){
            res.setData(dc);
        }
        return res;
    }
    @SentinelResource(value = "insertDataChannel")
    @PostMapping("/channel")
    public RespData insertDataChannel(DataChannel dataChannel){

        DataChannel newdataChannel = null;
        RespData res=RespData.getDefaultSuccRespData();
        try {
            newdataChannel = dataChannelService.insertDataChannel(dataChannel);
            res.setData(newdataChannel);
        } catch (Exception e) {
            e.printStackTrace();
//            throw  new MyException("2000",e.getMessage());
            res.setMsg(e.getMessage());
            res.setCode(RespData.ERROR_CODE);
        }
        return res;
    }
    @SentinelResource(value = "deleteDataChannel")
    @PostMapping("/channel/delete")
    public RespData deleteDataChannel(DataChannel dataChannel) {
        RespData res=RespData.getDefaultSuccRespData();
        int cnt=0;
        try {
            cnt= dataChannelService.deleteDataChannel(dataChannel);
        } catch (Exception e) {
            e.printStackTrace();
            res.setMsg(e.getMessage());
            res.setCode(RespData.ERROR_CODE);
        }
        return res;
    }
    @SentinelResource(value = "updateDataChannel")
    @PostMapping("/channel/update")
    public RespData updateDataChannel(DataChannel dataChannel) {
        RespData res=RespData.getDefaultSuccRespData();
        int cnt=0;
        try {
            cnt= dataChannelService.updateDataChannel(dataChannel);
        } catch (Exception e) {
            e.printStackTrace();
            res.setMsg(e.getMessage());
            res.setCode(RespData.ERROR_CODE);
        }
        return res;
    }

}

上一篇下一篇

猜你喜欢

热点阅读