配置映射主机名和IP
为每台虚拟主机的/etc/hosts文件加上如下内容,服务发现需要用到默认主机名作为访问地址,这样可以不用为每个服务实例配置IP
192.168.253.30 megumi-30 192.168.253.31 megumi-31 192.168.253.32 megumi-32
服务提供方
1.Maven依赖
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zookeeper-all</artifactId> </dependency> </dependencies>
2. 父模块的依赖管理
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>1.5.3.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-zookeeper-dependencies</artifactId> <version>1.1.1.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-netflix-dependencies</artifactId> <version>1.3.4.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>io.reactivex</groupId> <artifactId>rxjava</artifactId> <version>1.3.1</version> </dependency> </dependencies> </dependencyManagement>
3. bootstrap.yml (这里配置应用程序的名称,也就是服务的名称,用于Feign查找服务,启用服务发现和注册)
spring: application: name: demo-service cloud: zookeeper: connect-string: 192.168.253.30:2181,192.168.253.31:2181,192.168.253.32:2181 discovery: enabled: true register: true
4. App.java 用@EnableDiscoveryClient注解配置启用服务发现
package demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @EnableDiscoveryClient @SpringBootApplication public class App { public static void main(String[] args) throws Exception { SpringApplication.run(App.class, args); } }
5. DemoController.java
package demo; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping(value = "/api/demo") public class DemoController { private static final UUID INSTANCE_UUID = UUID.randomUUID(); @GetMapping(value = "/instance") public Object instance() { return INSTANCE_UUID.toString(); } }
服务消费方
1. Maven依赖 (和提供方同父模块)
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zookeeper-all</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency> </dependencies>
2. bootstrap.yml 这里选择不注册服务
spring:
application:
name: demo-app
cloud:
zookeeper:
connect-string: 192.168.253.30:2181,192.168.253.31:2181,192.168.253.32:2181
discovery:
enabled: true
register: false
3. App.java 同样用注解启用Feign客户端和服务发现
package demo2; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.netflix.feign.EnableFeignClients; @EnableFeignClients @EnableDiscoveryClient @SpringBootApplication public class App { public static void main(String[] args) throws Exception { SpringApplication.run(App.class, args); } }
4. DemoService.java 用注解声明Feign客户端调用的服务名称,与服务提供方yml配置的spring.application.name一致,注意这里虽然能用RequestMapping注解,但是可能引发URL路由注册冲突的问题。
package demo2; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; @FeignClient(value = "demo-service", path = "/api/demo") //@RequestMapping(value = "/api/demo") public interface DemoService { @GetMapping(value = "/instance") String instance(); }
5. DemoController.java
package demo2; import java.util.UUID; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping(value = "/api/demo") public class DemoController { private static final UUID INSTANCE_UUID = UUID.randomUUID(); private final DemoService remoteService; public DemoController(final DemoService remoteService) { this.remoteService = remoteService; } @GetMapping(value = "/remote-instance") public Object remoteInstance() { return this.remoteService.instance(); } @GetMapping(value = "/instance") public Object instance() { return INSTANCE_UUID.toString(); } }
服务启动后,使用zkCli运行 ls /services/demo-service ,可以看到服务的各实例已经被注册到这里。
使用浏览器访问消费方的 /api/demo/remote-instance,不停刷新可以看到值是变化的,说明客户端负载均衡已经在正常工作了。