程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

2023-06(1)

springCloud入门(三)

发布于2021-06-12 13:49     阅读(411)     评论(0)     点赞(27)     收藏(3)


Ribbon是Netflix发布的负载均衡器,它可以帮我们控制HTTP和TCP客户端的行为。只需为Ribbon配置服务提供者地址列表,Ribbon就可基于负载均衡算法计算出要请求的目标服务地址。

Ribbon默认为我们提供了很多的负载均衡算法,例如轮询、随机、响应时间加权等——当然,为Ribbon自定义负载均衡算法也非常容易,只需实现 IRule 接口即可。

在Spring Cloud中,当Ribbon与Eureka配合使用时,Ribbon可自动从Eureka Server获取服务提供者地址列表,并基于负载均衡算法,选择其中一个服务提供者实例。

负载均衡规则是Ribbon的核心

  • AvailabilityFilteringRule:过滤掉一直连接失败的被标记为circuit
    tripped的后端Server,并过滤掉那些高并发的后端Server或者使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个Server的运行状态;
  • BestAvailableRule:选择一个最小的并发请求的Server,逐个考察Server,如果Server被tripped了,则跳过。
  • RandomRule:随机选择一个Server;
  • ResponseTimeWeightedRule:作用同WeightedResponseTimeRule,二者作用一样;
    RetryRule:对选定的负载均衡策略机上重试机制,在一个配置时间段内当选择Server不成功,则一直尝试使用subRule的方式选择一个可用的server;
  • RoundRobinRule:轮询选择, 轮询index,选择index对应位置的Server;
  • WeightedResponseTimeRule:根据响应时间加权,响应时间越长,权重越小,被选中的可能性越低;
  • ZoneAvoidanceRule:复合判断Server所在区域的性能和Server的可用性选择Server
  • 如需自定义负载均衡规则,只需实现IRule 接口或继承AbstractLoadBalancerRule、PredicateBasedRule即可

代码如下:
Eureka Server

maven 依赖

<?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>2.0.7.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>eurekaServer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>eurekaServer</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--增加eurekaServer-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

    </dependencies>

    <!-- 引入spring cloud的依赖,不能少,主要用来管理Spring Cloud生态各组件的版本 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.SR2</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>

</project>

启动类


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
// 服务发现
@EnableEurekaServer
public class EurekaServerApplication {

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

}

配置文件

server:
  port: 8761
eureka:
  client:
    # 是否要注册到其他eureka server 实例
    register-with-eureka: false
    # 是否从其他eureka server实例获取数据
    fetch-registry: false
    service-url:
      defaultZone: http://localhost:8761/eureka/

服务提供者1
maven

<?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>2.0.7.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>test-provider-library</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>test-provider-library</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <!-- 引入H2数据库,一种内嵌的数据库,语法类似MySQL -->
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
        </dependency>
        <!-- 引入Lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!--增加eurekaclient-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

    </dependencies>

    <!-- 引入spring cloud的依赖,不能少,主要用来管理Spring Cloud生态各组件的版本 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.SR2</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>

</project>

启动类

package com.example.testproviderlibrary;

import com.example.testproviderlibrary.dao.LibraryDao;
import com.example.testproviderlibrary.pojo.LibraryInfo;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;

import java.util.stream.Stream;

@SpringBootApplication
// 加注解
@EnableEurekaClient
public class TestProviderLibraryApplication {

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

    /**
     * 使用内置数据库h2 初始化数据
     */
    @Bean
    ApplicationRunner init (LibraryDao repository){
        return args ->{
            LibraryInfo libraryInfo1=LibraryInfo.builder().id(1L).name("前门图书馆")
                    .address("东城区前门东大街").number(1000).count(20).build();
            LibraryInfo libraryInfo2=LibraryInfo.builder().id(2L).name("青年路图书馆")
                    .address("丰台区青年路").number(500).count(10).build();
            LibraryInfo libraryInfo3=LibraryInfo.builder().id(2L).name("大地图书馆")
                    .address("昌平区上地八街").number(800).count(2).build();
            Stream.of(libraryInfo1,libraryInfo2,libraryInfo3).forEach(repository :: save);


        };
    }

}

配置文件

server:
  # 指定Tomcat端口
  port: 8000
spring:
  jpa:
  # 让hibernate打印执行的SQL
     how-sql: true
    ## 指定注册到eureka server上的服务名称
  application:
    name: test-provider-library
logging:
  level:
    root: INFO
    # 配置日志级别,让hibernate打印出执行的SQL参数
    org.hibernate: INFO
    org.hibernate.type.descriptor.sql.BasicBinder: TRACE
    org.hibernate.type.descriptor.sql.BasicExtractor: TRACE
