0%

本文是结合写于2015年的博客jenkins源码分析获取脉络,结合自己的研究完成,较原文有所拓展和深入。

jenkins框架

architecture_jenkins

jenkins的Model对象

jenkin(实际是传承Hudson的)Model对象jenkin平台的基石,它们hold住了某一个(job、project、executor、user、buildable item、test result)的数据和状态。

每个Model对象可以和多个views绑定,view使用了Jelly来渲染HTML和对象。

Model的可执行性是通过绑定Actions对象到Model。

Model如是描述对象存在时,是通过绑定Descriptor对象到Model。

每个Model对象和一个URL对象绑定。
Stapler通过类似JSF表达式的方式来解决URL和Model Object的绑定问题。Stapler同时处理一个model和URL,然后根据object计算URL,一直重复这个动作,直到命中某个静态资源、可执行方法、视图(jsp、jelly、groovy等)。

命中可执行方法举例:

1
2
3
4
5
6
Scenario: browser sends "POST /project/jaxb/testResult HTTP/1.1"

evaluate(<root object>, "/project/jaxb/testResult")
-> evaluate(<root object>.getProject("jaxb"), "/testResult")
-> evaluate(<jaxb project object>, "/testResult")
-> evaluate(<jaxb project object>.getTestResult())

命中视图举例:

1
2
3
org.jvnet.hudson.project.testResul -> /org/jvnet/hudson/project/testResult/index.jelly

命中之后,response.forward(this,"/org/jvnet/hudson/project/testResult/index.jelly",request)

jenkins用了stapler

阅读全文 »

将之前写过的一个小工具做了一些优化,开源出来。起了个没有任何意义的ppter。

ppter概述

为什么叫ppter

任性,没有意义,听着挺好听,嗯就这样。

项目地址: https://github.com/windanchaos/ppter

可用场景

多地办公,没有固定IP,需办公区对办公区建立VPN,办公区和阿里云建立VPN的场景。

能节省的费用就是两条固定IP的费用。拒我了解的一个固定IP的电信一年30万左右,移动的要10来万。对于小公司来说,一年还是能节约不少钱了。

市面上的其他解决方案,我并不太清楚,如果有更优的免费方案,欢迎告知。

文件说明

  • aliapi.py 阿里云部分产品api的封装
  • ConfigProvider.py 配置相关,读取config.ini转成需要的数据类型
  • Jobs.py 运行的进程
  • Dockerfile docker image镜像构建文件
  • requirement 项目依赖
  • config.ini 配置相关
  • getDnsInfo.py 获取域名解析信息工具
  • ppter_vpn.py vpn相关代码
  • ppter_vps.py vps相关代码
  • ppter_dns.py dns解析相关

    工作原理

    使用独立于办公区内部环境的阿里云(或其他共有云),部署redis作为ip交换媒介。
    clip_image001

前置动作

  • 修改正确的config.ini
  • 修改正确vpn配置

具体参考下文

容器安装

docker的安装和配置优化

其中user是可以操作docker的普通账户,换成自己的即可

script
1
2
<!-- more -->
bash installDocker.sh user

监控程序启动操作

1
2
3
4
# 镜像打包
docker build -t dns_monitor .
# 启动容器进程
docker run -it -d -v `pwd`/config.ini:/root/config.ini --name monitor dns_monitor

直接安装

使用的python3。

依赖安装

1
sudo pip3 install redis request configparser base64

执行

不同环境独立执行:

1
nohup python3 Jobs.py > log.log &

程序会做以下动作:

  • 5分钟定时获取一次外网IP地址,并同步到redis上
  • 对比IP地址是否有变化,有就执行dns解析、阿里云ipes、本地路由vpn配置变更。ip地址包括本地ip变化和连接端的ip变动。A和B的IP任意变动都会触发本地路由vpn配置。

启动前需要修改的配置

config.ini的文件内容,大部分顾名思义。

Credentials

需要配置具有阿里云vps 、dns操作权限的id和secret。

域名解析的配置

