spring-cloud + Zookeeper Demo

参考:https://www.jianshu.com/p/cb21c3b86126

MAC 安装 zookeeper

https://www.jianshu.com/p/5491d16e6abd

启动的时候,一直报错:
./zkServer.sh: line 173: -e /Users/xxx/Downloads/apache-zookeeper-3.5.6/data/zookeeper_server.pid: No such file or directory
经过仔细看 zkServer.sh 脚本,发现
114 ZOO_DATADIR="$(echo -e "${ZOO_DATADIR}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
这行里 echo -e 有问题,把 -e 去掉就 OK。

连接 ZK,写 ZK 时,碰到 
KeeperException$UnimplementedException
通常这是zookeeper客户端和服务端版本不一致造成的,client版本高。
下载最新的zookeeper解决。

Producer 工程

建立 Spring boot 工程

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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.1.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>spring-cloud-zookeeper-producer</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>spring-cloud-zookeeper-producer</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<spring-cloud.version>Dalston.RELEASE</spring-cloud.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
			<version>2.2.0.M2</version>
		</dependency>

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

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

		<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>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
	</dependencies>

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

application.yml

spring:
  application:
    name: HelloWorld
  cloud:
    zookeeper:
      connect-string: localhost:2181
      discovery:
        enabled: true
server:
  port: 8081
endpoints:
  restart:
    enabled: true
logging:
  level:
    org.apache.zookeeper.ClientCnxn: WARN

Main 改造

@SpringBootApplication
@EnableDiscoveryClient
public class SpringCloudZookeeperProducerApplication {

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

}

HelloWorldController

@RestController
public class HelloWorldController {
    @GetMapping("/helloworld")
    public String HelloWorld() {
        return "Hello World!";
    }
}

Consumer 工程

pom.xml
与 Producer 工程的一致。

application.yml

spring:
  application:
    name: Greeting
  cloud:
    zookeeper:
      connect-string: localhost:2181
server:
  port: 8083
logging:
  level:
    org.apache.zookeeper.ClientCnxn: WARN

Main 改造

@SpringBootApplication
@EnableDiscoveryClient
public class SpringCloudZookeeperConsumerApplication {

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

}

HelloWorldClient

@Configuration
@EnableFeignClients
@EnableDiscoveryClient
public class HelloWorldClient {
    @Autowired
    private TheClient theClient;

    @FeignClient(name = "HelloWorld")
    interface TheClient {

        @RequestMapping(path = "/helloworld", method = RequestMethod.GET)
        @ResponseBody
        String HelloWorld();
    }

    public String HelloWorld() {
        return theClient.HelloWorld();
    }
}

GreetingController

@RestController
public class GreetingController {
    @Autowired
    private HelloWorldClient helloWorldClient;

    @GetMapping("/get-greeting")
    public String greeting() {

        return helloWorldClient.HelloWorld();

    }
}

测试

启动 Producer Main

启动 Consumer Main

访问 Consumer

服务注册

  • Producer ZK 节点

get /services/HelloWorld/495dc630-2b8e-4347-98d9-08c01847b3cb

{"name":"HelloWorld","id":"495dc630-2b8e-4347-98d9-08c01847b3cb","address":"10.0.0.6","port":8081,"sslPort":null,"payload":{"@class":"org.springframework.cloud.zookeeper.discovery.ZookeeperInstance","id":"application-1","name":"HelloWorld","metadata":{}},"registrationTimeUTC":1573325073906,"serviceType":"DYNAMIC","uriSpec":{"parts":[{"value":"scheme","variable":true},{"value":"://","variable":false},{"value":"address","variable":true},{"value":":","variable":false},{"value":"port","variable":true}]}}

  • Customer ZK 节点

get /services/Greeting/c67ee628-2624-4792-adef-2298e47b9919

{"name":"Greeting","id":"c67ee628-2624-4792-adef-2298e47b9919","address":"10.0.0.6","port":8083,"sslPort":null,"payload":{"@class":"org.springframework.cloud.zookeeper.discovery.ZookeeperInstance","id":"application-1","name":"Greeting","metadata":{}},"registrationTimeUTC":1573326354388,"serviceType":"DYNAMIC","uriSpec":{"parts":[{"value":"scheme","variable":true},{"value":"://","variable":false},{"value":"address","variable":true},{"value":":","variable":false},{"value":"port","variable":true}]}}

1. 无论 Producer 还是 Consumer,在 ZK 上节点内容是一致的。实际上,Consumer 本身也可作为其他 Consumer 的 Producer。

2. 当服务停止而不可用,相应的 ZK 节点消失。

服务发现

HelloWorldClient

@Configuration
@EnableFeignClients
@EnableDiscoveryClient
public class HelloWorldClient {
    @Autowired
    private TheClient theClient;

    @FeignClient(name = "HelloWorld")
    interface TheClient {

        @RequestMapping(path = "/helloworld", method = RequestMethod.GET)
        @ResponseBody
        String HelloWorld();
    }

    public String HelloWorld() {
        return theClient.HelloWorld();
    }
}
  • Producer 在 ZK 上注册的 service 名字 HelloWorld 来自 application.yml 的配置:
spring:
  application:
    name: HelloWorld
  • HelloWorldClient 中的 @FeignClient(name = "HelloWorld") 的 HelloWorld 即 Producer 的 app 名。
  • 服务发现的关键在于 @EnableDiscoveryClient
发布了34 篇原创文章 · 获赞 0 · 访问量 1393

猜你喜欢

转载自blog.csdn.net/justsomebody126/article/details/102993806