如何设计一个注册中心?(2)实现注册接口

1. 创建SpringBoot工程

创建父工程及三个子模块,其中一个模块作为注册中心,另外两个作为服务提供者。
在这里插入图片描述
pom

<?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>

    <groupId>org.example</groupId>
    <artifactId>registerTest</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>server</module>
        <module>provider1</module>
        <module>provider2</module>
    </modules>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.1.23</version>
        </dependency>
    </dependencies>

</project>

2. 实现http访问

注意:这里目前用的是同步请求,实际用异步才是合适的

package http.client;

import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;

public class HttpClient {
    private String url;
    private String contentType;
    private String encoding;
    private JSONObject data;

    public HttpClient(String url, String encoding, String contentType, JSONObject data) {
        this.url = url;
        this.data = data;
        this.encoding = encoding == null ? "UTF-8" : encoding;
        this.contentType = contentType == null ? "application/json" : contentType;
    }

    public JSONObject httpGet() throws Exception {
        try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {
            HttpGet httpGet = new HttpGet(url);
            HttpResponse response = httpClient.execute(httpGet);
            if (response.getStatusLine().getStatusCode() != 200) {
//            throw new Exception("调用服务端异常.");
                return getResult(false, "调用服务端异常.");
            }
            HttpEntity res = response.getEntity();
            String resultData = EntityUtils.toString(res);
            System.out.println("从服务端返回结果: " + resultData);
            return JSONObject.parseObject(resultData);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return getResult(false, "");
    }

    public JSONObject httpPost() throws Exception {
        try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {
            String json = JSONObject.toJSONString(data);
            StringEntity entity = new StringEntity(json);
            entity.setContentEncoding(encoding);
            entity.setContentType(contentType);
            HttpPost httpPost = new HttpPost(url);
            httpPost.setEntity(entity);
            HttpResponse response = httpClient.execute(httpPost);
            if (response.getStatusLine().getStatusCode() != 200) {
                return getResult(false, "调用服务端异常.");
            }
            HttpEntity res = response.getEntity();
            String resultData = EntityUtils.toString(res);
            System.out.println("从服务端返回结果: " + resultData);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return getResult(false, "");
    }

    public static JSONObject getResult(boolean res, String msg) {
        return new JSONObject(){{
            put("res", res);
            put("msg", msg);
        }};
    }
}

实现一个简单的注册表结构,代表模块的名称和ip

package common;

public class RegisterTable {
    private String name;
    private String ip;

    public RegisterTable(String name, String ip) {
        this.name = name;
        this.ip = ip;
    }

    public String getIp() {
        return ip;
    }
}

3. 注册中心实现

实现注册表管理,增加,删除,查询

package register.list;

import com.alibaba.fastjson.JSONObject;
import common.RegisterTable;
import http.client.HttpClient;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;

@Component
public class RegisterList {
    HashMap<String, ArrayList<RegisterTable>> hashMap = new HashMap<>();

    public JSONObject add(String name, String ip) {
        ArrayList<RegisterTable> list = hashMap.get(name);
        if (list == null) {
            list = new ArrayList<RegisterTable>();
        } else {
            for (RegisterTable table : list) {
                if (table.getIp().equals(ip)) {
                    return HttpClient.getResult(false, "repeat");
                }
            }
        }
        RegisterTable registerTable = new RegisterTable(name,ip);
        list.add(registerTable);
        hashMap.put(name, list);
        return HttpClient.getResult(true, "success");
    }

    public HashMap<String, ArrayList<RegisterTable>> getAll() {
        return hashMap;
    }

    public ArrayList<RegisterTable> getByName(String name) {
        return hashMap.get(name);
    }
}

提供注册接口:

package register.control;

import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import register.list.RegisterList;

@RestController
@RequestMapping("/register")
public class Register {

    @Autowired
    RegisterList registerList;

    @PostMapping("/register")
    public JSONObject register(@RequestBody JSONObject data) {
        //处理注册逻辑
        return registerList.add(data.getString("name"), data.getString("ip"));
    }

    @GetMapping("/list/{name}")
    public Object getList(@PathVariable(value = "name", required = true) String name) {
        //获取注册列表
        return registerList.getByName(name);
    }

    @GetMapping("/list/all")
    public Object getList() {
        return registerList.getAll();
    }
}

4. provider模块

功能:项目启动后发送注册信息到注册中心模块。

package common.register;

import com.alibaba.fastjson.JSONObject;
import http.client.HttpClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

@Component
public class Register implements ApplicationRunner {

    @Value("${model.name}")
    String name;

    @Value("${model.host}")
    String host;

    @Value("${model.port}")
    String port;

    @Value("${register.url}")
    String url;

    //发送注册消息
    @Override
    public void run(ApplicationArguments args) throws Exception {
        register();
    }

    private void register() throws Exception {
        JSONObject data = new JSONObject() {{
            put("name", name);
            put("ip", "http://" + host + ":" + port);
        }};
        HttpClient client = new HttpClient(url, null, null, data);
        client.httpPost();
    }
}

application.yml

server:
  port: 8001

model:
  name: "provider"
  port: "8001"
  host: "127.0.0.1"

register:
  url: "http://localhost:8080/register/register"

另外一个provider也是一样,不过端口不同

5. 测试

启动后:
在这里插入图片描述
查询注册表:两个模块都已经注册。
在这里插入图片描述

缺点

这种做法有非常大的缺点,就是如果先启动客户端再启动服务器,则无法完成注册,会报错链接服务器失败。因此客户端需要不断的重新注册,直到成功。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值