[dns] 下的domain设置

  • 一个{’RecordId’:’xxx’,’RR’:’record’}就是一条记录

  • 用’|’符号作分隔符。多条记录:{’RecordId’:’4154842768102400’,’RR’:’recordA’}|{’RecordId’:’4154842768102400’,’RR’:’recordB’}

    其中RR标识map.baidu.com 中的map。

  • 按规则添加即可,删除也是

如何获取domain的recordId和RR(主机记录)?

1
python3 getDnsInfo.py

执行后会打印‘baidu.com’的所有解析信息。复制粘贴到json在线解析,找到需要的解析信息。

如果要换域名就修改getDnsInfo.py的内容。

vpn的设置

前三个参数是路由器的登录地址和账户密码。

redisLocalVpnName 是redis中IP地址的本地标识。

redisRemoteVpnName 是vpn连接远端的标识。

A、B环境的名字需要互换。

A环境的配置:

1
2
redisLocalVpnName = A
redisRemoteVpnName = B

B环境的配置:

1
2
redisLocalVpnName = B
redisRemoteVpnName = A

vpn 的配置数据这里没有做到配置文件中,在updata_vpn.py中修改vpn_data,默认vpn-config[0]是对阿里云的vpn设置。vpn-config[1:]之后的是本地对本地的设置。
这类数据可能不同路由器,值是不一样的。需要自己去抓包了解一下了。

VPS设置

不同环境名字区别开即可。

详细的配置在update_vps.py中,主要修改CreateVpnConnection参数。

1
2
3
4
5
6
CreateVpnConnection = {'Action': 'CreateVpnConnection', 'RegionId': 'cn-hangzhou',
'VpnGatewayId': 'XXXXXXX', \
'LocalSubnet': '172.16.128.0/20', 'RemoteSubnet': '10.189.51.0/24',
'IpsecConfig':str({'IpsecAuthAlg':'sha1'}),
'IkeConfig': str({'Psk': 'XXXXXXX','IkeAuthAlg': 'sha1'}), 'CustomerGatewayId': '', 'Name': ''}

网关的名字是设置的name取第二个字符(不含)之后的字符,比如现在name为tohzh,则对应网关名hzh。

Psk 要设置成自己定义的值。

特别注意,用户网关如果没有和ipsce关联,就不要提前设置,否则无法新建。

开源小总结

1、requests类库是个优秀的开发语言级别的“浏览器”库,基本上不用费神去操作cookies之类的,畅快的request就好;

2、程序持续运行,异常抛出后继续运行的机制设置对程序进程稳定性很重要,异常抛出一般接不住就用所有异常类父类:BaseException

3、学会了一项新的技能,在服务器上控制台上做调试。可参考这篇文章

1
python3 -m pdb test.py

如果要简单说,下面wsn三个我用了比较实用。我在码代码过程中,遇到一个问题,始终不知道为什么在服务器上运行失败,而本地是ok的。调试后发现是配置文件没有换(服务器上是请求url有单引号,解析不出来)
w:(where)打印当前执行堆栈

s:(step)执行下一条命令

n:(next)执行下一条语句

4、docker是个好东西

5、扒拉一个系统的运行过程,才能结合自己的需求去做优化和修改。

目的

作为使用第三方(阿里云)的我司来说,我个人觉得很多钱是浪费了。在知乎上有人讨论自建和上云哪个省钱,其实还是要看在公有云上怎么用,公有云很多资源具有召之即来挥之即去的特性,实际上是可以最大限度的去压榨的。做容量规划的目的,很简单,向规划要资源利用率、投入产出比,算的是笔经济账。对个人而言,替公司节约几十甚至上百万的费用,这种贡献自然会得到丰厚的回报。对企业而言,节约了费用和开支,资源可以使用到其他地方,继而可以提高竞争力。所以,容量规划是必须而且重要的。

容量规划步骤

我个人构思的步骤有如下,虽不成熟,但是独立思考所得。容量规划有个前置条件,即系统的性能瓶颈已经或者大部分都被识别,在做规划的时候尽量保守一些。大致步骤和关键点:

  • 确定系统资源消耗类型(计算密集耗cpu、数据密集吃内存、网络或读写密集吃io),掌握系统在某资源配置情况下,能够支持的并发数。建立各系统的并发模型。
  • 掌握系统当前线上环境日常流量特征,并基于该特征制定一个流量模型。
  • 基于流量模型定制一个资源的基准水位,以达到支持日常访问较合理的资源利用率。
  • 核心服务的流量监控报警方案及自动扩容、缩容方案。

