一、服务远程简单调用

服务远程调用,可以利用http+传统的servlet服务实现。(关于通信服务,也可使用其他,例如:netty等框架)
- 服务消费者通过httpClient,使用ip+port。调用远程服务。
服务提供者,接受入参,(通过接口信息获取实现类信息)通过反射方式,执行业务处理逻辑,序列化处理结果返回。
缺陷
服务消费者,在调用远程服务时,每次都需要进行参数组装(Invocattion参数)、HttpClient数据发送等远程调用逻辑实现。重复的调用逻辑严重影响正常业务逻辑。
消费端实现
public class OriginalConsumer {public static void main(String[] args) throws IOException {//组装Invocation参数RpcInvocation invocation = new RpcInvocation();invocation.setServiceName(DemoServiceImpl.class.getName());invocation.setMethodName("sayHello");invocation.setParameterTypes(new Class[]{String.class});invocation.setArguments(new Object[]{"masterlu"});//发送数据Socket socket = new Socket("127.0.0.1", 8080);ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());oos.writeObject(invocation);//接收数据InputStream inputStream = socket.getInputStream();byte[] bytes = new byte[1024];int read = inputStream.read(bytes);System.out.println(new String(bytes,0,read));}}
服务端实现
```java /**
- 原始服务提供 */ public class OriginalService {
public static void main(String[] args) throws IOException {// 1. 注册服务// 2. 本地注册// 3. 启动tomcat// 注册服务ServerSocket serverSocket = new ServerSocket(8080);while (true) {Socket accept = serverSocket.accept();new Thread(() -> {try {InputStream inputStream = accept.getInputStream();// 获取接口调用信息ObjectInputStream ois = new ObjectInputStream(accept.getInputStream());Invocation invocation = (Invocation) ois.readObject();Class implClass = Class.forName(invocation.getServiceName());//接口//反射调用方法Class[] parameterTypes = new Class[invocation.getArguments().length];for (int i = 0; i < invocation.getArguments().length; i++) {parameterTypes[i] = invocation.getArguments()[i].getClass();}Method method = implClass.getMethod(invocation.getMethodName(), new Class[]{String.class});String result = (String) method.invoke(implClass.newInstance(), invocation.getArguments());System.out.println("socket:" + result);IOUtils.write(result, accept.getOutputStream());} catch (Exception e) {System.out.println(e);}}).start();}}
}
<a name="kMsqd"></a># 二、动态代理优化服务远程调用<a name="Hs5uo"></a>## 缺陷服务消费者,在代码中写死服务提供者IP。提供者下线、扩容,对服务消费者,影响很大。<a name="Pwk1A"></a>## 优化消费端实现```javapublic static void main(String[] args) throws IOException {//将远程调用逻辑进行封装,减少对业务逻辑的影响DemoService demoService = getProxy(DemoServiceImpl.class);String result = demoService.sayHello("masterlu");System.out.println(result);}public static <T> T getProxy(final Class interfaceClass) {return (T)Proxy.newProxyInstance(interfaceClass.getClassLoader(),interfaceClass.getInterfaces(),(proxy, method, args) -> {//组装Invocation参数RpcInvocation invocation = new RpcInvocation();invocation.setServiceName(interfaceClass.getName());invocation.setMethodName(method.getName());invocation.setParameterTypes(method.getParameterTypes());invocation.setArguments(args);//发送数据Socket socket = new Socket("127.0.0.1", 8080);ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());oos.writeObject(invocation);//接收数据InputStream inputStream = socket.getInputStream();byte[] bytes = new byte[1024];int read = inputStream.read(bytes);return new String(bytes,0,read);});}}
三、引入注册中心优化服务远程调用

引入注册中心,服务提供者,将信息存储在注册中;消费者实时感知可用服务。
注册中心数据缓存
服务消费者,获取注册中心数据后,缓存在本地。注册中心临时短时间故障,不影响服务使用。
失败重试
服务消费获取远程服务列表后,可实现服务的调用策略(随机、轮询、最少活跃、一致性哈希【根据参数计算hash,决定调用服务,参数一致会调用同一台】)
注册中心作用
监控服务提供者
可以利用zk的临时节点,或利用redis的定时节点(定时延期),实时感知服务提供者的服务可用性,监控服务提供者的服务。
发现服务消费者
利用zk的wacth机制(注册到提供的创建的临时节点上)、redis的发布订阅模式,及时感知服务提供者增、减的情况
四、增加监控中心

