负载均衡框架 ribbon 三

Ribbon 在 SpringCloud 中的使用

1.构建 Eureka 注册中心 smart-platform-eureka1

(1)导入jar包

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

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

  <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>

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

  <build>
    <pluginManagement>
      <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>                                   
                <fork>true</fork>
                <addResources>true</addResources>
            </configuration>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>

(2)添加eureka配置 application.yml

server:
  port: 8761
spring:
  application:
    name: smart-platform-eureka1
eureka:
  instance:
    hostname: localhost
  client:
    registerWithEureka: false
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
  server:
    #eureka服务自我保护模式 默认是开启的
    enable-self-preservation: true
    #eureka服务 指定时间清理死掉的服务 默认60秒 单位毫秒
    eviction-interval-timer-in-ms: 60000

(3) 编写启动类

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

/**
 * eureka注册中心服务
 */
@SpringBootApplication
@EnableEurekaServer
public class Application {
    public static void main( String[] args) throws Exception{
        new SpringApplicationBuilder(Application.class).run(args);
    }
}

 

2.构建生产者服务 smart-platform-base

(1)导入jar包

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

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

  <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>

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

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

  </dependencies>

  <build>
    <pluginManagement>
      <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>                                   
                <fork>true</fork>
                <addResources>true</addResources>
            </configuration>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>

(2) 编写接口

public class User {
    private int id;
    private String userName;
    private String sex;
    private int age;
    private String createTime;
    private String message;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getCreateTime() {
        return createTime;
    }

    public void setCreateTime(String createTime) {
        this.createTime = createTime;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

 

@RestController
@RequestMapping(value = "/platform/base")
public class TestController {
   
    @GetMapping(value = "/getUser")
    public User getUser(HttpServletRequest request){
        User user = new User();
        user.setId(1);
        user.setUserName("delan");
        user.setAge(5);
        user.setMessage(request.getRequestURL().toString());
        return user;
    }

}

(3)编写启动类(由于此处要做负载均衡,所以启动两个端口)

@SpringBootApplication
@EnableEurekaClient
public class Application {
    public static void main( String[] args) {
        Scanner scan = new Scanner(System.in);
        System.out.println("请输入端口号:");
        String port = scan.nextLine();
        new SpringApplicationBuilder(Application.class).properties("server.port="+port).run(args);
    }
}

 

3.构建消费者服务 smart-platform-sm

(1) 导入jar包

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

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

  <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>

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

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

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

      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-devtools</artifactId>
          <optional>true</optional>
          <scope>true</scope>
      </dependency>
  </dependencies>

  <build>
    <pluginManagement>
      <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>                                   
                <fork>true</fork>
                <addResources>true</addResources>
            </configuration>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>

(2)编写调用代码

import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.ZoneAwareLoadBalancer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
@Configuration  //由于此类种有使用@Bean注解将 RestTemplate 注入到 spring 容器所以需要此注解
@RequestMapping(value = "/platform/shumeng")
public class TestController {

    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }

    @GetMapping(value = "/getUser")
    public String getUser(){
    //此种方式会通过轮询服务列表的方式访问服务接口 RestTemplate restTemplate
= getRestTemplate(); String json = restTemplate.getForObject("http://smart-platform-base/platform/base/getUser", String.class); return json; } //获取实例 @Autowired private LoadBalancerClient client; @GetMapping(value = "/lb", produces = MediaType.APPLICATION_JSON_VALUE) public ServiceInstance lb() { ServiceInstance serviceInstance = client.choose("smart-platform-base"); return serviceInstance; } //获取spring客户端 @Autowired private SpringClientFactory factory; @GetMapping(value = "/factory", produces = MediaType.APPLICATION_JSON_VALUE) public String factory() { ILoadBalancer balancer = factory.getLoadBalancer("default"); System.out.println("默认使用的负载均衡器是:" + balancer.getClass().getName()); ZoneAwareLoadBalancer zb = (ZoneAwareLoadBalancer) balancer; System.out.println("默认使用的负载均衡规则是:" + zb.getRule().getClass().getName()); //默认使用的负载均衡器是:com.netflix.loadbalancer.ZoneAwareLoadBalancer //默认使用的负载均衡规则:com.netflix.loadbalancer.ZoneAvoidanceRule ZoneAwareLoadBalancer zbm = (ZoneAwareLoadBalancer)factory.getLoadBalancer("smart-platform-base"); return zbm.getRule().getClass().getName(); } }

(3) 自定义负载均衡规则

 ① 创建规则类

import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.Server;

import java.util.List;
import java.util.Random;

public class MyRule implements IRule {

    private ILoadBalancer iLoadBalancer;

    @Override
    public Server choose(Object o) {
        List<Server> servers = iLoadBalancer.getAllServers();
        System.out.println("自定义负载均衡规则,服务器数量:"+servers.size());
        Random random = new Random();
        int num = random.nextInt(10);
        if (num > 7) {
        //特别注意为了方便测试此处将生产者服务的启动端口写死为了8001,8002 如果不一样记得修改
return getServerByPort(servers, 8001); } return getServerByPort(servers, 8002); } @Override public void setLoadBalancer(ILoadBalancer iLoadBalancer) { this.iLoadBalancer = iLoadBalancer; } @Override public ILoadBalancer getLoadBalancer() { return this.iLoadBalancer; } private Server getServerByPort(List<Server> servers, int port) { for (Server server : servers) { if (server.getPort() == port) { return server; } } return null; } }

② 创建规则实例并注入到spring容器中

import com.netflix.loadbalancer.IRule;
import org.springframework.context.annotation.Bean;

public class MyConfig {

    @Bean
    public IRule getRule() {
        return new MyRule();
    }
}

③ 给 ribbon 客户端添加自定规则

import org.springframework.cloud.netflix.ribbon.RibbonClient;

@RibbonClient(name = "smart-platform-base", configuration = MyConfig.class)
public class MyClient {
}

上诉② ③方法是通过代码的方式将自定义的负载均衡规则 添加给了ribbon客户端 smart-platform-base

通过application.yml配置文件的方式添加自定义规则,如下

server:
  port: 9001
spring:
  application:
    name: smart-platform-shumeng
#设置自定义规则 如果将smart-platform-base 改成default 则会对所有的客户端生效,将默认的规则改成 MyRule
smart-platform-base:
  ribbon:
    NFLoadBalancerRuleClassName: com.idelan.platform.config.MyRule
eureka:
  client:
    #指定时间去抓取一次服务列表 默认30秒
    registry-fetch-interval-seconds: 30
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

 

posted @ 2018-12-05 21:00  谋知  阅读(239)  评论(0编辑  收藏  举报