运用前边写的RPC demo,结合zookeeper实现服务注册与发现、负载均衡(轮询)
2019-03-30 22:12
423 查看
运用前边写的RPC demo,结合zookeeper实现服务注册与发现、负载均衡(轮询)
本例模拟了user,order,good三个服务,每个服务有2~3个地址,数据只存放在java容器中未和数据库交互,未使用任何成熟框架(后面会用spring cloud实现真实些的项目),配置未实现热加载,后续可能会写关于热加载的东西。。过程中尽量实现基于配置的自动化,避免写死一些东西。
本人电脑很辣鸡内存只有2G,虚拟机卡爆,只能在Windows下操作,且只有这一台电脑,只能用不同端口模拟不同的主机,所以ip都是本地,本例未用到分布式锁,因为用了也测不出效果,后续会基于zookeeper写个简单的。代码较多,只贴出重点。
- 服务注册代码
public static void regServer(String serverAddressKey) { //LoadConfig为读取文件的配置文件工具类 String rigCenterAddress = LoadConfig.getConfigValue("server_rigister_center"); String[] rigCenterPathArr = rigCenterAddress.split(":"); if(rigCenterPathArr.length != 2 || rigCenterPathArr[0] == null || rigCenterPathArr[1] == null){ throw new RuntimeException("获取的注册中心地址有误"); } ZkClient zkClient = new ZkClient(rigCenterAddress, 5000, 2000); //若不存在根节点先创建根节点,持久节点 String rootPath = ExposeAll.rootPath; if (!zkClient.exists(rootPath)) { zkClient.createPersistent(rootPath,rigCenterAddress); } //若不存在相应服务父节点,则先创建,持久节点 String serverType = serverAddressKey.substring(0, serverAddressKey.indexOf("_")); String serverPath = rootPath + LoadConfig.getConfigValue(serverType + "_server_name"); System.out.println("serverPath:"+serverPath); if (!zkClient.exists(serverPath)) { //其子节点才携带具体地址 zkClient.createPersistent(serverPath); } String serverAddress = LoadConfig.getConfigValue(serverAddressKey); String[] addressArr = serverAddress.split(":"); if(addressArr.length != 2 || addressArr[0] == null || addressArr[1] == null){ throw new RuntimeException("获取" + serverAddress + "地址有误"); } //若不存在相应服务节点,则先删除再创建,临时节点 String nodePath = serverPath + "/" + serverAddressKey; if (zkClient.exists(nodePath)) { zkClient.delete(nodePath); } zkClient.createEphemeral(nodePath, serverAddress); System.out.println(nodePath + "服务注册成功"); }
- 服务发现与负载均衡(轮询)
package testZookeeper.testZKServer; import org.junit.Test; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.net.Socket; import java.util.*; public class ServiceProxyFactory { //private static Class consumer; public static Object getService(Class serviceClazz){ return Proxy.newProxyInstance(serviceClazz.getClassLoader(), new Class[]{serviceClazz}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object back = null; String[] path = getPath(serviceClazz); if(null == path || path.length != 2 || path[0] == null || path[1] == null){ throw new RuntimeException("获取的地址有误"); } System.out.println((Arrays.asList(path))); String ip = path[0]; int port; try { port = Integer.parseInt(path[1]); } catch (NumberFormatException e) { throw new RuntimeException("获取的端口有误"); } ObjectOutputStream objOutStream = null; Socket client; try { client = new Socket(ip,port); objOutStream = new ObjectOutputStream(client.getOutputStream()); objOutStream.writeUTF(method.getName()); objOutStream.writeObject(method.getParameterTypes()); objOutStream.writeObject(args); try (ObjectInputStream objInStream = new ObjectInputStream(client.getInputStream())) { back = objInStream.readObject(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } catch (IOException e) { e.printStackTrace(); } finally { try { if(null != objOutStream) objOutStream.close(); } catch (IOException e) { e.printStackTrace(); } } return back; } }); } /** * 根据配置去注册中心查找服务地址 * @return ip和端口 */ private static String[] getPath(Class consumer){ try { //用负载均衡算法获取具体服务地址 String ipAndPort = getServerAddress(consumer); //为简化,假设ip和端口格式合法,暂不做格式校验 System.out.println("具体服务地址为:" + ipAndPort); return ipAndPort.split(":"); } catch (Exception e) { e.printStackTrace(); return null; } } // 服务调用次数 private static int count = 1; //客户端实现轮询 private static String getServerAddress(Class consumer) { //serversMap; System.out.println("App.serversMap=" + App.serversMap); List<String> serverList = App.serversMap.get(getFatherServerNode(consumer)); String balancingAlgorithms = LoadConfig.getConfigValue("load_balancing_algorithms"); //轮询算法 if("polling".equals(balancingAlgorithms)){ String serverAddress = serverList.get(count % serverList.size()); count++; return serverAddress; } //其他情况,取首 return serverList.get(0); } @Test public void test(){ System.out.println(App.serversMap.get(getFatherServerNode(GoodService.class))); } private static String getFatherServerNode(Class consumerClazz) { String clazzName = consumerClazz.getName(); String serverName = clazzName.substring(clazzName.lastIndexOf(".")+1); String serverKey = serverName.substring(0,serverName.indexOf("Service")).toLowerCase() + "_server_name"; return LoadConfig.getConfigValue(serverKey).replace("/",""); } }
- 配置文件
#注册中心根路径 root_node_name=/rigister_center #注册中心地址 server_rigister_center=127.0.0.1:2181 #user服务父节点路径 user_server_name=/user_server_address #user服务主机地址1 user_server_address_1=127.0.0.1:6060 #user服务主机地址2 user_server_address_2=127.0.0.1:6061 #user服务主机地址3 user_server_address_3=127.0.0.1:6062 #order服务父节点路径(相对根节点) order_server_name=/order_server_address #order服务主机地址1 order_server_address_1=127.0.0.1:7070 #order服务主机地址2 order_server_address_2=127.0.0.1:7071 #good服务父节点路径(相对根节点) good_server_name=/good_server_address #good服务主机地址1 good_server_address_1=127.0.0.1:9090 #good服务主机地址2 good_server_address_2=127.0.0.1:9091 #负载均衡算法类型,本例只实现了一中 load_balancing_algorithms=polling
- zokeeper节点结构
- 所有代码截图,没有模块化,时间有限请谅解
相关文章推荐
- zookeeper与grpc集成实现服务注册与发现
- 三、go-kit 与 grpc 结合实现注册发现与负载均衡
- 用ZooKeeper做为注册中心搭建基于Spring Cloud实现服务注册与发现
- 使用Spring Cloud Zookeeper实现服务的注册和发现
- SOA研究-用zookeeper实现服务的注册和发现
- 【Zookeeper】JAVA通过ZK实现服务注册和服务发现
- spring cloud搭建微服务second-fiberhome(二):结合consul实现服务注册与服务发现
- 服务注册发现Eureka之三:Spring Cloud Ribbon实现客户端负载均衡(客户端负载均衡Ribbon之三:使用Ribbon实现客户端的均衡负载)
- Apache Thrift 初学小讲(八)【zookeeper实现服务注册与发现】
- RPC框架原理及从零实现系列文章(四):支持zookeeper注册中心与负载均衡
- Eureka+ribbon 实现服务注册与发现和负载均衡
- 如何写一个RPC框架(三):服务注册与服务发现
- gRpc服务注册到zookeeper实现
- Dubbo+Zookeeper实现分布式服务和负载均衡
- 简单RPC框架-基于Consul的服务注册与发现
- 微服务~Eureka实现的服务注册与发现及服务之间的调用
- 使用zookeeper实现服务路由和负载均衡
- 微服务:实现服务发现与服务注册
- SpringCloud之服务注册发现(Spring Cloud Zookeeper) |第十五章 -yellowcong
- 【微信群分享预告】Kubernetes结合LVS实现高可用负载均衡与集群外服务访问