什么是微服务
- 微服务架构是一个分布式系统,依照业务进行划分成为不同的服务单元,解决单体零碎性能等有余。
- 微服务是一种架构格调,一个大型软件应用由多个服务单元组成。零碎中的服务单元能够独自部署,各个服务单元之间是松耦合的。
微服务概念起源:Microservices
微服务之间是如何独立通信的
同步
REST HTTP 协定
REST 申请在微服务中是最为罕用的一种通信形式,它依赖于 HTTP\HTTPS 协定。RESTFUL 的特点是:
- 每一个 URI 代表 1 种资源
- 客户端应用 GET、POST、PUT、DELETE 4 个示意操作形式的动词对服务端资源进行操作:GET 用来获取资源,POST 用来新建资源(也能够用于更新资源),PUT 用来更新资源,DELETE 用来删除资源
- 通过操作资源的表现形式来操作资源
- 资源的表现形式是 XML 或者 HTML
- 客户端与服务端之间的交互在申请之间是无状态的, 从客户端到服务端的每个申请都必须蕴含了解申请所必须的信息
举个例子,有一个服务方提供了如下接口:
@RestController
@RequestMapping("/communication")
public class RestControllerDemo {@GetMapping("/hello")
public String s() {return "hello";}
}
另外一个服务须要去调用该接口,调用方只须要依据 API 文档发送申请即可获取返回后果。
@RestController
@RequestMapping("/demo")
public class RestDemo{
@Autowired
RestTemplate restTemplate;
@GetMapping("/hello2")
public String s2() {String forObject = restTemplate.getForObject("http://localhost:9013/communication/hello", String.class);
return forObject;
}
}
通过这样的形式能够实现服务之间的通信。
RPC TCP 协定
RPC(Remote Procedure Call) 近程过程调用,简略的了解是一个节点申请另一个节点提供的服务。它的工作流程是这样的:
- 执行客户端调用语句,传送参数
- 调用本地零碎发送网络音讯
- 音讯传送到近程主机
- 服务器失去音讯并获得参数
- 依据调用申请以及参数执行近程过程(服务)
- 执行过程结束,将后果返回服务器句柄
- 服务器句柄返回后果,调用近程主机的零碎网络服务发送后果
- 音讯传回本地主机
- 客户端句柄由本地主机的网络服务接管音讯
- 客户端接管到调用语句返回的后果数据
举个例子。
首先须要一个服务端:
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* RPC 服务端用来注册近程办法的接口和实现类
*/
public class RPCServer {private static ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
private static final ConcurrentHashMap<String, Class> serviceRegister = new ConcurrentHashMap<>();
/**
* 注册办法
* @param service
* @param impl
*/
public void register(Class service, Class impl) {serviceRegister.put(service.getSimpleName(), impl);
}
/**
* 启动办法
* @param port
*/
public void start(int port) {
ServerSocket socket = null;
try {socket = new ServerSocket();
socket.bind(new InetSocketAddress(port));
System.out.println("服务启动");
System.out.println(serviceRegister);
while (true) {executor.execute(new Task(socket.accept()));
}
} catch (Exception e) {e.printStackTrace();
} finally {if (socket != null) {
try {socket.close();
} catch (IOException e) {e.printStackTrace();
}
}
}
}
private static class Task implements Runnable {
Socket client = null;
public Task(Socket client) {this.client = client;}
@Override
public void run() {
ObjectInputStream input = null;
ObjectOutputStream output = null;
try {input = new ObjectInputStream(client.getInputStream());
// 依照程序读取对方写过来的内容
String serviceName = input.readUTF();
String methodName = input.readUTF();
Class<?>[] parameterTypes = (Class<?>[]) input.readObject();
Object[] arguments = (Object[]) input.readObject();
Class serviceClass = serviceRegister.get(serviceName);
if (serviceClass == null) {throw new ClassNotFoundException(serviceName + "没有找到!");
}
Method method = serviceClass.getMethod(methodName, parameterTypes);
Object result = method.invoke(serviceClass.newInstance(), arguments);
output = new ObjectOutputStream(client.getOutputStream());
output.writeObject(result);
} catch (Exception e) {e.printStackTrace();
} finally {
try {
// 这里就不写 output!=null 才敞开这个逻辑了
output.close();
input.close();
client.close();} catch (IOException e) {e.printStackTrace();
}
}
}
}
}
其次须要一个客户端:
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.InetSocketAddress;
import java.net.Socket;
/**
* RPC 客户端
*/
public class RPCclient<T> {
/**
* 通过动静代理将参数发送过来到 RPCServer ,RPCserver 返回后果这个办法解决成为正确的实体
*/
public static <T> T getRemoteProxyObj(final Class<T> service, final InetSocketAddress addr) {return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[]{service}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Socket socket = null;
ObjectOutputStream out = null;
ObjectInputStream input = null;
try {socket = new Socket();
socket.connect(addr);
// 将实体类, 参数, 发送给近程调用方
out = new ObjectOutputStream(socket.getOutputStream());
out.writeUTF(service.getSimpleName());
out.writeUTF(method.getName());
out.writeObject(method.getParameterTypes());
out.writeObject(args);
input = new ObjectInputStream(socket.getInputStream());
return input.readObject();} catch (Exception e) {e.printStackTrace();
} finally {out.close();
input.close();
socket.close();}
return null;
}
});
}
}
再来一个测试的近程办法。
public interface Tinterface {String send(String msg);
}
public class TinterfaceImpl implements Tinterface {
@Override
public String send(String msg) {return "send message" + msg;}
}
测试代码如下:
import com.huifer.admin.rpc.Tinterface;
import com.huifer.admin.rpc.TinterfaceImpl;
import java.net.InetSocketAddress;
public class RunTest {public static void main(String[] args) {new Thread(new Runnable() {
@Override
public void run() {RPCServer rpcServer = new RPCServer();
rpcServer.register(Tinterface.class, TinterfaceImpl.class);
rpcServer.start(10000);
}
}).start();
Tinterface tinterface = RPCclient.getRemoteProxyObj(Tinterface.class, new InetSocketAddress("localhost", 10000));
System.out.println(tinterface.send("rpc 测试用例"));
}
}
输入 send message rpc 测试用例
。
异步
消息中间件
常见的消息中间件有 Kafka、ActiveMQ、RabbitMQ、RocketMQ,常见的协定有 AMQP、MQTTP、STOMP、XMPP。这里不对音讯队列进行拓展了,具体如何应用还是请移步官网。