Alex Guo
文章36
标签33
分类10
java基础之NIO

java基础之NIO

BIO NIO AIO 的概念

Mysql主从配置,实现读写分离

Mysql主从配置,实现读写分离

大型网站为了软解大量的并发访问,除了在网站实现分布式负载均衡,远远不够。到了数据业务层、数据访问层,如果还是传统的数据结构,或者只是单单靠一台服务器扛,如此多的数据库连接操作,数据库必然会崩溃,数据丢失的话,后果更是 不堪设想。这时候,我们会考虑如何减少数据库的联接,一方面采用优秀的代码框架,进行代码的优化,采用优秀的数据缓存技术如:memcached,如果资金丰厚的话,必然会想到假设服务器群,来分担主数据库的压力。

Ok切入今天微博主题,利用MySQL主从配置,实现读写分离,减轻数据库压力。这种方式,在如今很多网站里都有使用,也不是什么新鲜事情,今天总结一下,方便大家学习参考一下。

概述:搭设一台Master服务器(win8.1系统,Ip:192.168.0.104),搭设两台Slave服务器(虚拟机——一台Ubuntu,一台 Windows Server 2003)

原理:主服务器(Master)负责网站NonQuery操作,从服务器负责Query操作,用户可以根据网站功能模特性块固定访问Slave服务器,或者自己写个池或队列,自由为请求分配从服务器连接。主从服务器利用MySQL的二进制日志文件,实现数据同步。二进制日志由主服务器产生,从服务器响应获取同步数据库。

具体实现:

1、在主从服务器上都装上MySQL数据库

windows系统鄙人安装的是mysql_5.5.25.msi版本,
Ubuntu安装的是mysql-5.6.22-linux-glibc2.5-i686.tar

windows安装mysql就不谈了,一般地球人都应该会。鄙人稍微说一下Ubuntu的MySQL安装,我建议不要在线下载安装,还是离线安装的好。大家可以参考 http://www.linuxidc.com/Linux/2013-01/78716.htm 这位不知道大哥还是姐妹,写的挺好按照这个就能装上。在安装的时候可能会出现几种现象,大家可以参考解决一下:

(1)如果您不是使用root用户登录,建议 su - root 切换到Root用户安装,那就不用老是 sudo 了。

(2)存放解压的mysql 文件夹,文件夹名字最好改成mysql

(3)在./support-files/mysql.server start 启动MySQL的时候,可能会出现一个警告,中文意思是启动服务运行读文件时,忽略了my.cnf文件,那是因为my.cnf的文件权限有问题,mysql会认为该文件有危险不会执行。但是mysql还会启动成功,但如果下面配置从服务器参数修改my.cnf文件的时候,你会发现文件改过了,但是重启服务时,修改过后的配置没有执行,而且您 list一下mysql的文件夹下会发现很多.my.cnf.swp等中间文件。这都是因为MySQL启动时没有读取my.cnf的原因。这时只要将my.cnf的文件权限改成my_new.cnf的权限一样就Ok,命令:chmod 644 my.cnf就Ok

(4)Ubuntu中修改文档内容没有Vim,最好把Vim 装上,apt-get install vim,不然估计会抓狂。

这时候我相信MySQL应该安装上去了。

2、配置Master主服务器

(1)在Master MySQL上创建一个用户‘repl’,并允许其他Slave服务器可以通过远程访问Master,通过该用户读取二进制日志,实现数据同步。

1 mysql>create user repl; //创建新用户
2 //repl用户必须具有REPLICATION SLAVE权限,除此之外没有必要添加不必要的权限,密码为mysql。说明一下192.168.0.%,这个配置是指明repl用户所在服务器,这里%是通配符,表示192.168.0.0-192.168.0.255的Server都可以以repl用户登陆主服务器。当然你也可以指定固定Ip。
3 mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.0.%' IDENTIFIED BY 'mysql';

(2)找到MySQL安装文件夹修改my.Ini文件。mysql中有好几种日志方式,这不是今天的重点。我们只要启动二进制日志log-bin就ok。