系统并发压测方案

采集线上流量特征,建立流量模型、生成压测模型;

笔者是电商行业,所以对于高频的营销工具也需要单独压测,比如拼团购、限时折扣、拉人应用等。这些工具都是高并发、突发性流量的主要来源。

资源利用率的判定

理论上,在系统不崩溃、响应正常的前提下,资源利用率的平均值在80-90%,是最优的利用率,它最大限度的压榨了机器的价值。但是很明显,人工构建的系统,想要达到这种级别的利用率而系统一切ok的话,可能要投入更多的研发资源来优化,对于中小企业来说,可能就有点缘木求鱼了,毕竟业务才是王道。退而求其次的话,资源利用率降低一个档次,在60-80%,就是一个比较合理的利用率(压榨)了。

利用率% 级别 措施
[0,30] 闲置 缩容减支
[30,50] 适当 观察
[50,70] 合理 观察
[70,90] 充分 警觉和扩容
[90,100] 过量 必须扩容

监控方案

监控指标的确定:

  • TCP连接指标
  • 内存使用率指标
  • cpu使用率指标
  • 磁盘IO指标
  • db的监控指标系列
阅读全文 »

出发点

最近,在构思一套内部环境服务的监控系统,起码的功能是能识别到业务进程异常(进程级别的),退出后自动拉起。
找到了supervisor,了解基本功能后,觉得它在分布式方面还存在不足之处,所有配置分散在单机上。鉴于它的技术符合目前需要练习python技术栈。所以,准备对其源代码进行解构、分析和学习。

概览

源码研究和学习,起码要对该工具如何使用有个基本的掌握。

Supervisor是用Python开发的一套通用的进程管理程序,能将一个普通的命令行进程变为后台daemon,并监控进程状态,异常退出时能自动重启。它是通过fork/exec的方式把这些被管理的进程当作supervisor的子进程来启动,这样只要在supervisor的配置文件中,把要管理的进程的可执行文件的路径写进去即可。也实现当子进程挂掉的时候,父进程可以准确获取子进程挂掉的信息的,可以选择是否自己启动和报警。supervisor还提供了一个功能,可以为supervisord或者每个子进程,设置一个非root的user,这个user就可以管理它对应的进程。

medusa

它依赖第三方的medusa来处理网络请求。medusa的源码也值得学习和研究。

supervisord

类似于docker所在服务器运行的守护进程,负责响应客户端的命令行、受监控进程的监控、重启、受控子进程的标准输入输出的日志、生成和处理与子流程生命周期中相对应的“事件”。配置文件一般为/etc/supervisord.conf。

supervisorctl

控制台,和supervisord交互。通过控制台,用户可以连接到不同的supervisord进程( 通过UNIX domain socket or an internet (TCP) socket),查看supervisord的控制进程的状态。读取/etc/supervisord.conf下的[supervisorctl]内容作为配置。

Web Server

supervisord的浏览器控制台。仅支持单机模式,就是说,N台服务器安装了supervisor的话,就有N个webServer,它们彼此之间并没有关联,所以也没有一个集中化的界面统一管理。

有个php的解决方案:https://blog.csdn.net/geerniya/article/details/80107761

XML-RPC Interface

The same HTTP server which serves the web UI serves up an XML-RPC interface that can be used to interrogate and control supervisor and the programs it runs.

不足

优点:
- 可以将非后台运行程序后台运行
- 自动监控,重启进程

缺点:
- 不能管理后台运行程序
- 对多进程服务,不能使用kill关闭

源码分析

源码分析步骤:

1、clone代码到本地;

2、本地做supervisord的配置

3、参考别写的源码文章,找到程序入口,阅读代码

4、debug若干次,追中代码运行逻辑

阅读全文 »

这篇文章是研习supervisor源代码的副产品,主要理解supervisor的驱动原理和操作系统对进程管理的一些基本知识。