eureka:
  client:
    service-url:
      # 指定eureka server通信地址,注意/eureka/小尾巴不能少
      defaultZone: http://localhost:8761/eureka/
  instance:
    # 是否注册IP到eureka server,如不指定或设为false,那就会注册主机名到eureka server
    prefer-ip-address: true


controller


import com.example.testproviderlibrary.pojo.LibraryInfo;
import com.example.testproviderlibrary.service.LibraryService;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Optional;

@RestController
@RequestMapping("/library")
public class LibraryController {

    @Autowired
    private LibraryService libraryService;

    @GetMapping("/{id}")
    public LibraryInfo findById(@PathVariable Long id){
        Optional<LibraryInfo> libraryInfo = this.libraryService.findById(id);
        return libraryInfo.get();
    }

}

service


import com.example.testproviderlibrary.dao.LibraryDao;
import com.example.testproviderlibrary.pojo.LibraryInfo;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.Optional;

@Service
//可以代替@AutoWired注解,需要注意的是在注入时需要用final定义,或者使用@notnull注解
@RequiredArgsConstructor
public class LibraryService {


    private final LibraryDao libraryDao;

    public Optional<LibraryInfo> findById(Long id){
        return this.libraryDao.findById(id);
    }


}

dao


import com.example.testproviderlibrary.pojo.LibraryInfo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface LibraryDao extends JpaRepository<LibraryInfo,Long> {
}

实体类


import lombok.*;

import javax.persistence.*;

/**
 * 图书馆信息
 *
 */
@Getter
@Setter
@Builder
@Entity
// 为类提供一个无参的构造方法。
@NoArgsConstructor
// 为类提供一个全参的构造方法
@AllArgsConstructor
public class LibraryInfo {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    /**
     * 图书馆名称
     */
    @Column
    private String name;

    /**
     * 图书馆地址
     */
    @Column
    private String address;

    /**
     * 总座位数
     */
    @Column
    private Integer number;

    /**
     * 可预约数量
     */
    @Column
    private Integer count;

}

服务提供者2与服务提供者1代码一致,唯一不同的是端口号,可以直接复制服务提供者1然后改下端口即可

服务消费者
maven引入

<?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>2.0.7.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>test-consumer-user-ribbon</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>test-consumer-user-ribbon</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- 引入Lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!--增加eurekaclient-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>

    <!-- 引入spring cloud的依赖,不能少,主要用来管理Spring Cloud生态各组件的版本 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.SR2</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>

</project>

启动类


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class TestConsumerUserRibbonApplication {

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

    @Bean
    // 只需在 RestTemplate 上添加 LoadBalanced 注解,即可让RestTemplate整合Ribbon!
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();

    }

}

配置文件

server:
  port: 8003
spring:
  ## 指定注册到eureka server上的服务名称
  application:
    name: test-consumer-user-ribbon
eureka:
  client:
    service-url:
      # 指定eureka server通信地址,注意/eureka/小尾巴不能少
      defaultZone: http://localhost:8761/eureka/
  instance:
    # 是否注册IP到eureka server,如不指定或设为false,那就会注册主机名到eureka server
    prefer-ip-address: true

实体类


import lombok.*;

/**
 * 图书馆信息
 *
 */
@Getter
@Setter
@Builder
@NoArgsConstructor
// 为类提供一个全参的构造方法
@AllArgsConstructor
public class LibraryInfo {


    private Long id;

    /**
     * 图书馆名称
     */
    private String name;

    /**
     * 图书馆地址
     */
    private String address;

    /**
     * 总座位数
     */
    private Integer number;

    /**
     * 可预约数量
     */
    private Integer count;

}

controller


import com.example.testconsumeruserribbon.pojo.LibraryInfo;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/library/{id}")
    public LibraryInfo findById(@PathVariable Long id){
        // 这里用到了RestTemplate的占位符能力
        // Ribbon会自动在实际调用时,将目标服务名替换为该服务的IP和端口。
        LibraryInfo forObject = restTemplate.getForObject("http://test-provider-library/library/{id}",
                LibraryInfo.class, id);
        return forObject;
    }

}

然后依次启动 注册中心,服务提供者1,服务提供者2,消费者

启动成功后,访问注册中心

http://localhost:8761/

在这里插入图片描述
可以看到服务提供者有2个服务
然后访问服务消费者

http://localhost:8003/user/library/1

在这里插入图片描述
多刷新几次
然后查看后台服务提供者日志,会发现两个服务都分别打印的有日志,说明负载均衡算法有效

原文链接:https://blog.csdn.net/G_whang/article/details/117718329



所属网站分类: 技术文章 > 博客

作者:小泽圈儿郎

链接:http://www.javaheidong.com/blog/article/222308/46d5a24d7f1d6b1ea2b0/

来源:java黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

27 0
收藏该文
已收藏

评论内容:(最多支持255个字符)