Follow me Spring Cloud (iii) service providers and call Eureka Finchley [version] -b2b2c E-commerce

Describes the Eureka building service registry, this article describes how to use the Eureka service registry, set up a simple registration server service, clients use the service to call the case.

Case has three roles: service registry, service providers, service consumers, service registry, which is what we in Eureka on a single node starts either.
Process is as follows:

Start registry
service providers and production services registered with the service center
consumers to obtain service from the service center and the implementation of
Here Insert Picture Description
a service provider
we assume that the service provider has a hello () method, according to the incoming parameters, provides an output "hello xxx + current time "service.

POM package configuration
to create a basic Spring Boot application, designated eureka-producer, add the following configuration in pom.xml:

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

Profile
application.yml configuration is as follows

spring:
  application:
    name: eureka-producer
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7000/eureka/
server:
  port: 8000

By spring.application.name property, we can specify the name of the micro-services follow only need to use this name when calling on it to access the service. Configure Content eureka.client.serviceUrl.defaultZone property corresponds to the service registry, specify the location of a service registry. In order to test the machine and to distinguish the service provider service registry, a different set of attributes server.port port.

Start class
to keep the default can be generated, Finchley.RC1 this version of the Spring Cloud has no need to add @EnableDiscoveryClient annotated. (So if I introduced the relevant jar package and want to disable the service registration and discovery how to do? Set eureka.client.enabled = false)

@EnableDiscoveryClient is no longer required. You can put a DiscoveryClient implementation on the classpath to cause the Spring Boot application to register with the service discovery server.
Spring Cloud - @EnableDiscoveryClient

@SpringBootApplication
    public class EurekaProducerApplication {

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

}

Controller
provides hello services

@Restcontroller
@RequestMapping("/hello")
  public  class  HelloController {

         @GetMapping  ("/")
   public String hello(@RequestParam String name) {
       return "Hello, " + name + " " + new Date();
   }

}

After starting the project, you can see EUERKA-PRODUCER service in the registry Eureka page.
Here Insert Picture Description
Service consumers
created according to different service consumers using the API, there are roughly three ways. Although we should all be using Feign in actual use, but these three are still here tell us about it, if you are only interested Feign, you can jump directly to the final.

Three ways to use the same configuration file is no longer alone explains

spring:
  application:
    name: eureka-consumer
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7000/eureka/ # 指定 Eureka 注册中心的地址
server:
  port: 9000 # 分别为 9000、9001、9002

Use LoadBalancerClient
from LoadBalancerClient interface name, we know that this is an abstract definition of a client load balancing, let's look at how to use consumer Spring Cloud provides load balancing client interface to implement the service.

POM package configuration
we first create a service consumer project, named: eureka-consumer. pom.xml with the Producer, and not repeat them.

Start the class
initialization RestTemplate, REST request to initiate.

@SpringBootApplication
public class EurekaConsumerApplication {

   @Bean 
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

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

Controller
to create an interface for consuming interface eureka-producer provided:

@RequestMapping ("/hello")

@RestController 
public class HelloController {

   @Autowired 
    private LoadBalancerClient client;

    @Autowired
    private RestTemplate restTemplate;

   @GetMapping ("/")
    public String hello(@RequestParam String name) {
        name += "!";
        ServiceInstance instance = client.choose("eureka-producer");
        String url = "http://" + instance.getHost() + ":" + instance.getPort() + "/hello/?name=" + name;
        return restTemplate.getForObject(url, String.class);
    }

}

You can see here, we injected LoadBalancerClient and RestTemplate, and hello method, the first to choose the method by loadBalancerClient load balancing service instances elect a eureka-producer of basic information stored in ServiceInstance this service instances, and then by the information of these objects splicing out the caller's access services / hello address / interface, and finally the use of RestTemplate object implements the interface provides the caller to the service.

In addition, in order from the returned when calling the results have with the service provider a distinction here I simply deal with it, name + = "!", That is, response service caller will provide more than an exclamation point person than the service ( !).

Spring Cloud Ribbon
Introduced before the Ribbon, which is based on HTTP and TCP client load balancer. It can be configured ribbonServerList in the client to set the server to the list of polling access to achieve the effect of load balancing.

Ribbon When used in conjunction with Eureka, ribbonServerList DiscoveryEnabledNIWSServerList will be rewritten, expanded to obtain service instances from Eureka registry list. At the same time it will be replaced with NIWSDiscoveryPing IPing, it will delegate responsibilities to Eureka to determine whether the services have been started.

POM package configuration
will be before the eureka-consumer copy engineering, and named eureka-consumer-ribbon.

pom.xml file also on the line before use. As for spring-cloud-starter-ribbon, because Spring Cloud version I am using Finchley.RC1, spring-cloud-starter-netflix-eureka-client inside already contains a spring-cloud-starter-netflix-ribbon up.

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

Start class
to modify the application main class, add annotations to RestTemplate @LoadBalanced

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

Controller
modify Controller, remove LoadBalancerClient, and modify the process initiation request directly RestTemplate

@GetMapping("/")
public String hello(@RequestParam String name) {
    name += "!";
    String url = "http://eureka-producer/hello/?name=" + name;
    return restTemplate.getForObject(url, String.class);
}

As you may have noticed, there is the direct use of the service name eureka-producer replaces the previous specific host: port. Why then such a request can be called a success? Spring Cloud Ribbon time because there is a interceptors, it is capable of actually call here, to automatically select the service instance, and replace where the service name to the actual IP address and port to be requested to complete the service call interface.

Spring Cloud Feign
in practice, we are basically using Feign to complete the call. Feign us to show how easy definitions and declarations calling for eureka-producer services through an example. Welcome to add my qq: 1038774626 discuss technical issues.
POM package configuration
to create a basic Spring Boot application, designated eureka-producer-feign, add the following configuration in pom.xml:

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

Start class
on startup class plus @EnableFeignClients

@EnableFeigClients
@SpringBootApplication
public class EurekaConsumerFeignApplication {

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

Feign call implementation
create a client interface definition of Feign. @FeignClient use annotations to specify the name of the service interface to call the various functions defined in the interface using annotations Spring MVC REST interface can bind since the service provider, such as the following is the binding / hello eureka-producer services / examples of interfaces:

