春クラウドユーレカは、サービスレジストリの開発を分散、負荷分散、宣言型サービスコールの実装

入門

負荷分散、宣言型サービス、サービスレジストリなどをこの例では、ユーレカスプリング・クラウドシリーズを説明し、あなたがすぐに始めることができます

ユーレカサーバー

ユーレカは、位置サービスのためのRESTベースのサービス、クラウドサービス発見及びフェイルオーバーを実現するために、中間層であるNetflixのサブモジュールです。

マイクロアーキテクチャのためのサービスの登録と発見サービスは、それは非常に重要です。サービスの発見と登録して、単にサービスの識別子を使用して設定ファイルサービスの呼び出しを変更することなく、サービスにアクセスできるようになります。この機能は、同様のレジストリダボ、こうした飼育係です。

CSの設計アーキテクチャを使用してユーレカ。サービスレジストリでサーバーサービスの登録機能、などユーレカサーバー。システムは、ユーレカServerに他のマイクロサービスのクライアント接続で使用すると、ハートビート接続を維持しています

ユーレカServerは、登録サービスのサービスを提供しています。各サービスノードを起動した後、利用可能なすべてのサービスノード情報はユーレカサーバ、レジストリ店でユーレカServerサービスでのサービスに登録されています。

ユーレカクライアントは相互作用、クライアントユーレカサーバを簡素化するためのJavaクライアントであり、また、内蔵のアルゴリズムのポーリング負荷のロードバランサを持つこと。アプリケーションを起動した後、ユーレカサーバーにハートビート(デフォルトの時間は30秒)を送ります。ユーレカServerは、複数のハートビート期間中のハートビート・ノードを受信しない場合、ユーレカServerはサービスレジストリサービスノード情報から削除されます。

简单理解:各个微服务将自己的信息注册到server上,需要调用的时候从server中获取到其他微服务信息

リボン

春クラウドリボンは最終顧客Netflixのリボン達成負荷分散ツールのセットに基づいて、その主な機能は、ロードバランシングアルゴリズムクライアントソフトウェアを提供一緒にネットフリックスの中間層サービスを接続することです。

応答時間の重みのように、ポーリングのような、ランダム:リボンは、より多くの負荷分散戦略を提供します。

見せ掛けます

装うは宣言され、テンプレートベースのHTTPクライアントは、より速く、よりエレガントなHTTP 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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.easy</groupId>
    <artifactId>eureka-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>eureka-server</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <artifactId>cloud-feign</artifactId>
        <groupId>com.easy</groupId>
        <version>1.0.0</version>
    </parent>

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

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

application.ymlプロフィール

server:
    port: 9000

spring:
  application:
    name: eureka-server
    
eureka:
    instance:
        hostname: localhost   # eureka 实例名称
    client:
        register-with-eureka: false # 不向注册中心注册自己
        fetch-registry: false       # 是否检索服务
        service-url:
            defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/  # 注册中心访问地址

EurekaServerApplication.java起動クラス

package com.easy.eurekaServer;

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

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

2.ハローサービスAPIインターフェイスを作成します。

Result.java統一エンティティ復帰

package com.easy.helloServiceApi.vo;


import lombok.Getter;

import java.io.Serializable;

@Getter
public class Result implements Serializable {

    private static final long serialVersionUID = -8143412915723961070L;

    private int code;

    private String msg;

    private Object data;

    private Result() {
    }

    private Result(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    private Result(int code, String msg, Object data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }


    public static Result success() {
        return success(null);
    }

    public static Result success(Object data) {
        return new Result(200, "success", data);
    }

    public static Result fail() {
        return fail(500, "fail");
    }

    public static Result fail(int code, String message) {
        return new Result(code, message);
    }
}

Order.javaの注文エンティティクラス

package com.easy.helloServiceApi.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * 订单类
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Order {

    private String orderId;

    private String goodsId;

    private int num;

}

GoodsServiceClient.java文の製品サービスのカテゴリ

package com.easy.helloServiceApi.client;

import com.easy.helloServiceApi.vo.Result;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

@FeignClient(value = "hello-server")
public interface GoodsServiceClient {