在[mysqld]下面增加下面几行代码

 server-id=1   //给数据库服务的唯一标识,一般为大家设置服务器Ip的末尾号
 log-bin=master-bin
 log-bin-index=master-bin.index

(3)查看日志

mysql> SHOW MASTER STATUS;
+-------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| master-bin.000001 | 1285 | | |
+-------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

重启MySQL服务

3、 配置Slave从服务器(windows)

(1)找到MySQL安装文件夹修改my.ini文件,在[mysqld]下面增加下面几行代码
my.cnf 配置

[mysqld]
server-id=2
relay-log-index=slave-relay-bin.index
relay-log=slave-relay-bin 

重启MySQL服务

(2)连接Master

change master to master_host='192.168.0.104', //Master 服务器Ip
master_port=3306,
master_user='repl',
master_password='mysql', 
master_log_file='master-bin.000001',//Master服务器产生的日志
master_log_pos=0;

(3)启动Slave

start slave;

4、 Slave从服务器(Ubuntu)

(1)找到MySQL安装文件夹修改my.cnf文件,vim my.cnf

图片

(2) 重启

./support-files/myql.server restart 重启MySQL服务  ,  
./bin/mysql 进入MySQL命令窗口 

(3)连接Master

change master to master_host='192.168.0.104', //Master 服务器Ip
master_port=3306,
master_user='repl',
master_password='mysql', 
master_log_file='master-bin.000001',//Master服务器产生的日志
master_log_pos=0;

(4)启动Slave

start slave;

OK所有配置都完成了,这时候大家可以在Master Mysql 中进行测试了,因为我们监视的时Master mysql 所有操作日志,所以,你的任何改变主服务器数据库的操作,都会同步到从服务器上。创建个数据库,表试试吧。。。

pcloud- hosts- 终端(开发)配置

pcloud- hosts- 终端(开发)配置

开发时,终端映射配置(都访问nginx)

zuul网关 转发

  • 127.0.0.1 dev-api.pcloud.net 

网页前端

  • 127.0.0.1 dev-login.pcloud.net 登录前端
  • 127.0.0.1 dev-admin.pcloud.net 后台管理前端
  • 127.0.0.1 dev-mall.pcloud.net
pcloud nginx映射配置

pcloud nginx映射配置

dev-admin