 @FeignClient 
(name = "eureka-producer")
public interface HelloRemote {

   @GetMapping ("/hello/")
    String hello(@RequestParam(value = "name") String name);

}

Methods in this class and in Contoller remote service method name and parameters to be consistent.

Here are a few pit, behind a detailed description.

Controller
modify Controller, will HelloRemote injected into the controller layer, like a regular method to call to

@RequestMapping
@Restcontroller ("/hello")

public class HelloController {

    @Autowired
    HelloRemote helloRemote;

  @GetMapping  ("/{name}")
    public String index(@PathVariable("name") String name) {
        return helloRemote.hello(name + "!");
    }

}

Ways to achieve service invocation by Spring Cloud Feign very simple, to unify the interfaces defined by @FeignClient statement we need to rely on micro-service interface. In particular, when used just like calling a local method that can be invoked. Since Feign is based on the Ribbon to achieve, so it comes with a client load balancing policies can also be extended through the Ribbon IRule. In addition, Feign also integrated Hystrix for fault tolerance and protection services, saying more about this in the back. (In Finchley.RC1 version, Feign's Hystrix is ​​off by default. Reference Spring Cloud OpenFeign and Disable HystrixCommands For FeignClients By Default).

In my IDEA years, there will be error, as
Here Insert Picture Description
this is actually not control, run time will be properly injected. If you think that this annoying prompts, you can add annotations @Component HelloRemote this interface on top.
Stepped pit recording
One problem: not have have the Available Server
com.netflix.client.ClientException: the Load Balancer does not have have the Available for Client Server: Eureka-Producer
This problem started bothering me for a long time, finally found out that I did not join eureka-client this dependency, an increase of only spring-boot-starter-web and the spring-cloud-starter-openfeign. Only the latter two, then start, when in fact there is not any exception is thrown,
but if you carefully look at the log, then start, which actually can be seen that there is a really is not acquired any services

c.netflix.loadbalancer.BaseLoadBalancer: Client: eureka-producer instantiated a LoadBalancer: DynamicServerListLoadBalancer: {NFLoadBalancer: name = eureka-producer, current list of Servers = [], Load balancer stats = Zone stats: {}, Server stats: [ ]} ServerList: null
Therefore, in order to use Feign, dependent on at least the following three

Starter--Boot-Spring Web
Spring-Cloud-Starter-openfeign
Spring-Cloud-Starter-Eureka-Client-Netflix
Second problem: the Request Method 'the POST' Not Supported
feign.FeignException: Hello Status # 405 Reading HelloRemote (String); Content :
{ "timestamp": "2018-04-13T16: 29: 12.453 + 0000", "Status": 405, "error": "Method, the Allowed Not", "Message": "the Request Method 'the POST' Not Supported", "path": "/ Hello /"}
HelloRemote code is such that the upper side abnormal

@GetMapping("/hello/")
String hello(String name);

Into this, or the same abnormal

@RequestMapping(value = "/hello/", method = RequestMethod.GET)
String hello(String name);

Another change, this time the OK

@GetMapping("/hello/")
String hello(@RequestParam(value = "name") String name);

The problem is quite wonderful, without @RequestParam becomes a POST request, whether I was @GetMapping or method = RequestMethod.GET, also silent.
As for how to think added a @RequestParam (value = "name") , a long story. At first I did not add eureka-client dependency, did not increase @RequestParam notes, a start on the reported abnormal:

Caused by: java.lang.IllegalStateException: PathVariable annotation was empty on param 0.
so we added a @RequestParam, regarded as a lucky hit it.

As to why the emergence of this situation changed GET POST, and personal guess it should be when the parameter is not modified @RequestParam notes will automatically be treated as a request body. As long as the body, it will be considered Feign POST request, so the whole service is treated as POST request parameter and body with a request sent out.

Load balancing
these three methods can achieve load balancing, access is by way of poll implemented. The way we used to do a Feign test.

In the above eureka-producer of a modified example, in which the controller changes are as follows:

@Restcontroller
@RequestMapping("/hello")
public class HelloController {

  @Value  ("${config.producer.instance:0}")
    private int instance;

   @GetMapping ("/")
    public String hello(@RequestParam String name) {
        return "[" + instance + "]" + "Hello, " + name + " " + new Date();
    }

}

Start packing

// 打包
mvn clean package  -Dmaven.test.skip=true

// 分别以 8000 和 8001 启动实例 1 和 实例 2
java -jar target/eureka-producer-0.0.1-SNAPSHOT.jar --config.producer.instance=1 --server.port=8000
java -jar target/eureka-producer-0.0.1-SNAPSHOT.jar --config.producer.instance=2 --server.port=8001

// 在端口 9002 上启动 eureka-consumer-feign
java -jar target/eureka-eureka-consumer-feign-0.0.1-SNAPSHOT.jar --server.port=9002
Published 12 original articles · won praise 35 · views 450

Guess you like

Origin blog.csdn.net/m0_46413054/article/details/104629821