.Net 微服务实战之技术选型篇
.Net 微服务实战之技术架构分层篇
.Net 微服务实战之 DevOps 篇
相关源码: https://github.com/SkyChenSky/Sikiro
PS: 最近开始在找工作, 如果在广州地区需要技术管理岗的 (.Net 架构师, 技术经理) 可以随时联系我, 微信: SkyChen_Gong.
分布式? 集群? 负载均衡?
我曾经面试过一家企业, 当时描述完我在老东家完成的微服务架构后, 面试官问了我一个问题:
面试官: 您有做过分布式系统吗?
我: 有, 刚刚我描述的微服务架构就是分布式的......
面试官: 不不不, 我意思是你有没有尝试过把一个站点部署到多台服务器上?
我: 哦...... 你意思是我有没有用过类似 nginx 这些工具做负载均衡是吧? 有, 现在我们就这么做的. 但是我对分布式理解是工作方式, 但是你描述的更多具体称之为集群或者负载均衡.
面试官: 对对, 大家的站在的观点不一样所以理解的不一样(尴尬的笑了笑)
PS: 首先我申明下我没有对该面试官有任何贬低嘲讽之意, 也没刻意突出谁对谁错, 面试完了后我回去回想了下我的回答并找到些资料做出以下总结.
分布式
分布式计算是指系统的工作方式, 主要分为数据分布式和任务分布式:
数据分布式也称为数据并行, 把数据拆分后, 利用多台计算机并行执行多个相同任务. 优点是缩短所有任务总体执行时间, 缺点是无法减少单个任务的执行时间.
任务分布式也称为任务并行, 单个串行的任务拆分成多个可并行子任务. 优点是提高性能, 可扩展性, 可维护性, 缺点是增加设计复杂性.
负载均衡
负载均衡(Load Balance), 简称 LR, 就是将并发的用户请求通过规则后平衡, 分摊到多台服务器上进行执行, 以此达到压力分摊, 数据并行的效果.
集群
集群是系统在负载均衡结果后的物理表现, 系统 (服务) 通过部署到多台服务器以达到共同提供相同的功能, 可以称这一组服务为某某集群, 例如 Redis 集群, 某 web 站点集群.
负载均衡器
作用
负载均衡器的分类有很多, 而他们的作用主要体现于架构要素的其中三个: 可用性, 性能, 安全.
可用性, 多台服务器的部署避免了单点故障.
性能, 一台 Web 站点能提供每秒 4000 次的并发请求, 5 台服务器构成的一个集群就可以达到 20000.
安全, 通过反向代理到真实服务器, 避免直接路由到高危 Web 服务, 避免开放危险端口.
算法
常用的负载均衡算法主要以下 4 个:
加权轮询
随机
最少链接数
哈希
分类
从制造上主要分为软件负载和硬件负载:
软负载, 包含了 Nginx,LVS,HAProxy 等.
硬负载, 包含了 F5,Array 等.
从量级上主要分为: 百万级, 数十万级, 万级:
百万级, 硬负载, 例如 F5,Array.
数十万级, 第四层负载, LVS,HAProxy.
万级, 第七层负载, Nginx.
当然从成本上, 硬负载绝对是土豪公司的工具, 便宜的十来万 RMB, 贵则上百万 RMB. 而软负载只需要一台 Linux 服务器的钱就足够了. 此外 LVS 的部署复杂度相比于 Nginx 会高那么一点, 但是 Nginx 的七层负载的灵活性是四层负载的无法比拟的.
在实际工作中大家更多会接触到上图的架构模型, 从功能职责上又可以划分地域级, 集群级和应用级的负载:
地域级的负载均衡使用的是 DNS 的智能解析来完成的, DNS 全称 Domain Name System, 中文叫域名系统 (服务) 协议, 一般都会采用云服务厂商的 DNS 系统, 我们知道域名是需要花钱购买的, 而厂商会附带一个免费的域名解析套餐, 如果需要对域名进行域名智能解析, 就需要付费给厂商获取相应的服务.
Nginx 作为应用级负载也有自己的并发处理上限, 如果超过上限了那么只能通过再上一层加一个更高处理性能的负载均衡器作为解决, 而 LVS 可以很好担任集群级的负载重任. 如果是土豪公司可以在自己选择使用硬负载来代替 LVS, 硬负载虽然贵也有自己的优势, 例如防火墙, 加密, 高性能处理等.
Nginx
Nginx 是一个高性能的反向代理服务器, 也是稳定且高效的基于七层的负载均衡器. Nginx 可以根据以随机, 加权轮询, IP 哈希, URL 哈希等方式调度后端真是服务器, Nginx 也支持对后端服务器的健康检查功能.
LVS
LVS 即 Linux Virtual Server, 翻译中文为 Linux 虚拟服务器, 目前 LVS 是已经被集成到 Linux 内核模块中, LVS 的工作模式分为 NAT 模式, TUN 模式以及 DR 模式. 那么在实战中, 更多会 Keepalived + LVS 一起集成使用, Keepalived 可以自动将 LVS 备用调度器升级为主调度器, 最终实现整个集群系统的高负载, 高可用.
本篇的重点主要讲解 Keepalive + LVS + Nginx + .Net Core 的搭建与使用.
效果图
PS: 上图是我完成搭建后录制的视频转 gif, 因为中间有等待的一分钟, 为了观看效果剪断了.
Web1 与 Web2 是同一个 Nginx,Web3 和 Web4 是同为另外的一个 Nginx. 在图里可见需要过一段时间才能从一个 Nginx 切换到另外一个 Nginx, 原因主要是 LVS 会根据访问客户端的 IP + 端口在会话时间内重复的转发到同一个目标服务器. 而控制这个会话时间的可以通过设置 ipvsadm --persistent 与 --set 这两个参数决定.
LVS 的三种工作模式
NAT(Network Address Translation)- 网络地址转换模式.
首先, 外部请求会经过 LVS 的 VIP(Virtual IP Address); 接着, LVS 会根据预设的调度算法选择一台真实的服务器进行数据请求包转发, 转发前会把原数据包的目标地址与目标端口修改为真实服务器的地址与端口; 最后, LVS 在得到响应数据包后会把源地址与源端口改为 VIP 及调度器相应的端口. 因为由于所有的请求与响应都会经过 LVS 调度器转发, 因此容易成为集群的瓶颈.
TUN - 隧道模式
因为 NAT 会的瓶颈问题, 因此 TUN 模式采用用了请求与响应数据分离的思路, 让调度器仅处理数据请求, 让真实服务器响应数据包直接返回给客户端, 需要注意的是该模式下的真实服务器需要与外部网络连接. 另外 TUN 模式下需要在 LVS 调度器与真实服务器之间创建隧道连接, 同样会增加服务器的负担.
DR(Direct Routing)- 直接路由模式
DR 模式也是采用请求与响应分离的思路, 由真实服务器直接响应客户端, 但是它的报文转发方法有所不同, 在不修改数据报文的情况下, 将数据帧的 Mac 地址修改为需要转发到的真实服务器 Mac 地址, 免去了 TUN 中的 IP 隧道开销. 这种方式是三种负载调度机制中性能最高最好的, 但是 LVS 调度器与真实后端服务器必须在一个局域网内.
LVS 的部署
接下来的部署操作将实现上图 Keepalived + LVS +Nginx 的多层负载均衡, LVS 将是以 DR 模式实现.
两台 LVS 服务器(主从)
基础依赖安装
- yum install gcc
- yum -y install openssl-devel
- yum -y install libnl libnl-devel
- yum install -y libnfnetlink-devel
- yum -y install.NET-tools
- yum install VIM -y
安装 keepalived 和 ipvsadm
yum install -y keepalived ipvsadm
LVS-Master 服务器
修改 Keepalived 配置:
VIM /etc/keepalived/keepalived.conf
复制以下配置覆盖进去
注意: real_server 填写的是 Nginx 服务器的 IP 地址
- global_defs {
- router_id LVS_MASTER # 设置 lvs 的 id, 在一个网络内应该是唯一的
- }
- vrrp_instance VI_1 {
- state MASTER #指定 Keepalived 的角色, MASTER 为主, BACKUP 为备 记得大写
- interface ens33 #网卡 id 不同的电脑网卡 id 会有区别 可以使用: ip a 查看
- virtual_router_id 51 #虚拟路由编号, 主备要一致
- priority 100 #定义优先级, 数字越大, 优先级越高, 主 DR 必须大于备用 DR
- advert_int 1 #检查间隔, 默认为 1s
- authentication {
- auth_type PASS
- auth_pass 12345678
- }
- virtual_ipaddress {
- 192.168.174.128/24 #定义虚拟 IP(VIP)为 192.168.174.128, 可多设, 每行一个
- }
- }
- # 定义对外提供服务的 LVS 的 VIP 以及 port
- virtual_server 192.168.174.128 80 {
- delay_loop 6 # 设置健康检查时间, 单位是秒
- lb_algo rr # 设置负载调度的算法为 wlc
- lb_kind DR # 设置 LVS 实现负载的机制, 有 NAT,TUN,DR 三个模式
- nat_mask 255.255.255.0
- persistence_timeout 0
- protocol TCP
- real_server 192.168.88.137 80 {
- weight 1
- TCP_CHECK {
- connect_timeout 10
- nb_get_retry 3
- delay_before_retry 3
- connect_port 80
- }
- }
- real_server 192.168.88.139 80 {
- weight 1
- TCP_CHECK {
- connect_timeout 10
- nb_get_retry 3
- delay_before_retry 3
- connect_port 80
- }
- }
- }
LVS-BackUp 服务器
修改 Keepalived 配置:
VIM /etc/keepalived/keepalived.conf
复制以下配置覆盖进去
注意: real_server 填写的是 Nginx 服务器的 IP 地址, state 改为 BACKUP,priority 改为比 Master 小.
- global_defs {
- router_id LVS_SLAVE # 设置 lvs 的 id, 在一个网络内应该是唯一的
- }
- vrrp_instance VI_1 {
- state BACKUP #指定 Keepalived 的角色, MASTER 为主, BACKUP 为备 记得大写
- interface ens33 #网卡 id 不同的电脑网卡 id 会有区别 可以使用: ip a 查看
- virtual_router_id 51 #虚拟路由编号, 主备要一致
- priority 50 #定义优先级, 数字越大, 优先级越高, 主 DR 必须大于备用 DR
- advert_int 1 #检查间隔, 默认为 1s
- authentication {
- auth_type PASS
- auth_pass 12345678
- }
- virtual_ipaddress {
- 192.168.174.128/24 #定义虚拟 IP(VIP)为 192.168.174.128, 可多设, 每行一个
- }
- }
- # 定义对外提供服务的 LVS 的 VIP 以及 port
- virtual_server 192.168.174.128 80 {
- delay_loop 6 # 设置健康检查时间, 单位是秒
- lb_algo rr # 设置负载调度的算法为 wlc
- lb_kind DR # 设置 LVS 实现负载的机制, 有 NAT,TUN,DR 三个模式
- nat_mask 255.255.255.0
- persistence_timeout 0
- protocol TCP
- real_server 192.168.88.137 80 {
- weight 1
- TCP_CHECK {
- connect_timeout 10
- nb_get_retry 3
- delay_before_retry 3
- connect_port 80
- }
- }
- real_server 192.168.88.139 80 {
- weight 1
- TCP_CHECK {
- connect_timeout 10
- nb_get_retry 3
- delay_before_retry 3
- connect_port 80
- }
- }
- }
两台 Nginx 服务器
执行以下命令
VIM /etc/sysconfig/network-scripts/ifcfg-lo:0
填写以下配置并保存
- DEVICE=lo:0
- IPADDR=192.168.88.128
- NETMASK=255.255.255.255
- BROADCAST=192.168.88.128
- ONBOOT=yes
- NAME=lvs_vip
修改 ARP
VIM /etc/sysctl.conf
填写配置并保存
- net.ipv4.conf.all.arp_ignore = 1
- net.ipv4.conf.all.arp_announce = 2
- net.ipv4.conf.lo.arp_ignore = 1
- net.ipv4.conf.lo.arp_announce = 2
重启网卡
- sysctl -p
- systemctl restart network
那么以上关于 LVS 部分就搭建好了.
Nginx 的部署
在两台 Nginx 服务器都执行以下指令
添加源并安装
- rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
- yum install -y nginx
填写 Nginx 配置
把 http 里[# 开始] 到[# 结束] 这段拷贝进去就可以了.
- user nginx;
- worker_processes 1;
- error_log /var/log/nginx/error.log warn;
- pid /var/run/nginx.pid;
- events {
- worker_connections 1024;
- }
- http {
- #开始
- upstream 192.168.88.139{
- server localhost:5001 weight=1;
- server localhost:5002 weight=1;
- }
- server {
- listen 80;
- server_name 192.168.88.139;
- charset utf8;
- client_max_body_size 50m;
- client_body_buffer_size 256k;
- location / {
- proxy_pass http://192.168.88.139;
- proxy_set_header X-Forwarded-For $remote_addr;
- proxy_set_header Host $host;
- }
- }
- #结束
- }
设置开机启动
- systemctl start nginx.service
- systemctl enable nginx.service
重启防火墙
- firewall-cmd --permanent --zone=public --add-port=80/tcp
- firewall-cmd --reload
以上关于 Nginx 的部分就完成了搭建. 可以通过以下指令查看 LVS 的调度与连接信息.
查看 LVS 调度信息
ipvsadm -Ln
查看 LVS 连接信息
ipvsadm -Lnc
.Net Core 部署
添加下载源:
rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm
下载安装:
sudo yum install aspnetcore-runtime-2.2
通过 FTP 把 Web 站点文件复制两份并上传到服务器, 然后启动后台进程:
- nohup dotnet Test1.dll --server.urls "http://*:5001" &
- nohup dotnet Test1.dll --server.urls "http://*:5002" &
FTP 服务器的部署
安装 FTP 服务器:
yum install -y vsftpd
修改配置:
VIM /etc/vsftpd/vsftpd.conf
把已有的三项配置修改了:
- anonymous_enable=NO
- listen=YES
- #listen_ipv6=YES
启动
- systemctl start vsftpd
- systemctl enable vsftpd
重启防火墙
- firewall-cmd --permanent --zone=public --add-service=ftp
- firewall-cmd --reload
允许 root 登录, 把以下两个文件的 root 注释了
- VIM /etc/vsftpd/user_list
- VIM /etc/vsftpd/ftpusers
- #root
关掉 selinux, 会影响上传
- setenforce 0
- VIM /etc/selinux/config
- # 将 SELINUX=enforcing 改为 SELINUX=permissive
FTP 客户端 - FileZilla 下载地址
结束
以上为本篇的所有内容了, 负载均衡在实际工作中涉及的地方挺多的, 因此我将分为上下两篇, 该篇为负载均衡的上篇主要从大方向 DNS,LVS,Nginx 进行了分享, 下篇会从微服务架构里使用到的组件 API 网关和注册中心进行探讨, 如果大家在实践上遇到任何问题, 或者有更好的建议可以到评论反馈给我.
.Net 微服务实战之负载均衡(上)
来源: http://www.bubuko.com/infodetail-3641537.html