消费者 去注册中心获取信息 然后缓存到本地 如果有生产者某个服务宕机了 会通过通知的方式告知 (订阅的方式)
微服务rpc远程调用框架中,服务的负载均衡都是采用本地负载均衡的,Spring Cloud 使用的ribbon(本地负载均衡)
如果使用Nginx,那么获取到服务信息后,请求要交给Nginx,再由Nginx进行转发实现负载均衡
本地负载均衡:本地服务从注册中心上获取服务信息列表(缓存在JVM),然后在本地使用rpc远程调用技术,比如Netty、Netty。本地负载均衡更容易实时刷新新数据。
本地效率更高呀
实现如下架构:
在玩的时候注意 不要加端口号
完整路径:/ 一定要加
pom
<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>com.toov5.SocketForDubbo</groupId> <artifactId>com.toov5.SocketForDubbo</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> <version>0.8</version> </dependency> </dependencies> </project>
服务器端
package com.toov5.SocketForDubboServer; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import org.I0Itec.zkclient.ZkClient; //##ServerScoekt服务端 public class ZkServerScoekt implements Runnable { private static int port = 8080; // socket 服务启动后的所使用的 端口号 private static String parentService = "/service"; private static ZkClient zkClient = new ZkClient("192.168.91.5"); public static void main(String[] args) throws IOException { ZkServerScoekt server = new ZkServerScoekt(port); // 构造函数传入port regServer(); // 去zk注册 Thread thread = new Thread(server); thread.start(); } public ZkServerScoekt(int port) { ZkServerScoekt.port = port; } // 注册服务 public static void regServer() { // 先创建父节点 判断 if (!zkClient.exists(parentService)) { // 创建父 节点 zkClient.createPersistent(parentService); // 创建父节点(持久化) } //存在就不用管了 // 创建子节点 String serverKey = parentService + "/server_" + port; // 约定了个规范 if (!zkClient.exists(serverKey)) { zkClient.createEphemeral(serverKey, "127.0.0.1:" + port); // 临时的 上面的删除是必须的 删除一遍 在创建 保持最新的 本地获取到 进行负载均衡 } else { zkClient.delete(serverKey); } } public void run() { ServerSocket serverSocket = null; try { serverSocket = new ServerSocket(port); System.out.println("Server start port:" + port); Socket socket = null; while (true) { socket = serverSocket.accept(); new Thread(new ServerHandler(socket)).start(); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (serverSocket != null) { serverSocket.close(); } } catch (Exception e2) { } } } }
package com.toov5.SocketForDubboServer; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; public class ServerHandler implements Runnable { private Socket socket; public ServerHandler(Socket socket) { this.socket = socket; } public void run() { BufferedReader in = null; PrintWriter out = null; try { in = new BufferedReader(new InputStreamReader(this.socket.getInputStream())); out = new PrintWriter(this.socket.getOutputStream(), true); String body = null; while (true) { body = in.readLine(); if (body == null) break; System.out.println("Receive : " + body); out.println("Hello, " + body); } } catch (Exception e) { if (in != null) { try { in.close(); } catch (IOException e1) { e1.printStackTrace(); } } if (out != null) { out.close(); } if (this.socket != null) { try { this.socket.close(); } catch (IOException e1) { e1.printStackTrace(); } this.socket = null; } } } }
客户端
package com.toov5.SocketForDubboClient; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; import java.util.ArrayList; import java.util.List; import javax.mail.Address; import org.I0Itec.zkclient.IZkChildListener; import org.I0Itec.zkclient.ZkClient; import org.apache.zookeeper.data.Stat; import org.jboss.netty.channel.StaticChannelPipeline; import org.jboss.netty.util.internal.SystemPropertyUtil; import org.omg.CORBA.PUBLIC_MEMBER; import org.w3c.dom.ls.LSInput; public class ZkServerClient { public static List<String> listServer = new ArrayList<String>(); private static ZkClient zkClient = new ZkClient("192.168.91.5"); private static String parentService = "/service"; public static void main(String[] args) { initServer(); ZkServerClient client = new ZkServerClient(); BufferedReader console = new BufferedReader(new InputStreamReader(System.in)); while (true) { String name; try { name = console.readLine(); if ("exit".equals(name)) { System.exit(0); } client.send(name); } catch (IOException e) { e.printStackTrace(); } } } // 注册所有server public static void initServer() { // 读取所有节点 信息 List<String> children = zkClient.getChildren(parentService); getChildren(zkClient, children); zkClient.subscribeChildChanges(parentService, new IZkChildListener() { public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception { System.out.println("注册中心服务列表信息有变化"); getChildren(zkClient, currentChilds);//如果监听到有变化了 就要重新读取哦 } }); } public static void getChildren(ZkClient zkClient, List<String> children) { listServer.clear(); for (String ch : children) { String serverAddr = zkClient.readData(parentService + "/" + ch); // 拿到服务地址 listServer.add(serverAddr); } System.out.println("服务接口地址"+listServer.toString()); } // 请求总数 private static int reqCount = 1; // //服务个数 // private static int serverCount = 0; //初始值是0 // 获取当前server信息 public static String getServer() { int index = reqCount % listServer.size(); String address = listServer.get(index); System.out.println("客户端请求服务器" + address); reqCount++; return address; } public void send(String name) { String server = ZkServerClient.getServer(); String[] cfg = server.split(":"); Socket socket = null; BufferedReader in = null; PrintWriter out = null; try { socket = new Socket(cfg[0], Integer.parseInt(cfg[1])); in = new BufferedReader(new InputStreamReader(socket.getInputStream())); out = new PrintWriter(socket.getOutputStream(), true); out.println(name); while (true) { String resp = in.readLine(); if (resp == null) break; else if (resp.length() > 0) { System.out.println("Receive : " + resp); break; } } } catch (Exception e) { e.printStackTrace(); } finally { if (out != null) { out.close(); } if (in != null) { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } if (socket != null) { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
客户端去获取下面的 地址信息 就好办了:
运行结果
动态的哦