【技术应用】java基于UNIX域套接字(unix domain socket)连接mysql数据库
前言
Unix domain socket
又叫 IPC(inter-process communication 进程间通信)socket
,用于实现同一主机上的进程间通信。
socket 原本是为网络通讯设计的,但后来在 socket 的框架上发展出一种 IPC 机制,就是 UNIX domain socket。虽然网络 socket 也可用于同一台主机的进程间通讯(通过 loopback 地址 127.0.0.1),但是 UNIX domain socket 用于 IPC 更有效率:不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等
,只是将应用层数据从一个进程拷贝到另一个进程。这是因为,IPC 机制本质上是可靠的通讯,而网络协议是为不可靠的通讯设计的。
Unix 套接字:Unix 套接字、 UNIX 域套接字、 Unix 域协议族AF_UNIX、POSIX 本地进程间通信套接字、POSIX 本地 IPC 套接字、、、、、、——所有这些术语或多或少指的是同一个概念——主机内部协议和寻址该方案或多或少类似于 Internet 上计算机之间的套接字通信。通常,但并非总是如此,Unix 套接字由文件系统上的路径名引用。PF_UNIXPF_LOCALAF_FILEPF_FILE
Unix 套接字可用于多种平台(包括 macOS、Windows 和 Linux),它们的工作方式都略有不同。
Unix域套接字
有兴趣的同学可以百度查找相关资料,这里不再赘述;
由上可知,unix套接字的通讯效率
是高于socket通讯的,在同一台服务器
上使用unix domian socket进行进程间的通讯,也能提高我们的通讯效率,例如同一台服务java server与java server
、java server与mysql
、java server与postgresql
、java server与docker
等通讯,可以使用unix domain socket进行数据交互,可以提高执行效率,同时也也避免了服务对外暴露端口,提高的安全性
;
这篇文章主要实现java通过unix domain socket
技术对mysql数据库的应用,主要涉及步骤讲解、代码示例;后续也会提供java基于unix domain socket实现Socket
、rmi
、postgresql
应用,尤其java通过unix domain socket技术调用postgresql数据库,我们工作中涉及到的应用最多,后续会着重讲解;
注:为了方便大家使用,本文介绍两种
unix domain socket连接mysql
数据库的方式:java + jdbc
和 spring boot + mybatis
mysql.sock简介:
“mysql.sock”是mysql的套接字文件,是mysql的主机和客户机在同一host
上的时候,使用unix socket做为通讯协议的载体。在UNIX系列系统下本地连接MySQL可以采用TCP连接
和UNIX域套接字
两种方式;其中UNIX域套接字方式需要一个套接字文件
,可用“show variables like ‘socket’\G;”命令来查看本地socket文件位置。
MySQL
中我们常用的有两种连接数据库
的方式,分别是:
- TCP/IP
mysql -uyouruser -pyourpassword -P3306 -h127.0.0.1
mysql -uyouruser -pyourpassword -P3306 -h192.168.199.198
- Socket
mysql -uyouruser -pyourpassword --socket=/tmp/mysql.sock
mysql -uyouruser -pyourpassword -hlocalhost
mysql -uyouruser -pyourpassword
以上三种方式是等价的,默认不填时,默认--host=localhost
,--socket=/tmp/mysql.sock
登录示例:
mysql使用 Unix 域套接字连接:
Connector/J
本身不支持使用 Unix 域套接字连接到 MySQL 服务器。但是,可以使用通过可插入套接字工厂提供功能的第 3 方库。这样的自定义工厂应该实现 Connector/J 的 com.mysql.cj.protocol.SocketFactory
接口或遗留 com.mysql.jdbc.SocketFactory
接口。当您为 Unix 套接字使用此类自定义套接字工厂时,请遵循以下要求:
1)MySQL 服务器必须配置系统变量 --socket
(对于使用 JDBC API 的本机协议连接)或 --mysqlx-socket
(对于使用 X DevAPI 的 X 协议连接),它必须包含 Unix 套接字文件的文件路径。
2)自定义工厂的完全限定类名应该通过连接属性传递给 Connector/J socketFactory
。例如,对于 junixsocket
库,设置:
socketFactory=org.newsclub.net.mysql.AFUNIXDatabaseSocketFactory
您可能还需要将其他参数作为连接属性传递给自定义工厂
。例如,对于 junixsocket
库,提供具有以下属性的套接字文件的文件路径junixsocket.file
:
junixsocket.file=path_to_socket_file
3)Fore release 8.0.21 及更早版本:使用 X 协议
时,设置连接属性 xdevapi.useAsyncProtocol=false(
这是 Connector/J 8.0.12 及更高版本的默认设置)。异步套接字通道不支持 Unix 套接字。当 时xdevapi.useAsyncProtocol=true
,该 socketFactory
属性将被忽略(连接属性 xdevapi.useAsyncProtocol
自 8.0.22 版以来已被弃用)。
注:可以参考MySQL Connector/J 8.0 开发人员指南
代码实现:
创建数据库表student
:
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,`name` varchar(10) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,`sex` char(6) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,`pwd` varchar(20) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,`email` varchar(20) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = DYNAMIC;SET FOREIGN_KEY_CHECKS = 1;
连接socket
,创建AFUNIXDatabaseSocketFactoryCJ
类:
package com.config;import com.mysql.cj.conf.PropertySet;
import com.mysql.cj.conf.RuntimeProperty;
import com.mysql.cj.protocol.ServerSession;
import com.mysql.cj.protocol.SocketConnection;
import com.mysql.cj.protocol.SocketFactory;
import org.newsclub.net.unix.AFUNIXSocket;
import org.newsclub.net.unix.AFUNIXSocketAddress;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.net.Socket;public class AFUNIXDatabaseSocketFactoryCJ implements SocketFactory {private AFUNIXSocket rawSocket;private Socket sslSocket;@Overridepublic <T extends Closeable> T connect(String s, int i, PropertySet propertySet, int i1) throws IOException {RuntimeProperty<String> prop = propertySet.getStringProperty("junixsocket.file");String sock;if (prop != null && !prop.isExplicitlySet()) {sock = prop.getStringValue();} else {sock = "/var/lib/mysql/mysql.sock";}final File socketFile = new File(sock);this.rawSocket = AFUNIXSocket.connectTo(AFUNIXSocketAddress.of(socketFile));this.sslSocket = rawSocket;return (T) rawSocket;}@Overridepublic <T extends Closeable> T performTlsHandshake(SocketConnection socketConnection, ServerSession serverSession) throws IOException {return null;}
}
建立数据库Connection
连接:
package com.sk.jdbc;import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;public class MysqlDemo {//建立connection连接public static Connection getConn() throws Exception{Driver driver = new com.mysql.cj.jdbc.Driver();String url = "jdbc:mysql://localhost/test";//将用户名和密码封装在Properties中Properties info = new Properties();info.setProperty("socketFactory","com.config.AFUNIXDatabaseSocketFactoryCJ");info.setProperty("user","root");info.setProperty("password","%Dsh0406");info.setProperty("junixsocket.file","/var/lib/mysql/mysql.sock");info.setProperty("sslMode","DISABLED");Connection conn = driver.connect(url,info);System.out.println(conn);return conn;}//通过conn操作数据库,主要用于jdbc实现public static List<String> run() throws Exception{Connection conn = getConn();Statement stmt = conn.createStatement();String sql = "select * from student";ResultSet rs = stmt.executeQuery(sql);//处理结果集List<String> res = new ArrayList<>();while(rs.next()) {String str = rs.getString("name");res.add(str);}rs.close();System.out.println("结果集关闭成功!");stmt.close();System.out.println("语句通道关闭成功!");conn.close();System.out.println("关闭连接成功!");//遍历输出if(res!=null){for(String out:res) {System.out.println(out);}}return res;}
}
jdbc
实现对数据库调用,结合上一步的run()
package com.controller;import com.bean.Student;
import com.mapper.StudentMapper;
import com.sk.jdbc.MysqlDemo;
import lombok.extern.log4j.Log4j2;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import java.sql.SQLException;
import java.util.List;@Log4j2
@RestController
public class TestAction {@Resourceprivate StudentMapper studentMapper;/*** 验证jdbc调用* @return*/@GetMapping("/test/local")private Object get(){try {return MysqlDemo.run();} catch (Exception e) {e.printStackTrace();}return null;}
}
jdbc
调用执行结果:
日志信息
接口调用:
集合springboot+mybatis
使用
创建mapper
package com.mapper;import com.bean.Student;
import org.apache.ibatis.annotations.*;
import org.springframework.stereotype.Repository;import java.util.List;
import java.util.Map;@Mapper
@Repository
public interface StudentMapper {@Select("select * from student")List<Student> selectAll();@Select("select * from student where id = #{id}")Student selectById(@Param("id") int id);@Select("select * from student where name = #{name}")Map<String, Object> selectByName1(@Param("name") String name);@Select("select * from student where name = #{name}")Student selectByName2(@Param("name") String name);@Select("select * from student where name = #{name} and pwd = #{pwd}")Student selectByNameAndPwd(String name, String pwd);@Delete("delete from student where id = #{id}")boolean deleteById(int id);@Insert("insert into student values (null,#{name},#{sex},#{pwd},#{email})")boolean insertUser(String name, String sex, String pwd, String email);@Update("update student set name = #{name} where id = #{id}")boolean updateById(String name, int id);}
重写DataSource
类MyDataSource.java
package com.config;import com.sk.jdbc.MysqlDemo;import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;public class MyDataSource implements DataSource {@Overridepublic Connection getConnection() {try {return MysqlDemo.getConn();} catch (Exception e) {e.printStackTrace();}return null;}@Overridepublic Connection getConnection(String username, String password) {try {return MysqlDemo.getConn();} catch (Exception e) {e.printStackTrace();}return null;}@Overridepublic <T> T unwrap(Class<T> iface) throws SQLException {return null;}@Overridepublic boolean isWrapperFor(Class<?> iface) throws SQLException {return false;}@Overridepublic PrintWriter getLogWriter() throws SQLException {return null;}@Overridepublic void setLogWriter(PrintWriter out) throws SQLException {}@Overridepublic void setLoginTimeout(int seconds) throws SQLException {}@Overridepublic int getLoginTimeout() throws SQLException {return 0;}@Overridepublic Logger getParentLogger() throws SQLFeatureNotSupportedException {return null;}
}
手动初始化数据库连接DruidConfig.java
package com.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;@Configuration
public class DruidConfig {@Beanpublic DataSource druid(){return new MyDataSource();}}
创建验证接口
package com.controller;import com.bean.Student;
import com.mapper.StudentMapper;
import com.sk.jdbc.MysqlDemo;
import lombok.extern.log4j.Log4j2;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import java.sql.SQLException;
import java.util.List;@Log4j2
@RestController
public class TestAction {@Resourceprivate StudentMapper studentMapper;/*** 验证mybatis* @return*/@GetMapping("/test")private Object get2(){List<Student> studentList = studentMapper.selectAll();log.info(studentList);return studentList;}
}
执行结果:
参考资料:
https://github.com/kohlschutter/junixsocket
https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-unix-socket.html
https://mp.weixin.qq.com/s/h3jOYAD05QfHSRXLnQtPYw
=有下午茶,必开会
【技术应用】java基于UNIX域套接字(unix domain socket)连接mysql数据库相关推荐
- 基于JAVA基于web的老年公寓管理计算机毕业设计源码+系统+mysql数据库+lw文档+部署
基于JAVA基于web的老年公寓管理计算机毕业设计源码+系统+mysql数据库+lw文档+部署 基于JAVA基于web的老年公寓管理计算机毕业设计源码+系统+mysql数据库+lw文档+部署 本源码技 ...
- 阿里云自动java和mysql数据库_阿里云服务器之基于Linux系统部署上线JavaWeb项目和连接MySQL数据库(从购买云服务器到发布JavaWeb项目全套详细流程)...
阿里云服务器之基于Linux系统部署上线JavaWeb项目和连接MySQL数据库(从购买云服务器到发布JavaWeb项目全套详细流程) (仅此纪念人生第一篇学习博客) 前阵子接了一个小小的JavaWe ...
- Java新手入门200例124之用JDBC连接Mysql数据库
文章目录 作者简介 引言 导航 热门专栏推荐 一.创建web项目 二.加入Mysql驱动 三.编写查询代码 四.测试查询代码 五.编写插入代码 六.编写修改代码 七.编写删除代码 小结 导航 热门专栏 ...
- unix 域套接字实现进程间通信
目录 1.认识域套接字 2.unix域套接字相关API及地址结构介绍 (1) 创建unix域套接字 (2) 填充地址结构 sockaddr_un 3.unix域套接字实现进程间通信( ...
- 域服务器广播消息,广播,组播和UNIX域套接字
1.广播 1.特点 一对多 仅能使用UDP 2.概念 发送方只有一个接收方则称单播 如果同时发给局域网中的所有主机,成为广播 只有用户数据包(使用UDP协议)套接字才能广播 广播地址 1.以192.1 ...
- linux 套接字 文件 路径,linux – 识别unix域套接字连接的另一端
我正在试图找出一个持有unix域套接字另一端的进程.在某些strace输出中,我已经确定了一个给定的文件描述符,这个文件描述符涉及到我目前正在调试的问题,我想知道哪一个进程在另一端.由于存在与该套接字 ...
- UNIX域套接字编程和socketpair 函数
一.UNIX Domain Socket IPC socket API原本是为网络通讯设计的,但后来在socket的框架上发展出一种IPC机制,就是UNIX Domain Socket.虽然网络soc ...
- Beats:将 Unix 域套接字中的数据索引到 Elastic Stack
这篇博文将解释什么是 UNIX 域套接字,以及如何将发送到 UNIX 域套接字的索引编入 Elastic Stack - 以及为此存在哪些不同的用例. UNIX 域套接字 - 简短的历史 如果你想让进 ...
- 【socket】 unix域套接字(socketpair )通信|socketpair和pipe的区别|进程间通信-Unix domain socket
目录 unix域套接字(socketpair )通信|socketpair和pipe的区别 socketpair机制 描述 原理 socketpair和pipe的区别 进程间通信-Unix domai ...
最新文章
- 在windows中安装python
- hdu 2516 FIB博弈模型
- DataX在数据迁移中的应用
- u3d 总是背向相机_纪念光学科学家“肖特”的相机
- php用mssql还是用pdo,php使用pdo连接mssql server数据库实例
- TSQLDBServerHttpApi使用工作线程池
- 简单好用的Adapter---ArrayAdapter
- Swagger自动接口文档生成框架————springboot整合swagger总结
- TokenInsight:BTC网络活跃度保持历史高位,人气居高不下
- win10配置清华源——快速安装anaconda、TensorFlow和pytorch
- PIE SDK 坐标系创建、定义、对比
- Web 网页开发的一点心得
- 微信8.0.0中的[烟花]\[炸弹]原来还可以这样玩(JAVA脚本)程序员的快乐,很简单,快来看!!!
- Win10虚拟机性能优化
- CMAQ-5.2安装及测试数据运行
- 8.3 初步理解 Texture Alpha
- 【元宵节】中国人民大学与加拿大女王大学金融硕士项目与你的那份“缘”
- mysql中图片的属性名是啥_数据库属性名
- 电脑无法连接wifi得解决方法
- uniapp实现微信小程序websocket+背景音频语音播报