提供三个角色:服务注册中心、服务提供者、服务消费者。用来模拟Eureka
服务提供者与消费者关系。
流程
- 启动注册中心
- 服务提供者生产服务并注册到服务中心中
- 消费者从服务中心中获取服务并执行
(图片来源于网络)
服务注册中心
参考另一片笔记《SpringCloud(注册中心Eureka)》
服务提供者
提供一个hello()
方法打印一个字符串。
新建一个名为spring-cloud-producer
的SpringBoot
工程
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
服务。
访问http://localhost:28084/hello/?name=zhangsan
可以看到有返回结果,说明服务提供者已经配置完成。
服务消费者
创建服务消费者根据使用 API 的不同,大致分为三种方式(LoadBalancerClient
、Spring Cloud Ribbon
和Feign
调用实现)。在实际使用中用的应该都是 Feign
,这里只记录Feign
。
创建一个名为eureka-consumer
的SpringBoot
工程
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
服务。
访问http://localhost:28085/hello/zhangsan,得到如下结果,说明消费者成功消费了提供者的服务。
其他
要想使用 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包,然后启动两个线程,分别注册到服务注册中心。
当通过消费者调用的时候,会交替消费两个服务,以此来实现负载均衡。