理解什么是进程

百度百科定义如下:进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。

进程是操作系统对资源的一个抽象。
操作系统是计算机的管家,掌控着计算机内部的一切资源的分配、调度、回收。
而进程可以理解为计算机资源调度的一个基本单元。用播放电影来举个形象的例子,进程就是电影一针一针的画面,而程序就是播放这部电影的一个统称,电影没开始播放前,得准备放映机(cpu),电影胶片(内存)。放音机齿轮转动就好比cpu的时钟脉冲,每秒扫过N个胶片(进程被调度),图像被光打到幕布上(计算机的输出设备)。

换一个角度看操作系统的进程,linux系统开机启动到系统启动完毕,从进程的角度看就是一生二、二生三、三生万物的感觉。我们面对的就是进程的一课大树,它的源头就是进程号为1(名叫systemd)的进程,systemd是Linux下的一种负责init的进程,那字母d就是daemon的标记,又比如apache的http服务,它的进程也有个字母d,httpd。可以运行pstree命令来体验一下这种子子孙孙无穷匮也。ps和systemctl命令也有类似效果。

1
2
3
pstree
ps axjf
systemctl status

进程运行环境

在Linux中,用户程序装入系统形成一个进程的实质是操作系统为用户程序提供一个完整的运行环境。进程的运行环境是由它的程序代码和程序运行所需要的数据结构以及硬件环境组成的。进程的运行环境主要包括:

  • 1.进程空间(内存)中的代码和数据、各种数据结构、进程堆栈和共享内存区等。

  • 2.环境变量:提供进程运行所需的环境信息。

  • 3.系统数据:进程空间中的对进程进行管理和控制所需的信息,包括进程任务结构体以及内核堆栈等。

  • 4.进程访问设备或者文件时的权限。

  • 5.各种硬件寄存器。

  • 6.地址转换信息。

    Linux下的进程模型

    从PCB中了解进程模型

    一个进程在操作系统中执行,有两种状态:内核态和用户态。如果当前运行的是用户程序(用户代码),那么对应进程就处于用户),如果出现系统调用或者发生中断,那么对应进程就处于内核模式(核心态)。

为了描述控制进程的运行,系统中存放进程的管理和控制信息的数据结构称为进程控制块 PCB(Process Control Block),它是进程实体的一部分,是操作系统中最重要的记录性数据结构。它是进程管理和控制的最重要的数据结构,每一个进程均有一个 PCB,在创建进程时,建立 PCB,伴随进程运行的全过程,直到进程撤消而撤消。PCB 记录了操作系统所需的,用于描述进程的当前情况以及控制进程运行的全部信息(如打开的文件、挂起的信号、进程状态、地址空间等等)。在linux中这个PCB是一个叫做task_struct的结构体。

task_struct 在linux中,每一个进程都有一个进程描述符,这个”进程描述符”是一个结构体名字叫做task_struct,在task_struct里面保存了许多关于进程控制的信息。

task_struct是Linux内核的一种数据结构,它会被装载到RAM里并包含进程的信息。

每个进程都把它的信息放在task_struct这个数据结构里面,而task_struct包含以下内容:

进程状态(State)

表示进程的状态, 在进程执行的时候,它会有一个状态,这个状态对于进程来说是很重要的一个属性。包括:可运行、可中断的等待状态、不可中断的等待状态、将死、暂停、换入/换出。

阅读全文 »

最近在刷leetcode算法的入门题,刷到二叉树,一开始浑浑噩噩,后来掌握了套路,自己搞定一个,而且很优雅,比留言中的大部分都优雅,嗯,写个日志自嗨一把。
所有刷题都提交到我的github上了,具体位置:windanchaos的github

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
题目要求:
将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。

本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1

示例:

给定有序数组: [-10,-3,0,5,9],

一个可能的答案是:[0,-3,9,-10,null,5],它可以表示下面这个高度平衡二叉搜索树:

0
/ \
-3 9
/ /
-10 5

