服务注册

service-discovery
DerekYRC 2 years ago
commit b4e6ccd888

7
.gitignore vendored

@ -0,0 +1,7 @@
out/
target/
.idea/
.idea_modules/
*.iml
*.ipr
*.iws

@ -0,0 +1,52 @@
# <img src="assets/spring-cloud.png" width="80" height="80"> mini-spring-cloud
[![Build Status](https://img.shields.io/badge/build-passing-brightgreen)](https://github.com/DerekYRC/mini-spring-cloud)
[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)
[![Stars](https://img.shields.io/github/stars/DerekYRC/mini-spring-cloud)](https://img.shields.io/github/stars/DerekYRC/mini-spring-cloud)
[![Forks](https://img.shields.io/github/forks/DerekYRC/mini-spring-cloud)](https://img.shields.io/github/forks/DerekYRC/mini-spring-cloud)
**姊妹版:**[**mini-spring**](https://github.com/DerekYRC/mini-spring/blob/main/README_CN.md) **(简化版的spring框架)**
## 关于
**mini-spring-cloud**是简化版的spring-cloud框架能帮助你快速熟悉spring-cloud源码及掌握其核心原理。在保留spring cloud核心功能的的前提下尽量精简代码核心功能包括服务注册、服务发现、负载均衡、集成Feign简化调用、流量控制、熔断降级、API网关等。
希望本项目对你有所帮助,请给个**STAR吧谢谢!!!**
## 功能
#### 基础篇
* [服务注册](https://github.com/DerekYRC/mini-spring-cloud/blob/main/changelog.md#服务注册)
* [服务发现](https://github.com/DerekYRC/mini-spring-cloud/blob/main/changelog.md#服务发现)
* [负载均衡](https://github.com/DerekYRC/mini-spring-cloud/blob/main/changelog.md#集成ribbon实现客户端负载均衡)
* [集成Feign简化调用]()
* [流量控制]()
* [熔断降级]()
* [API 网关]()
#### 扩展篇
> TODO 基础篇遗留的功能点
* [自定义负载均衡规则]()
## 使用方法
阅读 [changelog.md](https://github.com/DerekYRC/mini-spring-cloud/blob/main/changelog.md)
## 常见问题
[**点此提问**](https://github.com/DerekYRC/mini-spring-cloud/issues/1)
常见问题列表: [faq.md](https://github.com/DerekYRC/mini-spring-cloud/blob/main/faq.md)
## 贡献
欢迎Pull Request
## 联系我
手机/微信:**15521077528**
邮箱:**15521077528@163.com**
## 参考
- [《精尽 Spring Cloud 学习指南》](http://svip.iocoder.cn/Spring-Cloud/tutorials/)
## 版权说明
本项目可用于个人学习、非商业性或非盈利性用途。将本项目用于其他用途时,须征得本人的书面许可。

Binary file not shown.

After

Width:  |  Height:  |  Size: 328 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

@ -0,0 +1,338 @@
# [前言](#前言)
前置知识。阅读spring、springboot、spring cloud三者的源码必须严格按照 spring => springboot => spring cloud 的顺序进行阅读spring cloud源码的必备前置知识
- spring推荐本人写的简化版的spring框架 [**mini-spring**](https://github.com/DerekYRC/mini-spring/blob/main/README_CN.md) 。熟悉spring源码阅读springboot源码会非常轻松。
- springboot重点掌握1、启动流程 2、**自动装配的原理! 自动装配的原理!! 自动装配的原理!!!** 推荐文章:
- [Spring Boot精髓启动流程源码分析](https://www.cnblogs.com/java-chen-hao/p/11829344.html)
- [细说SpringBoot的自动装配原理](https://blog.csdn.net/qq_38526573/article/details/107084943)
- [Spring Boot 自动装配原理](https://www.cnblogs.com/javaguide/p/springboot-auto-config.html)
关于spring cloud。spring cloud是构建通用模式的分布式系统的工具集通过[**spring-cloud-commons**](https://github.com/spring-cloud/spring-cloud-commons) 定义了统一的抽象API相当于定义了一套协议标准具体的实现需要符合这套协议标准。spring cloud官方整合第三方组件Eureka、Ribbon、Hystrix等实现了spring-cloud-netflix阿里巴巴结合自身的Nacos、Sentinel等实现了spring-cloud-alibaba。本项目基于spring-cloud-commons的协议标准自主开发或整合第三方组件提供具体的实现。
写作本项目的目的之一是降低阅读原始spring cloud源码的难度。希望掌握本项目讲解的内容之后再阅读原始spring-cloud的源码能起到事半功倍的效果所以本项目的功能实现逻辑及原理和官方保持一致但追求代码最大精简化。
技术能力有限且文采不佳,大家可以在此[**issue**](https://github.com/DerekYRC/mini-spring-cloud/issues/1) 留言提问题和发表建议也欢迎Pull Request完善此项目。
# [服务注册](#服务注册)
> 分支: service-registry
为了演示,写一个非常简单的单机版的服务注册和发现中心,命名图图
```java
@RestController
@SpringBootApplication
public class TutuServerApplication {
private static Logger logger = LoggerFactory.getLogger(TutuServerApplication.class);
private ConcurrentHashMap<String, Set<Server>> serverMap = new ConcurrentHashMap<>();
public static void main(String[] args) {
SpringApplication.run(TutuServerApplication.class, args);
}
/**
* 服务注册
*
* @param serviceName
* @param ip
* @param port
* @return
*/
@PostMapping("register")
public boolean register(@RequestParam("serviceName") String serviceName, @RequestParam("ip") String ip, @RequestParam("port") Integer port) {
logger.info("register service, serviceName: {}, ip: {}, port: {}", serviceName, ip, port);
serverMap.putIfAbsent(serviceName.toLowerCase(), Collections.synchronizedSet(new HashSet<>()));
Server server = new Server(ip, port);
serverMap.get(serviceName).add(server);
return true;
}
/**
* 服务注销
*
* @param serviceName
* @param ip
* @param port
* @return
*/
@PostMapping("deregister")
public boolean deregister(@RequestParam("serviceName") String serviceName, @RequestParam("ip") String ip, @RequestParam("port") Integer port) {
logger.info("deregister service, serviceName: {}, ip: {}, port: {}", serviceName, ip, port);
Set<Server> serverSet = serverMap.get(serviceName.toLowerCase());
if (serverSet != null) {
Server server = new Server(ip, port);
serverSet.remove(server);
}
return true;
}
/**
* 根据服务名称查询服务列表
*
* @param serviceName
* @return
*/
@GetMapping("list")
public Set<Server> list(@RequestParam("serviceName") String serviceName) {
Set<Server> serverSet = serverMap.get(serviceName.toLowerCase());
logger.info("list service, serviceName: {}, serverSet: {}", serviceName, JSON.toJSONString(serverSet));
return serverSet != null ? serverSet : Collections.emptySet();
}
/**
* 查询所有服务名称列表
*
* @return
*/
@GetMapping("listServiceNames")
public Enumeration<String> listServiceNames() {
return serverMap.keys();
}
/**
* 服务
*/
public static class Server {
private String ip;
private Integer port;
//Construct、Getters、equals、hashCode
}
}
```
配置application.yml:
```yaml
server:
port: 6688
```
spring-cloud-commons服务注册相关API:
![](./assets/service-registry-api.png)
- ServiceInstance和Registration表示系统中服务的实例
- ServiceRegistry服务注册和注销接口
- AbstractAutoServiceRegistration自动注册和注销服务。监听WebServerInitializedEvent(Web服务启动完毕事件)WebServerInitializedEvent触发时注册服务实例@PreDestroy注解修饰的方法注销服务实例。
服务注册功能实现:
TutuDiscoveryProperties配置服务注册中心地址:
```java
@ConfigurationProperties("spring.cloud.tutu.discovery")
public class TutuDiscoveryProperties {
@Autowired
private InetUtils inetUtils;
private String serverAddr;
private String service;
private String ip;
private int port = -1;
private boolean secure = false;
@PostConstruct
public void init() throws Exception {
if (!StringUtils.hasLength(ip)) {
//获取服务IP地址
ip = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();
}
}
//getters and setters
}
```
TutuRegistration图图服务注册实例:
```java
public class TutuRegistration implements Registration {
private TutuDiscoveryProperties tutuDiscoveryProperties;
public TutuRegistration(TutuDiscoveryProperties tutuDiscoveryProperties) {
this.tutuDiscoveryProperties = tutuDiscoveryProperties;
}
@Override
public boolean isSecure() {
return tutuDiscoveryProperties.isSecure();
}
@Override
public URI getUri() {
return DefaultServiceInstance.getUri(this);
}
//getters and setters
}
```
注册和注销TutuRegistration的接口TutuServiceRegistry:
```java
public class TutuServiceRegistry implements ServiceRegistry<Registration> {
private static final Logger logger = LoggerFactory.getLogger(TutuServiceRegistry.class);
private TutuDiscoveryProperties tutuDiscoveryProperties;
public TutuServiceRegistry(TutuDiscoveryProperties tutuDiscoveryProperties) {
this.tutuDiscoveryProperties = tutuDiscoveryProperties;
}
/**
* 注册服务实例
*
* @param registration
*/
@Override
public void register(Registration registration) {
Map<String, Object> param = new HashMap<>();
param.put("serviceName", tutuDiscoveryProperties.getService());
param.put("ip", tutuDiscoveryProperties.getIp());
param.put("port", tutuDiscoveryProperties.getPort());
String result = HttpUtil.post(tutuDiscoveryProperties.getServerAddr() + "/register", param);
if (Boolean.parseBoolean(result)) {
logger.info("register service successfully, serviceName: {}, ip: {}, port: {}",
tutuDiscoveryProperties.getService(), tutuDiscoveryProperties.getIp(), tutuDiscoveryProperties.getPort());
} else {
logger.error("register service failed, serviceName: {}, ip: {}, port: {}",
tutuDiscoveryProperties.getService(), tutuDiscoveryProperties.getIp(), tutuDiscoveryProperties.getPort());
throw new RuntimeException("register service failed, serviceName");
}
}
/**
* 注销服务实例
*
* @param registration
*/
@Override
public void deregister(Registration registration) {
Map<String, Object> param = new HashMap<>();
param.put("serviceName", tutuDiscoveryProperties.getService());
param.put("ip", tutuDiscoveryProperties.getIp());
param.put("port", tutuDiscoveryProperties.getPort());
String result = HttpUtil.post(tutuDiscoveryProperties.getServerAddr() + "/deregister", param);
if (Boolean.parseBoolean(result)) {
logger.info("de-register service successfully, serviceName: {}, ip: {}, port: {}",
tutuDiscoveryProperties.getService(), tutuDiscoveryProperties.getIp(), tutuDiscoveryProperties.getPort());
} else {
logger.warn("de-register service failed, serviceName: {}, ip: {}, port: {}",
tutuDiscoveryProperties.getService(), tutuDiscoveryProperties.getIp(), tutuDiscoveryProperties.getPort());
}
}
}
```
AbstractAutoServiceRegistration实现类:
```java
public class TutuAutoServiceRegistration extends AbstractAutoServiceRegistration<Registration> {
private TutuRegistration tutuRegistration;
protected TutuAutoServiceRegistration(ServiceRegistry<Registration> serviceRegistry, TutuRegistration tutuRegistration) {
super(serviceRegistry, null);
this.tutuRegistration = tutuRegistration;
}
@Override
protected Registration getRegistration() {
if (tutuRegistration.getPort() < 0) {
//设置服务端口
tutuRegistration.setPort(this.getPort().get());
}
return tutuRegistration;
}
}
```
自动装配:
TutuServiceRegistryAutoConfiguration:
```java
/**
* 自动配置服务注册相关类
*/
@Configuration
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
public class TutuServiceRegistryAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public TutuDiscoveryProperties tutuProperties() {
return new TutuDiscoveryProperties();
}
@Bean
public TutuRegistration tutuRegistration(TutuDiscoveryProperties tutuDiscoveryProperties) {
return new TutuRegistration(tutuDiscoveryProperties);
}
@Bean
public TutuServiceRegistry tutuServiceRegistry(TutuDiscoveryProperties tutuDiscoveryProperties) {
return new TutuServiceRegistry(tutuDiscoveryProperties);
}
@Bean
public TutuAutoServiceRegistration tutuAutoServiceRegistration(ServiceRegistry<Registration> serviceRegistry, TutuRegistration tutuRegistration) {
return new TutuAutoServiceRegistration(serviceRegistry, tutuRegistration);
}
}
```
META-INF/spring.factories:
```yaml
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.github.cloud.tutu.registry.TutuServiceRegistryAutoConfiguration
```
测试:
1、maven install
![](./assets/service-registry-maven.png)
2、启动服务注册和发现中心TutuServerApplication
3、启动服务提供者ProviderApplication其代码如下:
```java
@RestController
@SpringBootApplication
public class ProviderApplication {
@Value("${server.port}")
private Integer port;
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
@PostMapping("/echo")
public String echo() {
return "Port of the service provider: " + port;
}
}
```
配置application.yml:
```yaml
spring:
application:
name: provider-application
cloud:
tutu:
discovery:
server-addr: localhost:6688
service: ${spring.application.name}
# 随机端口
server:
port: ${random.int[10000,20000]}
```
4、浏览器中访问http://localhost:6688/list?serviceName=provider-application 或执行命令 ```curl -X GET 'http://localhost:6688/list?serviceName=provider-application'``` ,响应报文如下,说明服务已经注册到服务注册中心
```json
[
{
"ip": "192.168.47.1",
"port": 19588
}
]
```

@ -0,0 +1 @@
# 常见问题列表

@ -0,0 +1,36 @@
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>mini-spring-cloud</artifactId>
<groupId>com.github</groupId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>mini-spring-cloud-provider-example</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.github</groupId>
<artifactId>mini-spring-cloud-tutu-discovery</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,28 @@
package com.github.cloud.examples;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author derek()
* @date 2022/3/19
*/
@RestController
@SpringBootApplication
public class ProviderApplication {
@Value("${server.port}")
private Integer port;
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
@PostMapping("/echo")
public String echo() {
return "Port of the service provider: " + port;
}
}

@ -0,0 +1,12 @@
spring:
application:
name: provider-application
cloud:
tutu:
discovery:
server-addr: localhost:6688
service: ${spring.application.name}
# 随机端口
server:
port: ${random.int[10000,20000]}

@ -0,0 +1,41 @@
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>mini-spring-cloud</artifactId>
<groupId>com.github</groupId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>tutu-server</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,133 @@
package com.github.cloud.examples;
import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author derek()
* @date 2022/3/19
*/
@RestController
@SpringBootApplication
public class TutuServerApplication {
private static Logger logger = LoggerFactory.getLogger(TutuServerApplication.class);
private ConcurrentHashMap<String, Set<Server>> serverMap = new ConcurrentHashMap<>();
public static void main(String[] args) {
SpringApplication.run(TutuServerApplication.class, args);
}
/**
*
*
* @param serviceName
* @param ip
* @param port
* @return
*/
@PostMapping("register")
public boolean register(@RequestParam("serviceName") String serviceName, @RequestParam("ip") String ip, @RequestParam("port") Integer port) {
logger.info("register service, serviceName: {}, ip: {}, port: {}", serviceName, ip, port);
serverMap.putIfAbsent(serviceName.toLowerCase(), Collections.synchronizedSet(new HashSet<>()));
Server server = new Server(ip, port);
serverMap.get(serviceName).add(server);
return true;
}
/**
*
*
* @param serviceName
* @param ip
* @param port
* @return
*/
@PostMapping("deregister")
public boolean deregister(@RequestParam("serviceName") String serviceName, @RequestParam("ip") String ip, @RequestParam("port") Integer port) {
logger.info("deregister service, serviceName: {}, ip: {}, port: {}", serviceName, ip, port);
Set<Server> serverSet = serverMap.get(serviceName.toLowerCase());
if (serverSet != null) {
Server server = new Server(ip, port);
serverSet.remove(server);
}
return true;
}
/**
*
*
* @param serviceName
* @return
*/
@GetMapping("list")
public Set<Server> list(@RequestParam("serviceName") String serviceName) {
Set<Server> serverSet = serverMap.get(serviceName.toLowerCase());
logger.info("list service, serviceName: {}, serverSet: {}", serviceName, JSON.toJSONString(serverSet));
return serverSet != null ? serverSet : Collections.emptySet();
}
/**
*
*
* @return
*/
@GetMapping("listServiceNames")
public Enumeration<String> listServiceNames() {
return serverMap.keys();
}
/**
*
*/
public static class Server {
private String ip;
private Integer port;
public Server(String ip, Integer port) {
this.ip = ip;
this.port = port;
}
public String getIp() {
return ip;
}
public Integer getPort() {
return port;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Server server = (Server) o;
if (!ip.equals(server.ip)) return false;
return port.equals(server.port);
}
@Override
public int hashCode() {
int result = ip.hashCode();
result = 31 * result + port.hashCode();
return result;
}
}
}

@ -0,0 +1,67 @@
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>mini-spring-cloud</artifactId>
<groupId>com.github</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>mini-spring-cloud-tutu-discovery</artifactId>
<version>1.0.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
</dependencies>
</project>

@ -0,0 +1,77 @@
package com.github.cloud.tutu;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.util.StringUtils;
import javax.annotation.PostConstruct;
/**
* @author derek()
* @date 2022/3/19
*/
@ConfigurationProperties("spring.cloud.tutu.discovery")
public class TutuDiscoveryProperties {
@Autowired
private InetUtils inetUtils;
private String serverAddr;
private String service;
private String ip;
private int port = -1;
private boolean secure = false;
@PostConstruct
public void init() throws Exception {
if (!StringUtils.hasLength(ip)) {
//获取服务IP地址
ip = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();
}
}
public String getServerAddr() {
return serverAddr;
}
public void setServerAddr(String serverAddr) {
this.serverAddr = serverAddr;
}
public String getService() {
return service;
}
public void setService(String service) {
this.service = service;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public boolean isSecure() {
return secure;
}
public void setSecure(boolean secure) {
this.secure = secure;
}
}

@ -0,0 +1,45 @@
package com.github.cloud.tutu.registry;
import org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
/**
*
*
* @author derek()
* @date 2022/3/19
*/
public class TutuAutoServiceRegistration extends AbstractAutoServiceRegistration<Registration> {
private TutuRegistration tutuRegistration;
protected TutuAutoServiceRegistration(ServiceRegistry<Registration> serviceRegistry, TutuRegistration tutuRegistration) {
super(serviceRegistry, null);
this.tutuRegistration = tutuRegistration;
}
@Override
protected Registration getRegistration() {
if (tutuRegistration.getPort() < 0) {
//设置服务端口
tutuRegistration.setPort(this.getPort().get());
}
return tutuRegistration;
}
@Override
protected Object getConfiguration() {
return tutuRegistration.getTutuDiscoveryProperties();
}
@Override
protected boolean isEnabled() {
return true;
}
@Override
protected Registration getManagementRegistration() {
return null;
}
}

@ -0,0 +1,61 @@
package com.github.cloud.tutu.registry;
import com.github.cloud.tutu.TutuDiscoveryProperties;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.serviceregistry.Registration;
import java.net.URI;
import java.util.Map;
/**
* tutu
*
* @author derek()
* @date 2022/3/19
*/
public class TutuRegistration implements Registration {
private TutuDiscoveryProperties tutuDiscoveryProperties;
public TutuRegistration(TutuDiscoveryProperties tutuDiscoveryProperties) {
this.tutuDiscoveryProperties = tutuDiscoveryProperties;
}
@Override
public String getServiceId() {
return tutuDiscoveryProperties.getService();
}
@Override
public String getHost() {
return tutuDiscoveryProperties.getIp();
}
@Override
public int getPort() {
return tutuDiscoveryProperties.getPort();
}
public void setPort(int port) {
this.tutuDiscoveryProperties.setPort(port);
}
@Override
public boolean isSecure() {
return tutuDiscoveryProperties.isSecure();
}
@Override
public URI getUri() {
return DefaultServiceInstance.getUri(this);
}
@Override
public Map<String, String> getMetadata() {
return null;
}
public TutuDiscoveryProperties getTutuDiscoveryProperties() {
return tutuDiscoveryProperties;
}
}

@ -0,0 +1,87 @@
package com.github.cloud.tutu.registry;
import cn.hutool.http.HttpUtil;
import com.github.cloud.tutu.TutuDiscoveryProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
import java.util.HashMap;
import java.util.Map;
/**
*
*
* @author derek()
* @date 2022/3/19
*/
public class TutuServiceRegistry implements ServiceRegistry<Registration> {
private static final Logger logger = LoggerFactory.getLogger(TutuServiceRegistry.class);
private TutuDiscoveryProperties tutuDiscoveryProperties;
public TutuServiceRegistry(TutuDiscoveryProperties tutuDiscoveryProperties) {
this.tutuDiscoveryProperties = tutuDiscoveryProperties;
}
/**
*
*
* @param registration
*/
@Override
public void register(Registration registration) {
Map<String, Object> param = new HashMap<>();
param.put("serviceName", tutuDiscoveryProperties.getService());
param.put("ip", tutuDiscoveryProperties.getIp());
param.put("port", tutuDiscoveryProperties.getPort());
String result = HttpUtil.post(tutuDiscoveryProperties.getServerAddr() + "/register", param);
if (Boolean.parseBoolean(result)) {
logger.info("register service successfully, serviceName: {}, ip: {}, port: {}",
tutuDiscoveryProperties.getService(), tutuDiscoveryProperties.getIp(), tutuDiscoveryProperties.getPort());
} else {
logger.error("register service failed, serviceName: {}, ip: {}, port: {}",
tutuDiscoveryProperties.getService(), tutuDiscoveryProperties.getIp(), tutuDiscoveryProperties.getPort());
throw new RuntimeException("register service failed, serviceName");
}
}
/**
*
*
* @param registration
*/
@Override
public void deregister(Registration registration) {
Map<String, Object> param = new HashMap<>();
param.put("serviceName", tutuDiscoveryProperties.getService());
param.put("ip", tutuDiscoveryProperties.getIp());
param.put("port", tutuDiscoveryProperties.getPort());
String result = HttpUtil.post(tutuDiscoveryProperties.getServerAddr() + "/deregister", param);
if (Boolean.parseBoolean(result)) {
logger.info("de-register service successfully, serviceName: {}, ip: {}, port: {}",
tutuDiscoveryProperties.getService(), tutuDiscoveryProperties.getIp(), tutuDiscoveryProperties.getPort());
} else {
logger.warn("de-register service failed, serviceName: {}, ip: {}, port: {}",
tutuDiscoveryProperties.getService(), tutuDiscoveryProperties.getIp(), tutuDiscoveryProperties.getPort());
}
}
@Override
public void close() {
}
@Override
public void setStatus(Registration registration, String status) {
throw new UnsupportedOperationException();
}
@Override
public <T> T getStatus(Registration registration) {
return null;
}
}

@ -0,0 +1,41 @@
package com.github.cloud.tutu.registry;
import com.github.cloud.tutu.TutuDiscoveryProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
*
*
* @author derek()
* @date 2022/3/19
*/
@Configuration
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
public class TutuServiceRegistryAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public TutuDiscoveryProperties tutuProperties() {
return new TutuDiscoveryProperties();
}
@Bean
public TutuRegistration tutuRegistration(TutuDiscoveryProperties tutuDiscoveryProperties) {
return new TutuRegistration(tutuDiscoveryProperties);
}
@Bean
public TutuServiceRegistry tutuServiceRegistry(TutuDiscoveryProperties tutuDiscoveryProperties) {
return new TutuServiceRegistry(tutuDiscoveryProperties);
}
@Bean
public TutuAutoServiceRegistration tutuAutoServiceRegistration(ServiceRegistry<Registration> serviceRegistry, TutuRegistration tutuRegistration) {
return new TutuAutoServiceRegistration(serviceRegistry, tutuRegistration);
}
}

@ -0,0 +1,2 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.github.cloud.tutu.registry.TutuServiceRegistryAutoConfiguration

@ -0,0 +1,69 @@
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-build</artifactId>
<version>3.1.1</version>
<relativePath/>
</parent>
<groupId>com.github</groupId>
<artifactId>mini-spring-cloud</artifactId>
<packaging>pom</packaging>
<version>1.0.0-SNAPSHOT</version>
<modules>
<module>mini-spring-cloud-examples/tutu-server</module>
<module>mini-spring-cloud-tutu-discovery</module>
<module>mini-spring-cloud-examples/mini-spring-cloud-provider-example</module>
</modules>
<properties>
<spring.cloud.version>2021.0.1</spring.cloud.version>
<fastjson.version>1.2.79</fastjson.version>
<hutool.version>5.7.21</hutool.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.github</groupId>
<artifactId>mini-spring-cloud-tutu-discovery</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
Loading…
Cancel
Save