server {
    listen       80;
    server_name  dev-admin.pcloud.net;
    location / {
        proxy_pass http://localhost:7020;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }
}

###dev-login (网页前端)

server {
    listen       80;
    server_name  dev-login.pcloud.net;
    location / {
        # 内网
        proxy_pass http://localhost:7010;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }
}

dev-mall (网页前端)

server {
    listen       80;
    server_name  dev-mall.pcloud.net;
    location / {
        proxy_pass http://localhost:7030;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }
}

dev-api (api zuul网关)

server {
    listen       80;
    server_name  dev-api.pcloud.net;
    location ~ {
        proxy_pass   http://localhost:7979;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }
}
pcloud 内网服务之间hosts配置

pcloud 内网服务之间hosts配置

这里是为了方便,给每一个内网服务取了一个名字,任何其他调用该服务的应用都可以通过这个名字来访问

内部服务映射

基础工具

  • 127.0.0.1 pcloud-db-mysql 
  • 127.0.0.1 pcloud-db-redis
  • 127.0.0.1 pcloud-mq-rabbit
  • 127.0.0.1 pcloud-mq-rocket
  • 127.0.0.1 pcloud-provider-zk

spring cloud 服务

  • 127.0.0.1 pcloud-discovery
  • 127.0.0.1 pcloud-eureka
  • 127.0.0.1 pcloud-gateway
  • 127.0.0.1 pcloud-monitor
  • 127.0.0.1 pcloud-zipkin

内部服务

  • 127.0.0.1 pcloud-provider-uac
  • 127.0.0.1 pcloud-provider-mdc
  • 127.0.0.1 pcloud-provider-omc
  • 127.0.0.1 pcloud-provider-opc
  • 127.0.0.1 pcloud-provider-ptc

终端api接口服务

  • 127.0.0.1 pcloud-service-auth 授权服务
  • 127.0.0.1 pcloud-service-app  手机app
  • 127.0.0.1 pcloud-service-web 网页
  • 127.0.0.1 pcloud-service-wechat 微信
docker 启动常用容器命令

docker 启动常用容器命令

redis

docker run -p 6379:6379 -v $PWD/data:/data  -d redis:3.2 redis-server --appendonly yes

命令说明:

-p 6379:6379 : 将容器的6379端口映射到主机的6379端口

-v $PWD/data:/data : 将主机中当前目录下的data挂载到容器的/data

redis-server –appendonly yes : 在容器执行redis-server启动命令,并打开redis持久化配置

rabbitmq

docker run -d --name rabbitmq --publish 5671:5671  --publish 5672:5672 --publish 4369:4369 --publish 25672:25672 --publish 15671:15671 --publish 15672:15672 rabbitmq

常见启动错误

Cannot start container web: iptables failed: iptables -t nat -A DOCKER -p tcp -d 0/0 --dport 32797

解决办法:重建docker0网络恢复

pkill docker 
iptables -t nat -F 
ifconfig docker0 down 
brctl delbr docker0 
docker -d 
service docker restart
docker常用命令

docker常用命令

关键字:

  • 镜像 images
  • 镜像名 image_name
  • 镜像id image_id
  • 容器 container
  • 容器名 con_name
  • 容器id con_id

从公网拉取一个镜像

docker pull images_name

查看已有的docker镜像

[root@docker ~]# docker images

查看帮助

docker command --help

查看镜像列表

docker search nginx

启动一个容器

基于hello-world镜像启动一个容器,如果本地没有镜像会从公网拉取过来,这次做为测试用

docker run hello-world

导出镜像

docker save -o image_name.tar image_name

删除镜像

docker rm image_name

启动一个容器

docker run --name=con_name images
# --name  #设置容器名

基于创建好的容器自定义docker镜像

docker commit -m "con_name" con_id image_name

创建一个容器的同时进入这个容器

docker run -it --name=con_name images
# -it     #在启动之后进入这个容器

创建一个容器,放入后台运行,把物理机80端口映射到容器的80端口

docker run -d -p 81:80 image_name

-p 参数说明

-p hostPort:containerPort
-p ip:hostPort:containerPort
-p ip::containerPort
-p hostPort:containerPort:udp

看容器的端口映射情况

docker port con_id

查看正在运行的容器

docker ps 

查看所有的容器

docker ps -a

动态查看容器日志

docker logs -f con_name

进入容器

docker attach con_name

退出容器

方法一

exit

方法二

ctrl+p && ctrl+q (一起按,注意顺序,退出后容器依然保持启动状态)

删除容器

docker rm  con_name

强制删除需要加-f,不加-f不能删除正在运行中的容器,非常危险,最好不用

查看docker网络

[root@docker ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
3f91f2097286        bridge              bridge              local
d7675dbd247c        docker_gwbridge     bridge              local
5b36c7e947fd        host                host                local
ims6qkpikafu        ingress             overlay             swarm
85ba10e7ef79        none                null                local

创建一个docker网络my-docker

docker network create -d bridge \
--subnet=192.168.0.0/24 \
--gateway=192.168.0.100 \
--ip-range=192.168.0.0/24 \
my-docker

利用刚才创建的网络启动一个容器

docker run --network=my-docker --ip=192.168.0.5 -itd --name=con_name -h lb01 image_name

–network #指定容器网络
–ip #设定容器ip地址
-h #给容器设置主机名

查看容器pid

方法一:

docker top con_name

方法二:

docker inspect --format "{{.State.Pid}}" con_name

运行dockerfile并给dockerfile创建的镜像建立名字

docker build -t mysql:3.6.34 pwd

mariadb容器启动前需先设置密码方法

docker run -d -P -e MYSQL_ROOT_PASSWORD=password img_id

docker修改镜像名

docker tag imageid name:tag

进入docker容器脚本

[root@docker ~]# cat nsenter.sh 
PID=`docker inspect --format "{{.State.Pid}}" $1`
nsenter -t $PID -u --mount -i -n -p

创建一个网络

docker network create --driver bridge --subnet 172.22.16.0/24 --gateway 172.22.16.1 my_net2

将容器添加到my_net2网络 connect

docker network connect my_net2 oldboy1

docker日志模块 使用filebeat收集日志

{
  "registry-mirrors": ["https://56px195b.mirror.aliyuncs.com"],
  "cluster-store":"consul://192.168.56.13:8500",
  "cluster-advertise": "192.168.56.11:2375",
  "log-driver": "fluentd",
  "log-opts": {
        "fluentd-address":"192.168.56.13:24224",
        "tag":"linux-node1.example.com"
        }
}
Spring Cloud Stream入门

Spring Cloud Stream入门

  • 引入依赖

          <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
          </dependency>
    
  • 消息接收者

    @EnableBinding(Sink.class)
    public class SinkReceiver {
      private static Logger logger = LoggerFactory.getLogger(SinkReceiver.class);
    
      @StreamListener(Sink.INPUT)
      public void receive(Object payload) {
          logger.info("Received: " + payload);
      }
    }
    

@EnableBinding

该注解用来指定一个或多个定义了@Input或@Output注解的接口,
以此实现对消息通道(Channel)的绑定。
在上面的例子中,我们通过@EnableBinding(Sink.class)绑定了Sink接口,
该接口是Spring Cloud Stream中默认实现的对输入消息通道绑定的定义,

它的源码如下:

public interface Sink {

    String INPUT = "input";

    @Input(Sink.INPUT)
    SubscribableChannel input();
}

它通过@Input注解绑定了一个名为input的通道。

除了Sink之外,Spring Cloud Stream还默认实现了绑定output通道的Source接口,
还有结合了Sink和Source的Processor接口,

实际使用时我们也可以自己通过@Input和@Output注解来定义绑定消息通道的接口。

当我们需要为@EnableBinding指定多个接口来绑定消息通道的时候,
可以这样定义:@EnableBinding(value = {Sink.class, Source.class})。

@StreamListener

该注解主要定义在方法上,
作用是将被修饰的方法注册为消息中间件上数据流的事件监听器,
注解中的属性值对应了监听的消息通道名。

在上面的例子中,我们通过@StreamListener(Sink.INPUT)注解将receive方法注册为对input消息通道的监听处理器,
所以当我们在RabbitMQ的控制页面中发布消息的时候,receive方法会做出对应的响应动作。

消息生产者

@Test
public void sinkSenderTester() {
    sinkSender.output().send(MessageBuilder.withPayload("produce a message :http://blog.didispace.com").build());
}

public interface SinkSender {

    String OUTPUT = "input";

    @Output(SinkSender.OUTPUT)
    MessageChannel output();

}

@Output(SinkSender.OUTPUT)定义了一个输出通过,
而该输出通道的名称为input,与前文中的Sink中定义的消费通道同名,
所以这里的单元测试与前文的消费者程序组成了一对生产者与消费者。

Spring rabbitMQ入门

Spring rabbitMQ入门

  • 引入rabbitMQ
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-amqp</artifactId>
          </dependency>
    
  • 配置属性
    ```java
    spring.application.name=rabbitmq-hello

spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest


- 配置
```java
@Configuration
public class RabbitConfig {
    @Bean
    public Queue helloQueue() {
        return new Queue("hello");
    }
}
  • 消息发送者

    @Component
    public class Sender {
    
      @Autowired
      private AmqpTemplate rabbitTemplate;
    
      public void send() {
          String context = "hello " + new Date();
          System.out.println("Sender : " + context);
          this.rabbitTemplate.convertAndSend("hello", context);
      }
    }
    
  • 消息接收者

    @Component
    @RabbitListener(queues = "hello")
    public class Receiver {
    
      @RabbitHandler
      public void process(String hello) {
          System.out.println("Receiver : " + hello);
      }
    }
    
HexoClient使用测试

HexoClient使用测试

这是用hexo client写的文章