来源:力扣(LeetCode
链接:https://leetcode-cn.com/problems/convert-sorted-array-to-binary-search-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

我的解法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
<!-- more -->
/*
执行用时 :1 ms, 在所有 Java 提交中击败了99.76%的用户
内存消耗 :37.2 MB, 在所有 Java 提交中击败了97.44%的用户
*/
class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
if(nums.length==0 || null == nums) return null;
//只有一个元素的情况
if(nums.length==1) return new TreeNode(nums[0]);
//数量大于1,构建节点
TreeNode root=new TreeNode(nums[nums.length/2]);
//构建左右子树
root.left=sortedArrayToBST(Arrays.copyOfRange(nums,0,nums.length/2));
root.right=sortedArrayToBST(Arrays.copyOfRange(nums,nums.length/2+1,nums.length));
return root;
}
}

最近在看一本讲数据库架构的英文书,书中很多次提及到一个叫缓存的词语,在我们商城的业务系统中也经常听到缓存这个词语。于是百度找到这篇文章。内心觉得总结很到位。转自:缓存技术原理

一、前言

应用中使用缓存技术,往往可以大大减少计算量,有效提升响应速度,让有限的资源服务更多的用户。但是,似乎还没有一种缓存方案可以满足所有的业务场景,我们需要根据自身的特殊场景和背景,选择最适合的缓存方案,尽量以最小的成本最快的效率达到最优的目的。本文将从多个方面对缓存进行分析,以便作为选择缓存方案的考量。
二、文章要点

三、缓存的理解 3.1 狭义的理解

缓存指的是 CPU 缓存,当 CPU 要读取一个数据时,首先从 CPU 缓存中查找,找到就立即读取并送给 CPU 处理;没有找到,就从速率相对较慢的内存中读取并送给 CPU 处理,同时把这个数据所在的数据块调入缓存中,可以使得以后对整块数据的读取都从缓存中进行,不必再调用内存。

3.2 广义的理解

凡是位于速度相差较大的两种硬件/软件之间的,用于协调两者数据传输速度差异的结构,均可称之为缓存。

3.3 缓存的优点

如下,一个 Web 应用架构一般有如下几层:

在此架构的不同层级之间,都可以存在缓存。比如:

总结来说,缓存在如下三个方面做了提升:

四、CPU 缓存简介

CPU 缓存(Cache Memory)是位于 CPU与 内存之间的临时存储器,它的容量比内存小的多,但是交换速率却比内存要快得多。缓存的出现主要是为了解决 CPU 运算速率与内存读写速率不匹配的矛盾,因为 CPU 运算速率要比内存读写速率快很多,这样会使 CPU 花费很长时间等待数据到来或把数据写入内存。在缓存中的数据是内存中的一小部分,但这一小部分是短时间内 CPU 即将访问的,当 CPU 调用大量数据时,就可避开内存直接从缓存中调用,从而加快读取速率。由此可见,在 CPU 中加入缓存是一种高效的解决方案,这样整个内存储器(缓存+内存)就变成了既有缓存的高速率,又有内存的大容量的存储系统了。 缓存基本上都是采用 SRAM 存储器,存储器在计算机内部的组织方式如下图所示:

越往上,存储器的容量越小、成本越高、速度越快。由于 CPU 和主存之间巨大的速度差异,系统设计者被迫在 CPU 寄存器和主存之间插入了一个小的 SRAM 高速缓存存储器称为 L1 缓存,大约可以在 2-4 个时钟周期(计算机中最小的时间单位)内访问。再后来发现 L1 高速缓存和主存之间还是有较大差距,又在 L1 高速缓存和主存之间插入了 L2 缓存,大约可以在 10 个时钟周期内访问。后面还新增了 L3 等,于是,在这样的模式下,在不断的演变中形成了现在的存储体系。
五、分布式缓存原理 5.1 本地缓存

本地缓存可能是大家用的最多的一种缓存方式了,如 Ehcache、Guava Cache 等,它是在应用中的缓存组件,其最大的优点是应用和 cache 是在同一个进程内部,请求缓存非常快速,没有过多的网络开销等,在单应用不需要集群支持或者集群情况下各节点无需互相通知的场景下使用本地缓存较合适; 同时,它的缺点也是因为缓存跟应用程序耦合,多个应用程序无法直接的共享缓存,各应用或集群的各节点都需要维护自己的单独缓存,对内存是一种浪费。