    @RequestMapping("/goods/goodsInfo/{goodsId}")
    Result goodsInfo(@PathVariable("goodsId") String goodsId);
}

Goods.java商品エンティティクラス

package com.easy.helloServiceApi.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

/**
 * 商品类
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Goods {

    private String goodsId;

    private String name;

    private String descr;

    // 测试端口
    private int port;
}

3.ハロー・サービス-01のサービスプロバイダを作成します(ここで負荷分散を行うために3つの異なるサービスプロバイダを作成します)

GoodsController.java製品サービスエントランス


package com.easy.helloService.controller;

import com.easy.helloService.service.GoodsService;
import com.easy.helloServiceApi.model.Goods;
import com.easy.helloServiceApi.vo.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/goods")
public class GoodsController {

    @Autowired
    private GoodsService goodsService;

    @RequestMapping("/goodsInfo/{goodsId}")
    public Result goodsInfo(@PathVariable String goodsId) {

        Goods goods = this.goodsService.findGoodsById(goodsId);
        return Result.success(goods);
    }
}

GoodsService.javaインタフェース

package com.easy.helloService.service;

import com.easy.helloServiceApi.model.Goods;

public interface GoodsService {

    Goods findGoodsById(String goodsId);
}

GoodsServiceImpl.javaは、インターフェイスを実装します

package com.easy.helloService.service.impl;

import com.easy.helloService.service.GoodsService;
import com.easy.helloServiceApi.model.Goods;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

@Service
public class GoodsServiceImpl implements GoodsService {

    // 模拟数据库
    private static Map<String, Goods> data;

    static {
        data = new HashMap<>();
        data.put("1", new Goods("1", "华为", "华为手机", 8081));  //表示调用8081端口的数据,实际上数据会放在数据库或缓存中
        data.put("2", new Goods("2", "苹果", "苹果", 8081));
    }

    @Override
    public Goods findGoodsById(String goodsId) {
        return data.get(goodsId);
    }
}

HelloServiceApplication.java起動クラス

package com.easy.helloService;

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

@EnableDiscoveryClient
@SpringBootApplication
public class HelloServiceApplication {

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

application.ymlプロファイル、01サービスポートを行う8081

server:
    port: 8081

spring:
  application:
    name: hello-server
    
eureka:
    instance:
        instance-id: goods-api-8081
        prefer-ip-address: true # 访问路径可以显示 IP
    client:
        service-url:
            defaultZone: http://localhost:9000/eureka/  # 注册中心访问地址

4.ハローサービス-02サービスプロバイダを作成します(01のサービスではなく、同じ場所に掲載)

application.ymlプロファイル、02サービスポートを行う8082

server:
    port: 8082

spring:
  application:
    name: hello-server
    
eureka:
    instance:
        instance-id: goods-api-8082
        prefer-ip-address: true # 访问路径可以显示 IP
    client:
        service-url:
            defaultZone: http://localhost:9000/eureka/  # 注册中心访问地址

GoodsServiceImpl.javaはここに故意に発効していない負荷分散の使用をテストするために使用されるさまざまなデータソースを設定します

package com.easy.helloService.service.impl;

import com.easy.helloService.service.GoodsService;
import com.easy.helloServiceApi.model.Goods;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

@Service
public class GoodsServiceImpl implements GoodsService {

    // 模拟数据库
    private static Map<String, Goods> data;

    static {
        data = new HashMap<>();
        data.put("1", new Goods("1", "华为", "华为手机", 8082));  //表示8082端口的数据,实际上数据会放在数据库或缓存中
        data.put("2", new Goods("2", "苹果", "苹果", 8082));
    }

    @Override
    public Goods findGoodsById(String goodsId) {
        return data.get(goodsId);
    }
}

5.ハローサービス-02サービスプロバイダを作成します(01のサービスではなく、同じ場所に掲載)

application.ymlプロファイル、02サービスポートを行う8082

server:
    port: 8083

spring:
  application:
    name: hello-server
    
eureka:
    instance:
        instance-id: goods-api-8083
        prefer-ip-address: true # 访问路径可以显示 IP
    client:
        service-url:
            defaultZone: http://localhost:9000/eureka/  # 注册中心访问地址

GoodsServiceImpl.javaはここに故意に発効していない負荷分散の使用をテストするために使用されるさまざまなデータソースを設定します

package com.easy.helloService.service.impl;

import com.easy.helloService.service.GoodsService;
import com.easy.helloServiceApi.model.Goods;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

@Service
public class GoodsServiceImpl implements GoodsService {

    // 模拟数据库
    private static Map<String, Goods> data;

    static {
        data = new HashMap<>();
        data.put("1", new Goods("1", "华为", "华为手机", 8083));  //表示8083端口的数据,实际上数据会放在数据库或缓存中
        data.put("2", new Goods("2", "苹果", "苹果", 8083));
    }

    @Override
    public Goods findGoodsById(String goodsId) {
        return data.get(goodsId);
    }
}

6.消費者に装う - 消費者サービスを作成し、導入リボンは、サービスコールの負荷分散を実装し、宣言型のサービスコールを実装します

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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.easy</groupId>
    <artifactId>feign-consumer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>feign-consumer</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <artifactId>cloud-feign</artifactId>
        <groupId>com.easy</groupId>
        <version>1.0.0</version>
    </parent>

    <dependencies>

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

        <!-- eureka 客户端 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

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

        <!-- feign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.9</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.easy</groupId>
            <artifactId>hello-service-api</artifactId>
            <version>0.0.1</version>
        </dependency>
    </dependencies>

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

登録、ディスカバリサービスのopenfeign、リボン、ユーレカ・クライアントと宣言型のサービスコールを実装するために使用される他の依存、openfeignの導入、負荷分散を実現するために使用されたリボン、ユーレカ、クライアント

RestConfiguration.java設定

package com.easy.feignConsumer.config;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestConfiguration {

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

    /**
     * 随机选取负载均衡策略
     * @return
     */
    @Bean
    public IRule testRule() {
        return new RandomRule();
    }
}

GoodsServiceサービスクラス・インターフェース

