1. 程式人生 > >負載均衡框架 ribbon 三

負載均衡框架 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/