5.2 分布式缓存特性

阅读全文 »

问题描述:
我们的tomcat启动了apr启动https端口,我设置了systemd的tomcat.service的文件,使用systemctl start tomcat,始终无法识别apr的环境变量。研究了一会后解决。
先贴tomcat.service最终设置,只需加一行配置即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[Unit]
Description=java tomcat project
After=syslog.target network.target

[Service]
Type=forking
User=user
Group=user
EnvironmentFile=/opt/apache-tomcat/bin/config
ExecStart=/opt/apache-tomcat/bin/startup.sh
ExecReload=
ExecStop=/arthas/servers/apache-tomcat-8.5.4-80/bin/shutdown.sh
PrivateTmp=true

[Install]
WantedBy=multi-user.target

关键点:

EnvironmentFile=/opt/apache-tomcat/bin/config 的设置。
文件内容如下,是启动tomcat的环境变量:

1
LD_LIBRARY_PATH=/usr/local/apr/lib:$LD_LIBRARY_PATH

原理:
1、/etc/profile或者/etc/security/limit.d这些文件中配置的环境变量仅对通过pam登录的用户生效,而systemd是不读这些配置的,所以这就造成登录到终端时查看环境变量和手动启动应用都一切正常,但是systemd无法正常启动应用。
2、EnvironmentFile:该字段指定软件自己的环境参数。

参考:
https://blog.csdn.net/lizao2/article/details/81030380
https://www.cnblogs.com/jhxxb/p/10654554.html

阅读全文 »

git在维护版本库的时候统一使用的是LF,这样就可以保证文件跨平台的时候保持一致。
在Linux下默认的换行符也是LF,那也就不存在什么问题。
在Windows下默认的换行符是CRLF,那么我们需要保证在文件提交到版本库的时候文件的换行符是LF,通常来说有两种方法:

1
2
3
4
5
6
# 在工作区使用CRLF,使用git commit提交的时候git帮你把所有的CRLF转换为LF
git config --global core.autocrlf true
# 在工作区使用LF
git config --global core.autocrlf input
# 避免文件中有混用换行符
git config --global core.safecrlf true

以上措施如果都不管用,尤其是莫名其妙的,git刚刚clone的代码库就存在图片换行符的问题,比如我的。
刚clone的代码库就存在换行符导致的问题
那么你可以试试——————————————————————————升级你的git,是的,所有设置方案都试过后,这一招彻底解决。

这里下载:https://github.com/git/git/releases?after=v2.21.0-rc1

1
2
3
4
5
6
7
8
9
10
11
12
# centos自带Git7.x版本自带git 1.8.3.1,安装新版本之前需要使用卸载。
yum remove -y git
# 依赖
yum install -y curl-devel expat-devel gettext-devel openssl-devel zlib-devel gcc perl-ExtUtils-MakeMaker
wget https://github.com/git/git/archive/v2.20.0.tar.gz
tar xzf v2.20.0.tar.gz
cd git-2.22.0
make prefix=/usr/local/git all
make prefix=/usr/local/git install
# 创建软连接
ln -s /usr/local/git/bin/git /usr/bin/git
git --version

最近在践行代码,先把尚学堂的习题做完,遇到有点代表的就发个日志。
以下算法时间复杂度为N,还可以。这个好像是用了某种算法,具体叫动态规划法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*
103. 【上机】编程求:∑1+∑2+……+∑100
这里输入最大数100作为参数
*/
public void sigma(int num){
//利用数组记录∑n的值,数组的index=n,特征:∑n=∑(n-1)+n
//数组下标等于数字,数组index为0的丢弃
int[] array_tmp=new int[num+1];
int sum=0;
for(int i=1;i<num+1;i++){
//数组index为0时,默认值0,可直接迭代
array_tmp[i]=array_tmp[i-1]+i;
sum=sum+array_tmp[i];
}
System.out.println("∑1+∑2+……+∑"+num+"的和为:"+sum);
}

∑1+∑2+……+∑100的和为:171700