提供三个角色:服务注册中心、服务提供者、服务消费者。用来模拟Eureka服务提供者与消费者关系。

流程

  1. 启动注册中心
  2. 服务提供者生产服务并注册到服务中心中
  3. 消费者从服务中心中获取服务并执行

服务提供者和消费者流程

(图片来源于网络

服务注册中心

参考另一片笔记《SpringCloud(注册中心Eureka)

服务提供者

提供一个hello()方法打印一个字符串。

新建一个名为spring-cloud-producerSpringBoot工程

POM文件部分配置

<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
</properties>

<dependencies>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</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-web</artifactId>
</dependency>

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

</dependencies>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

application.yml文件配置

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

通过spring.application.name属性,我们可以指定微服务的名称后续在调用的时候只需要使用该名称就可以进行服务的访问。eureka.client.serviceUrl.defaultZone属性对应服务注册中心的配置内容,指定服务注册中心的位置。为了在本机上测试区分服务提供方和服务注册中心,使用server.port属性设置不同的端口。

启动类

保持默认生成的即可, Finchley.RC1 这个版本的 Spring Cloud 已经无需添加@EnableDiscoveryClient注解了。如果引入了相关的jar包,需要禁用服务注册与发现,只需设置eureka.client.enabled=false

@SpringBootApplication
public class SpringCloudProducerApplication {

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

}

定义一个简单Controller接口,用来提供hello服务

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

@GetMapping("/")
public String hello(@RequestParam String name) {
return "Hello, " + name + ", 现在时间:" + System.currentTimeMillis();
}

}

至此,服务提供者就开发完成了。分别启动服务注册中心和服务提供者,可以在注册http://localhost:28081中心看到EUERKA-PRODUCER服务。

EUERKA-PRODUCER

访问http://localhost:28084/hello/?name=zhangsan

可以看到有返回结果,说明服务提供者已经配置完成。

Hello Zhangsan

服务消费者

创建服务消费者根据使用 API 的不同,大致分为三种方式(LoadBalancerClientSpring Cloud RibbonFeign 调用实现)。在实际使用中用的应该都是 Feign,这里只记录Feign

创建一个名为eureka-consumerSpringBoot工程

POM包配置

<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</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-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>
</dependencies>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

配置文件

spring:
application:
name: eureka-consumer
eureka:
client:
service-url:
defaultZone: http://localhost:28081/eureka/
server:
port: 28085

启动类

在启动类上加上@EnableFeignClients

@EnableFeignClients
@SpringBootApplication
public class EurekaConsumerApplication {

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

}

Feign 调用实现

创建一个 Feign 的客户端接口定义。使用@FeignClient注解来指定这个接口所要调用的服务名称,接口中定义的各个函数使用 Spring MVC 的注解就可以来绑定服务提供方的 REST 接口,比如下面就是绑定 eureka-producer 服务的/hello/接口的例子:

@FeignClient(name = "eureka-producer")
public interface HelloRemote {
@GetMapping("/hello/")
String hello(@RequestParam(value = "name") String name);

}

此类中的方法和远程服务中 Contoller 中的方法名和参数需保持一致。

Controller

HelloRemote注入到Controller中,像普通方法一样调用。

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

@Autowired
HelloRemote helloRemote;

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

}

通过 Spring Cloud Feign 来实现服务调用的方式非常简单,通过@FeignClient定义的接口来统一的声明我们需要依赖的微服务接口。而在具体使用的时候就跟调用本地方法一点的进行调用即可。由于 Feign 是基于 Ribbon 实现的,所以它自带了客户端负载均衡功能,也可以通过 Ribbon 的 IRule 进行策略扩展。另外,Feign 还整合的 Hystrix 来实现服务的容错保护。

在 Finchley.RC1 版本中,Feign 的 Hystrix 默认是关闭的。

启动服务,在注册http://localhost:28081中心看到eureka-consumer服务。

eureka-consumer

访问http://localhost:28085/hello/zhangsan,得到如下结果,说明消费者成功消费了提供者的服务。

eureka-consumer

其他

要想使用 Feign,至少需要以下三个依赖

  • spring-boot-starter-web
  • spring-cloud-starter-openfeign
  • spring-cloud-starter-netflix-eureka-cli

HelloRemote类中的方法参数要加上@RequestParam注解

Get请求的类型, 要加上@RequestParam注解,否则会报错。。

当参数没有被@RequestParam注解修饰时,会自动被当做 request body 来处理。只要有 body,就会被 Feign 认为是 POST 请求,所以整个服务是被当作带有 request parameter 和 body 的 POST 请求发送出去的。

负载均衡

将producer工程打包成Jar包,然后启动两个线程,分别注册到服务注册中心。

当通过消费者调用的时候,会交替消费两个服务,以此来实现负载均衡。