package com.easy.feignConsumer.service;

import com.easy.helloServiceApi.model.Goods;
import com.easy.helloServiceApi.vo.Result;

public interface GoodsService {
    Result placeGoods(Goods goods);
}

GoodsServiceImpl.java実装クラス

package com.easy.feignConsumer.service.impl;

import com.easy.feignConsumer.service.GoodsService;
import com.easy.helloServiceApi.client.GoodsServiceClient;
import com.easy.helloServiceApi.model.Goods;
import com.easy.helloServiceApi.vo.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class GoodsServiceImpl implements GoodsService {

    @Autowired
    private GoodsServiceClient goodsServiceClient;

    @Override
    public Result placeGoods(Goods order) {

        Result result = this.goodsServiceClient.goodsInfo(order.getGoodsId());

        if (result != null && result.getCode() == 200) {
            log.info("=====获取本地商品====");
            log.info("接口返回数据为==>{}", ToStringBuilder.reflectionToString(result.getData()));
        }
        return result;
    }
}

GoodsController.javaコントローラ

package com.easy.feignConsumer.controller;

import com.easy.feignConsumer.service.GoodsService;
import com.easy.helloServiceApi.model.Goods;
import com.easy.helloServiceApi.vo.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/goods")
public class GoodsController {

    @Autowired
    private GoodsService orderService;

    @RequestMapping("/place")
    public Result placeGoods(Goods goods) {
        Result result = this.orderService.placeGoods(goods);
        return result;
    }
}

FeignConsumerApplication.javaの密告起動クラス

package com.easy.feignConsumer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@EnableFeignClients(basePackages = {"com.easy"})
@EnableEurekaClient
@SpringBootApplication
public class FeignConsumerApplication {

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

application.ymlプロフィール

server:
  port: 8100

spring:
  application:
    name: feign-consumer

eureka:
  instance:
    instance-id: order-api-8100
    prefer-ip-address: true # 访问路径可以显示 IP
  client:
    service-url:
      defaultZone: http://localhost:9000/eureka/  # 注册中心访问地址

使用例

作成した5つのサービスを実行します

サービスレジストリ、3つのサービスプロバイダ、消費者向けサービス

サービスレジストリサービスにチェック

アドレスバーます。http:// localhost:9000 /、我々は5つのサービスが正常に登録動作していると、以下のような状態(UP状態)が、効果がある参照してください。

  • 2つのサービス(装う-CONSUMER、ハロー-SERVER)の下に記載されているアプリケーション
  • これは、利用可能なサービスの数は、利用可能ゾーンに記載されている(図1及び図3は、ここで示されている)を表します
  • (財-API-8100(顧客サービス)、商品-API-8081(サービスプロバイダ01)、グッズ-API-8082を:[ステータス]列は、サービスのステータスを表示し、UPはサービスが実行されていることを示し、内部アドレスは、それぞれ、サービスの後ろに続きますサービスプロバイダ02)、グッズ-API-8083(サービスプロバイダ03)

インタフェースのテストを呼び出します

アドレスバーます。http:// localhost:8100 /雑貨/場所goodsId = 1、データ結果を返します?:

{
code: 200,
msg: "success",
data: {
goodsId: "1",
name: "华为",
descr: "华为手机",
port: 8081
}
}
  • マルチページ数回を更新し、我々はポートが力に私たちのランダムなロードバランサを表現するために、ランダムに808180828083が変化することを発見しました
  • 、2またはサービスプロバイダをオフページのインターフェース機能は効果がありませんリフレッシュすること自由に、高可用性を実現するために、通常のデータに戻すことができます

宣言型サービスと非宣言のサービス比較

非宣言サービスの呼び出しコード

    @Test
    public void testFeignConsumer() {
        Goods goods = new Goods();
        goods.setGoodsId("1");
        Result result = this.restTemplate.getForObject("http://HELLO-SERVER/goods/goodsInfo/" + goods.getGoodsId(), Result.class);
        log.info("成功调用了服务,返回结果==>{}", ToStringBuilder.reflectionToString(result));
    }

各リクエストメソッドの消費者側がサービス要求のURLアドレスを継ぐ必要があり、問題があり、これは、オブジェクト指向プログラミングの考え方に沿ってハードコーディングされていません

宣言型サービスコール

@FeignClient(value = "hello-server")
public interface GoodsServiceClient {

    @RequestMapping("/goods/goodsInfo/{goodsId}")
    Result goodsInfo(@PathVariable("goodsId") String goodsId);
}
    @Autowired
    private GoodsServiceClient goodsServiceClient;

    @Override
    public Result placeGoods(Goods order) {
        Result result = this.goodsServiceClient.goodsInfo(order.getGoodsId());
        return result;
    }

書き込みや注釈を挿入するためのシンプルなインターフェースを介して、あなたは情報パラメータ、フォーマット、アドレス、および他の良いHTTPリクエスト、リモートインターフェース呼び出しを定義することができますので、我々のコードとは、よりスケーラブルな、複雑なオブジェクト指向プログラミングを使用します。

データ

おすすめ

転載: www.cnblogs.com/tqlin/p/11532661.html