使用同一个线程调用本容器的其他服务,不经过网络传输

dapeng容器目前的模式,每个请求都需要以调用远程服务的方式请求服务,即使它请求的服务运行在本地同一个容器内。打个比方,客户端调用A服务,A服务内需要调用B服务,这时候,对于A服务来说,它是B服务的客户端,它请求B服务的方式与标准的前端没有任何区别,都需要经过各种过滤链,走网络传输,然后调用到本地(或其他节点)的服务。 这样做的优点是,对于所有请求,模式是统一的,每一个请求都是完整的服务调用。缺点在于: 如果一个节点有很多服务,一个请求链的互相调用过程中,即使每次都是调用本节点,也依然有大量的网络传输过程开销; 对一个完整的服务调用来说,每个请求处理需要占用一个新的线程,如果一个请求中调用了十次本节点的服务,那么就至少占用了本节点10个线程,并且大多数都处于等待状态; 在分布式服务的调用过程中,如果后面某个服务调用异常,前面成功的服务调用无法自动回滚,但如果都是在同一个线程同一个事务,后面的异常可以使前面的数据库操作回滚。 因此,提出了这么一种需求:“如果本节点存在即将调用的服务,那么,不经过网络传输,直接用当前线程调用本地服务”,以此来解决上述的3个问题。

发布于 technology

ServerSocket 和 ThreadPoolExecutor学习笔记

ServerSocket部分123456789101112final ServerSocket server = new ServerSocket(9090);server.setReceiveBufferSize(1024 * 4);// 设置缓冲区大小4kdo { try { final Socket client = server.accept(); soaTransPool.execute(new SoaTransPool.SoaCodecTask(client)); } catch (IOException e) { //TODO e.printStackTrace(); }} while (true); 其中,soaTransPool是一个自定义的类,类中定义了ThreadPoolExecutor,以及实现了Runnable的静态类SoaCodecTask. ServerSocket监听9090端口,每当有请求到达,就创建一个socket,使用这个socket构造一个Runnable对象,即SoaCodecTask,再使用ThreadPoolExecutor来执行这个Runnable对象。也就是说,对每个请求创建一个任务,由线程池来执行这个任务。 事实上,ServerSocket的功能就是向系统注册一个服务,然后等待客户端请求,或者从请求队列中取出Socket,至于数据的传递则由Socket完成。 上面的例子中,使用的是线程池的处理方式,接收到的请求由线程池来处理;如果是简单的单线程ServerSocket,则可以这么写: 1234567891011121314151617ServerSocket server = new ServerSocket(9090);Socket client = null;do { try { client = server.accept(); System.out.println("新增链接: " + client.getInetAddress() + ": " + client.getPort()); // ...接收、处理、发送数据 } catch (IOException e) { //TODO e.printStackTrace(); }finally{ if(client != null){ client.close(); } }} while (true); 如果是想用多线程,就如第一个例子中那样,将socket作为参数创建一个Runnable对象,并新建一个线程并start以执行run方法。

发布于 technology